IL-0050 Toyota Connected · 2018-11-05 (게시일)kubernetesnetworking
팀의 Redis 의존 라이브러리를 쓰는 쿠버네티스 서비스들이 클러스터 밖 Redis 호스트 이름을 반복해서 해석하지 못했다. 원인을 찾고 조치하기까지 꼬박 하루가 걸렸다. 글쓴이는 자신의 운영 경험이 부족했고 헛짚은 단서가 여럿 있어서 조사가 길어졌다고 적었다.
파드의 resolv.conf 는 ndots:5 였다. Redis 호스트 이름에는 점이 네 개뿐이어서 리졸버는 이 이름에 검색 도메인을 먼저 붙여 조회했다. 이미지가 쓰던 Alpine 의 musl 리졸버에는 첫 네임서버 응답이 NXDOMAIN 이면 심각한 문제가 생길 수 있다는 주의 사항이 있다. 여기에 Netty 4.1.30 의 DNS 리졸버도 기대대로 동작하지 않았다. 글쓴이는 ndots 가 이 문제들을 한꺼번에 터뜨린 계기였다고 결론지었다.
끝에 점을 붙이는 우회책도 통하지 않았다. 이 Netty 버전은 호스트 이름 끝의 점을 허용하지 않았다. 조사 중에는 Redis 연결 수가 사용률 95% 가까이 올라 있는 것도 보였다. 라이브러리가 최대 연결 풀 크기를 잘못 설정하고 있었기 때문이다. 팀은 라이브러리 새 버전으로 이를 고쳐 연결 수를 약 70% 줄였다.
팀은 배포 매니페스트의 dnsConfig 로 ndots 를 4 로 낮춰 대부분 서비스를 되살렸다. 내부 서비스 디스커버리를 쓰지 않았기 때문에 ndots 를 낮추는 위험은 받아들일 만했다. 다른 팀에도 경우에 따라 ndots 를 4 로 설정해야 할 수 있다고 알렸다. 이 우회책 뒤에도 DNS 해석 오류는 가끔 났다.
팀의 Redis 의존 라이브러리를 쓰는 서비스들이 시작하자마자 죽는다는 보고가 운영 담당자에게 들어왔다. Spring Boot 로그를 보니 빈 초기화 중에 Redis 호스트 이름을 해석하지 못하고 있었다.
팀은 처음에 서비스가 쓰던 Azure Redis Cache 가 출처를 알 수 없는 인스턴스라는 것을 발견했다. 설정 저장소의 URI 를 정상 Redis Cache 인스턴스로 바꾸고 의존 서비스를 재시작했다. 먼저 재시작한 서비스가 정상으로 보여서 팀은 문제가 풀렸다고 판단했다.
며칠 뒤 Kibana 에 호스트 이름 해석 실패가 다시 보였다. 팀은 클러스터 DNS 를 의심해 Redis 연결 URI 끝에 점을 붙여 FQDN 으로 조회하게 했다. dev 환경에서 실패가 줄자 나머지 환경에도 반영했다. 하지만 PR 을 머지한 다음 날 DNS 해석 실패가 또 늘었고, 결국 정식 장애가 됐다.
팀이 직접 띄운 Busybox 로 같은 Redis 호스트 이름을 조회하면 문제없이 해석됐다. 파드의 /etc/resolv.conf 에는 nameserver 10.10.10.10, search ns.svc.cluster.local svc.cluster.local cluster.local, options ndots:5 가 들어 있었다. 조사하는 동안 Redis 연결 수가 사용률 95% 가까이 올라 있는 것도 보였다. 스택 트레이스 깊숙한 곳에서는 Server name value of host_name cannot have the trailing dot 오류가 나왔다.
원인 ? 소프트웨어 결함
Redis 의존 라이브러리를 쓰는 서비스 팀들이 시작 중에 서비스가 죽는다고 운영 담당자에게 보고하면서 문제가 처음 드러났다. 문제가 다시 나타났을 때는 팀이 Kibana 에서 호스트 이름 해석 실패를 보고 알았다.
쿠버네티스 기본값 ndots:5 에서는 리졸버가 점이 다섯 개보다 적은 외부 호스트 이름에 검색 도메인을 먼저 붙여 조회한다. 이 동작이 musl 리졸버의 NXDOMAIN 처리나 라이브러리의 DNS 리졸버 결함과 만나면 간헐적인 해석 실패가 된다. ndots 를 낮추면 대부분 서비스가 살아나지만 오래가는 해법은 아니다. 글쓴이는 이런 실패를 잡는 알림을 원했지만, 한 번씩 나는 DNS 실패마다 울리는 알림은 원하지 않는다고 했다.
–