{"id":"IL-0047","org":"MindTickle","date":"2019-08-05","docs":["https://www.weave.works/blog/racy-conntrack-and-dns-lookup-timeouts","https://blog.quentin-machu.fr/2018/06/24/5-15s-dns-lookups-on-kubernetes/"],"title":{"en":"Pod-to-pod requests delayed by 5, 10 or 15 seconds because of DNS lookups lost to a conntrack race","ko":"conntrack 경합으로 DNS 조회가 5초씩 늦어져 파드 사이 요청이 간헐적으로 5초, 10초, 15초씩 지연되었다."},"domain":["kubernetes","networking"],"impact":{"scope":"pod-to-pod communication and the overall responsiveness of the web application","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"Delays that are exact multiples of five seconds point to DNS lookups being retried after the resolver's 5-second timeout. A resolver option set in the pod spec only helps processes that use the libc resolver; runtimes with their own resolver, such as gRPC with c-ares, ignore it.","ko":"지연이 5초, 10초, 15초처럼 5초의 배수로 나타나면 DNS 조회 재시도를 먼저 의심한다. 리눅스 이미지는 파드 dnsConfig 에 single-request-reopen 을 넣으면 된다. gRPC 는 기본 리졸버가 libc 를 쓰지 않을 수 있으므로 GRPC_DNS_RESOLVER=native 도 함께 설정해야 한다. 설정이 먹었는지는 tcpdump 로 A 와 AAAA 조회가 나가는 포트를 보고 확인한다."},"related":[],"sources":[{"url":"https://medium.com/techmindtickle/intermittent-delays-in-kubernetes-e9de8239e2fa","kind":"blog","license":"unknown","archived":"https://web.archive.org/web/20241202203357/https://medium.com/techmindtickle/intermittent-delays-in-kubernetes-e9de8239e2fa"}],"summary":{"en":"MindTickle had moved most of its production workload to Kubernetes. After an earlier cluster-wide network failure that forced the team to build a new cluster and migrate every application, the team studied Kubernetes networking in depth, and in that period noticed intermittent delays in pod-to-pod calls. Because every delay was a multiple of five seconds, the team found that DNS lookups were the cause. The resolver in the C library (libc, or musl on Alpine) sends the A (IPv4) and AAAA (IPv6) queries on the same port; a race condition in conntrack, which shows up where DNAT or SNAT translation happens, sometimes loses one of them, and the resolver treats the whole lookup as timed out and retries after 5 seconds.\n\nAdding the resolver option single-request-reopen to the pods' dnsConfig made the resolver use a different socket for the second query, and tcpdump confirmed the A and AAAA queries now left from different ports. The delays disappeared for ordinary Linux images. gRPC services still hit DEADLINE_EXCEEDED, and tcpdump showed their A and AAAA queries still sharing a port: gRPC uses its own c-ares resolver when it is available, so the libc option had no effect. Setting GRPC_DNS_RESOLVER=native in the Dockerfiles made gRPC use the system resolver, and the problem was gone there too. Alpine images were left unchanged because most of the applications use other Linux images.","ko":"MindTickle 은 운영 워크로드 대부분을 쿠버네티스로 옮긴 뒤 클러스터 전체의 네트워크 스택이 내려가는 장애를 겪었고, 새 클러스터를 만들어 모든 애플리케이션을 옮겨야 했다. 그 뒤 쿠버네티스 네트워킹을 깊이 파던 중 파드 사이 통신이 5초의 배수만큼 간헐적으로 늦어지는 문제를 발견했다.\n\n지연의 원인은 DNS 조회였다. 리눅스의 libc 는 A 레코드와 AAAA 레코드 조회를 같은 포트로 보낸다. A 레코드 응답은 바로 오지만 AAAA 레코드 조회가 타임아웃되면, libc 는 조회 전체가 실패했다고 보고 5초 기다렸다가 다시 시도한다. 원문은 이 현상이 DNAT 나 SNAT 변환이 일어나는 커널에서 흔하고, conntrack 의 경합 조건 때문에 생긴다고 설명한다.\n\n팀은 파드 DNS 설정에 single-request-reopen 옵션을 넣어 A 와 AAAA 조회가 서로 다른 포트로 나가게 했고, 지연이 사라졌다. gRPC 애플리케이션에서는 그 뒤에도 DEADLINE_EXCEEDED 오류가 났다. gRPC 의 기본 DNS 리졸버가 libc 가 아니라 ares 여서 이 설정이 먹지 않았기 때문이다. Dockerfile 에 GRPC_DNS_RESOLVER=native 를 넣어 libc 리졸버를 쓰게 하자 문제가 풀렸다. 대부분의 애플리케이션이 Alpine 이미지를 쓰지 않아서 Alpine 쪽은 손대지 않았다."},"trigger":{"en":"The C library resolver sent the A and AAAA queries for each lookup on the same port; where DNAT or SNAT translation takes place, a race condition in conntrack sometimes left one of the queries unanswered, and the resolver waited 5 seconds before retrying.","ko":"libc 리졸버가 A 레코드와 AAAA 레코드 조회를 같은 포트로 보냈고, DNAT 와 SNAT 변환이 일어나는 경로에서 conntrack 경합 조건 때문에 그중 하나가 응답을 받지 못했다."},"severity":"unknown","symptoms":["intermittent-timeouts","high-latency","dns-resolution-failures"],"timeline":{"detected_after":null,"resolved_after":null},"date_kind":"published","detection":{"en":"The team noticed intermittent delays in pod-to-pod calls and slowness in the web application, and that the delays were always multiples of five seconds.","ko":"웹 애플리케이션이 간헐적으로 느려지고 파드 사이 요청이 5초의 배수만큼 늦게 도착하는 것을 보고 알았다. 지연이 5초 단위라는 점에서 DNS 조회를 의심했고, tcpdump 로 확인했다."},"components":["conntrack","dns-resolver","linux-kernel"],"root_cause":"dns-network","remediation":[{"text":{"en":"added the single-request-reopen option to dnsConfig in the deployment specs","ko":"파드 스펙의 dnsConfig options 에 single-request-reopen 을 넣어 A 와 AAAA 조회가 서로 다른 포트로 나가게 했다."}},{"text":{"en":"set GRPC_DNS_RESOLVER=native in the Dockerfiles of gRPC applications so they used the libc resolver","ko":"gRPC 애플리케이션의 Dockerfile 에 GRPC_DNS_RESOLVER=native 를 넣어 ares 대신 libc 리졸버를 쓰게 했다."}},{"text":{"en":"checked with tcpdump port 53 that A and AAAA queries left from different ports","ko":"`tcpdump port 53` 으로 A 와 AAAA 조회가 서로 다른 포트로 나가는 것을 확인했다."}}],"action_items":[],"contributing":["default-config-unchanged"],"recurrence_of":null,"symptoms_text":{"en":"Pod-to-pod calls were intermittently slow and the web application felt slow overall. A request that pod A sent at time x reached pod B at x + 5s, x + 10s or x + 15s, always a multiple of five seconds.\n\ngRPC services showed it as DEADLINE_EXCEEDED errors when their timeout was 3 seconds.\n\nA capture with tcpdump port 53 made the pattern visible: the pod sent the A and AAAA queries for a name from the same source port, the AAAA answers came back, and the A query for the same name was only sent again about five seconds later (18:09:09 to 18:09:15 in the published capture) before it was answered.","ko":"클러스터 전체 네트워크 장애를 겪은 뒤, 팀은 파드 사이 통신이 간헐적으로 늦어지고 웹 애플리케이션 전체가 이따금 느려지는 것을 알아챘다.\n\n파드 A 가 x 시각에 보낸 요청이 파드 B 에는 x + 5초, x + 10초, x + 15초에 도착했고, 요청 전체가 예상보다 훨씬 오래 걸렸다. 지연은 늘 5초의 배수였다.\n\ngRPC 애플리케이션은 타임아웃을 3초로 잡아 두었는데 DEADLINE_EXCEEDED 오류가 났다. 파드 DNS 설정을 고친 뒤에도 gRPC 애플리케이션에서는 이 오류가 계속 났다.\n\n`tcpdump port 53` 으로 보니 A 레코드와 AAAA 레코드 조회가 같은 포트로 나갔고, 응답을 받지 못한 조회가 5초 뒤 다시 나갔다. 원문의 출력에서는 18:09:09 에 보낸 A 조회가 응답 없이 남아 있다가 18:09:15 에 다시 나간다."},"updated_at":"2026-11-08T19:10:30.116985Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0047","org_slug":"mindtickle"}