{"id":"IL-0049","org":"Preply","date":"2020-02-28","docs":["https://kubernetes.io/blog/2019/03/29/kube-proxy-subtleties-debugging-an-intermittent-connection-reset/","https://www.projectcalico.org/when-linux-conntrack-is-no-longer-your-friend/","https://www.weave.works/blog/racy-conntrack-and-dns-lookup-timeouts"],"title":{"en":"Partial DNS outage after CoreDNS scaled down and kube-proxy failed to delete stale conntrack entries","ko":"CoreDNS 파드가 줄어든 뒤 kube-proxy 가 conntrack 항목을 지우지 못해 일부 서비스의 DNS 요청이 없어진 파드로 가면서 5xx 가 쏟아졌다"},"domain":["kubernetes","networking"],"impact":{"scope":"DNS for some services inside the Kubernetes cluster; 15000 events dropped for services A, B and C","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"Scaling CoreDNS down is not free: if kube-proxy fails to clear conntrack entries for the removed pod, clients keep sending DNS queries to it. Known DNS weaknesses in a cluster should be prioritised before they cause an outage, and fixes that only treat consequences leave the underlying conntrack problem in place.","ko":"모니터링은 장애를 빨리 잡았고 대응도 빠르고 체계적이었다. 노드는 어떤 한도에도 닿지 않았다.\n\n진짜 근본 원인은 아직 모른다. conntrack 의 특정 버그로 보인다. 팀이 정한 후속 조치는 모두 장애가 낳는 결과를 막는 것이지 근본 원인을 고치는 것이 아니다.\n\n팀은 DNS 에서 문제가 날 수 있다는 것을 알고 있었지만 이 일을 우선해서 다루지 않았다."},"related":[],"sources":[{"url":"https://medium.com/preply-engineering/dns-postmortem-e169efd45afd","kind":"blog","license":"unknown","archived":"https://web.archive.org/web/20260329190731/https://medium.com/preply-engineering/dns-postmortem-e169efd45afd"}],"summary":{"en":"At 22:13 EET on 28 February 2020 the CoreDNS autoscaler at Preply scaled CoreDNS from three pods to two. kube-proxy tried to delete the conntrack entries for UDP connections to the removed pod and failed, so the kernel's connection tracking table kept sending some services' DNS queries to an address where no CoreDNS pod was running. conntrack is the Linux kernel table that remembers the address translation chosen for a flow so later packets skip the lookup. Those services could not resolve names, returned 5xx errors, and 15000 events were dropped across services A, B and C.\n\nOn-call engineers were paged at 22:18, started troubleshooting at 22:21, and reverted the latest release of the service at 22:39; the errors were gone at 22:40. The postmortem gives the resolution as a regular deploy that created new nodes, after which the CoreDNS autoscaler added pods and the conntrack table was rewritten. The team lists time to detect as 4 minutes, time to engage as 21 minutes, time to fix as 1 minute, and the total as 26 minutes.\n\nThe team did not find the real root cause and suspected a specific conntrack bug. The postmortem also admits that DNS problems were known beforehand but not prioritised, and that every action item treats consequences rather than the root cause.","ko":"2020년 2월 28일 Preply 의 쿠버네티스 클러스터에서 일부 서비스의 DNS 가 26분 동안 부분적으로 멈췄다. 서비스 A, B, C 에서 이벤트 15000건이 유실됐다.\n\n클러스터 부하가 낮아지자 CoreDNS-autoscaler 가 CoreDNS 파드를 3개에서 2개로 줄였다. 이때 kube-proxy 가 conntrack 테이블에서 사라진 CoreDNS 파드로 가는 옛 항목을 지우지 못했다. conntrack 은 리눅스 커널이 NAT 기록을 테이블에 담아 두는 기능이다. 커널은 같은 출발지 파드에서 같은 목적지로 가는 다음 패킷을 CPU 를 아끼려고 다시 변환하지 않고, 이 테이블에서 목적지 주소를 가져온다. 그래서 일부 서비스의 DNS 요청이 이미 없어진 파드로 계속 갔다.\n\n당직 엔지니어들은 22시 39분에 서비스의 최신 릴리스를 되돌렸고, 22시 40분에 5xx 오류가 사라졌다. 포스트모템은 해결 경위를 이렇게 적었다. 클러스터의 정기 배포가 새 노드를 만들었고, CoreDNS-autoscaler 가 다시 파드를 늘리면서 conntrack 테이블이 자동으로 새로 쓰였다. 감지까지 4분, 대응 착수까지 21분, 해결까지 1분이 걸렸다.\n\n팀은 진짜 근본 원인을 아직 모른다고 밝혔다. conntrack 의 특정 버그로 보인다고 했다. 운이 좋았던 점도 두 가지 적었다. 다른 배포가 우연히 CoreDNS-autoscaler 를 움직여 conntrack 테이블이 새로 쓰인 것, 그리고 장애가 모든 서비스로 번지지 않은 것이다."},"trigger":{"en":"Because load in the cluster was low, the CoreDNS autoscaler reduced the number of CoreDNS pods from 3 to 2.","ko":"클러스터 안의 부하가 낮아지자 CoreDNS-autoscaler 가 CoreDNS 파드를 3개에서 2개로 줄였다."},"severity":"unknown","symptoms":["dns-resolution-failures","high-error-rate","stale-service-routing"],"timeline":{"detected_after":"4m","resolved_after":"26m"},"date_kind":"incident","detection":{"en":"Prometheus alerted on a high 5xx rate on services A, B and C and paged on-call through VictorOps.","ko":"Prometheus 모니터링이 서비스 A, B, C 에서 5xx 비율이 높아진 것을 잡아 VictorOps 로 당직자를 호출했다. 포스트모템이 적은 감지 시간은 4분이다."},"components":["coredns","kube-proxy","conntrack"],"root_cause":"dns-network","remediation":[{"text":{"en":"reverted the latest release of the affected service","ko":"22시 39분에 당직 엔지니어들이 해당 서비스의 최신 릴리스를 되돌렸다."}},{"text":{"en":"a regular deploy created new nodes, the CoreDNS autoscaler added CoreDNS pods, and the conntrack table was rewritten","ko":"정기 배포로 새 노드가 생기자 CoreDNS-autoscaler 가 CoreDNS 파드를 다시 늘렸고, conntrack 테이블이 자동으로 새로 쓰였다."}}],"action_items":[{"text":{"en":"Disable the autoscaler for CoreDNS","ko":"CoreDNS 의 오토스케일러를 끈다."}},{"text":{"en":"Run a DNS cache server in production","ko":"운영 환경에 DNS 캐시 서버를 둔다."}},{"text":{"en":"Monitor conntrack usage","ko":"conntrack 사용량을 모니터링한다."}}],"contributing":["automation-amplified","early-signal-ignored","no-caching"],"recurrence_of":null,"symptoms_text":{"en":"Prometheus detected a high rate of 5xx responses on three services, called A, B and C in the write-up, and paged the on-call engineers through VictorOps at 22:18 EET. The 5xx rate was also visible in Kibana.\n\nDNS lookups from some services inside the Kubernetes cluster were failing because their traffic to the cluster DNS was still being sent to a CoreDNS pod that no longer existed. kube-proxy had logged the failure at the moment of the scale-down: \"Failed to delete kube-system/kube-dns:dns endpoint connections, error: error deleting conntrack entries for UDP peer {100.64.0.10, 100.110.33.231}, error: conntrack command returned: ...\". The CoreDNS deployment events showed \"Scaled down replica set coredns-6cbb6646c9 to 2\" a fraction of a second earlier.\n\nNot every service was affected, and no node reached any of its limits.","ko":"Prometheus 모니터링이 서비스 A, B, C 에서 5xx 비율이 높아진 것을 잡아 당직자를 호출했다. 당직 엔지니어들은 22시 18분부터 VictorOps 호출을 받기 시작했다. Kibana 에서도 5xx 비율이 올라간 것이 보였다.\n\n그보다 5분 앞선 22시 13분에 CoreDNS-autoscaler 가 CoreDNS 파드를 3개에서 2개로 줄였다. CoreDNS 로그에는 다음 줄이 남았다.\nI0228 20:13:53.507780 1 event.go:221] Event(v1.ObjectReference{Kind:\"Deployment\", Namespace:\"kube-system\", Name:\"coredns\", UID:\"2493eb55-3dc0-11ea-b3a2-02bb48f8c230\", APIVersion:\"apps/v1\", ResourceVersion:\"132690686\", FieldPath:\"\"}): type: 'Normal' reason: 'ScalingReplicaSet' Scaled down replica set coredns-6cbb6646c9 to 2\n\n같은 시각 kube-proxy 는 conntrack 항목을 지우지 못했다는 오류를 남겼다.\nE0228 20:13:53.795782 1 proxier.go:610] Failed to delete kube-system/kube-dns:dns endpoint connections, error: error deleting conntrack entries for UDP peer {100.64.0.10, 100.110.33.231}, error: conntrack command returned: ...\n\n당직 엔지니어들은 22시 21분에 원인 조사를 시작했다. 22시 39분에 해당 서비스의 최신 릴리스를 되돌렸고, 22시 40분에 5xx 오류가 사라지며 상황이 안정됐다. 장애는 모든 서비스가 아니라 일부 서비스에만 나타났다."},"updated_at":"2026-11-10T00:00:38.657033Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0049","org_slug":"preply"}