{"id":"IL-0199","org":"GitHub","date":"2020-07-13","docs":[],"title":{"en":"A non-essential container exceeding its memory limit made GitHub's production pods unavailable, and their restarts failed because a DNS maintenance change had left the clusters unable to reach the image registry","ko":"운영에 꼭 필요하지 않은 컨테이너가 메모리 한도를 넘어 파드가 사용 불가로 표시됐고, DNS 작업 탓에 레지스트리에 접속하지 못해 파드가 다시 뜨지 못하면서 GitHub.com 이 4시간 넘게 멈췄다."},"domain":["kubernetes","networking"],"impact":{"scope":"GitHub.com services degraded and brought down by lost capacity across production Kubernetes clusters","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"A container that production traffic does not need can still take pods out of service, because a pod is available only when all of its containers are healthy.\n\nImagePullPolicy Always turns every container restart into a registry dependency, so an unrelated DNS change that breaks registry access turns a one-minute self-healing event into a long outage, and a mass redeploy spreads it.","ko":"운영에 필요 없는 보조 컨테이너 하나도 파드 전체를 사용 불가로 만들 수 있다. ImagePullPolicy 가 Always 이면 재시작마다 레지스트리에 기대게 되므로, 레지스트리나 DNS 가 흔들릴 때 평소에는 1분이면 끝날 재시작이 긴 장애로 바뀐다. 수습하려고 재배포하면 같은 실패를 전체 클러스터로 퍼뜨릴 수 있다."},"related":[],"sources":[{"url":"https://github.blog/news-insights/company-news/github-availability-report-july-2020/","kind":"blog","license":"unknown","archived":null}],"summary":{"en":"On 13 July 2020 GitHub.com was degraded for four hours and 25 minutes. A container that is not required for production traffic exceeded its memory limit and was killed, and because Kubernetes treats a pod as available only when every container is healthy, production pods were marked unavailable. The loss cascaded through the clusters and the reduced capacity took services down.\n\nNormal recovery failed because the container used ImagePullPolicy Always, so Kubernetes fetched the image on every start, and a routine DNS maintenance operation finished earlier had left the clusters unable to reach the registry. A redeploy triggered to mitigate made it worse by spreading the failure across production clusters. Services recovered only after the process was restarted with the cached DNS records, which let the clusters fetch images, redeploy and come back.","ko":"운영 쿠버네티스 파드 안의 컨테이너 하나가 메모리 한도를 넘어 계속 종료됐다. 이 컨테이너는 운영 트래픽과 상관이 없었지만, 쿠버네티스는 모든 컨테이너가 정상이어야 파드를 사용 가능으로 본다. 그래서 파드들이 사용 불가로 표시되며 클러스터 용량이 줄었다.\n\n보통은 컨테이너가 다시 시작되며 1분 안팎에 회복된다. 그런데 이 컨테이너에는 ImagePullPolicy 가 Always 로 설정돼 있어서 다시 시작할 때마다 이미지를 새로 받아야 했다. 그보다 앞서 끝난 정기 DNS 유지보수 작업 때문에 클러스터가 레지스트리에 접속하지 못했고, 그래서 파드가 뜨지 못했다. 이를 수습하려고 재배포를 실행하자 실패가 운영 클러스터들로 번지기 시작했다.\n\n캐시된 DNS 레코드로 프로세스를 다시 시작한 뒤에야 이미지를 받아 올 수 있었다. 그 뒤 재배포로 서비스를 복구했다. 장애는 4시간 25분 이어졌다."},"trigger":{"en":"A container in the production pods exceeded its memory limit and was terminated; a routine DNS maintenance operation completed earlier had left the clusters unable to reach the image registry.","ko":"파드 안에서 운영에 필요하지 않은 컨테이너 하나가 메모리 한도를 넘어 종료됐다. 앞서 끝난 정기 DNS 유지보수 작업 때문에 클러스터는 이미지 레지스트리에 접속하지 못하는 상태였다."},"severity":"unknown","symptoms":["oom-killed","image-pull-failures","service-unavailable"],"timeline":{"detected_after":null,"resolved_after":"4h 25m"},"date_kind":"incident","detection":null,"components":["memory-limit","registry"],"root_cause":"dns-network","remediation":[{"text":{"en":"restarted the process with the cached DNS records so the clusters could reach the registry","ko":"캐시된 DNS 레코드로 프로세스를 다시 시작해 레지스트리에서 컨테이너 이미지를 받아 올 수 있게 했다."}},{"text":{"en":"fetched the container images, redeployed and recovered the services","ko":"이미지를 받아 온 뒤 다시 배포해 서비스를 복구했다."}}],"action_items":[{"text":{"en":"Improve monitoring so pod restarts cannot fail again in the same pattern","ko":"같은 패턴으로 파드 재시작이 다시 실패하지 않도록 모니터링을 강화한다."}},{"text":{"en":"Minimise the dependency on the image registry","ko":"이미지 레지스트리 의존도를 줄인다."}},{"text":{"en":"Expand validation during DNS changes","ko":"DNS 를 바꿀 때 검증 범위를 넓힌다."}},{"text":{"en":"Re-evaluate all existing Kubernetes deployment policies","ko":"기존 쿠버네티스 배포 정책을 모두 다시 검토한다."}},{"text":{"en":"Improve progressive deployments so the impact of a deployment can be evaluated incrementally","ko":"배포 영향을 조금씩 확인하며 내보낼 수 있도록 점진 배포 방식을 개선한다."}}],"contributing":["overlapping-failures","manual-action-worsened","single-point-of-failure"],"recurrence_of":null,"symptoms_text":{"en":"At 08:18 UTC on 13 July 2020, production Kubernetes pods began to be marked unavailable. The loss of pods spread through the clusters and reduced capacity until GitHub.com services went down.\n\nInside the affected pods, one container was going over its memory limit and being terminated. That container was not needed to serve production traffic, but a pod is only available when all of its containers are healthy.\n\nThis kind of failure usually recovers within about a minute. This time the container had an ImagePullPolicy of Always, so each restart had to pull the image again, and the clusters could not reach the registry, so the pods failed to start. A redeploy started to mitigate the problem spread the failure to more production clusters.","ko":"2020년 7월 13일 08:18 UTC 에 운영 쿠버네티스 클러스터의 파드들이 사용 불가로 표시되기 시작했다. 이 상태가 클러스터 전체로 번지면서 처리 용량이 줄었고, 결국 GitHub.com 서비스가 내려갔다.\n\n파드를 살펴보니 파드 안의 컨테이너 하나가 정해진 메모리 한도를 넘어 종료되고 있었다. 이 컨테이너는 운영 트래픽 처리에 필요하지 않았다. 하지만 쿠버네티스는 파드 안의 모든 컨테이너가 정상이어야 파드를 사용 가능으로 표시한다.\n\n평소라면 이런 경우 클러스터가 1분 안팎에 회복한다. 이번에는 파드가 다시 뜨지 못했다. 클러스터가 이미지 레지스트리에 접속하지 못해 이미지를 받아 오지 못했기 때문이다.\n\n복구하려고 재배포를 실행하자 오히려 영향이 커졌다. 실패가 운영 클러스터들로 퍼지기 시작했다."},"updated_at":"2026-11-10T00:00:40.783708Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0199","org_slug":"github"}