사례3건
3건 중 1~3번째
IL-0005새 텔레메트리 서비스가 모든 노드에서 무거운 쿠버네티스 API 요청을 보내 대형 클러스터의 컨트롤 플레인이 무너졌고, DNS 기반 서비스 디스커버리가 깨져 OpenAI 의 모든 서비스가 멈췄다OpenAI2024- 증상
2024년 12월 11일 오후 3시 13분 PST 에 알림이 울려 엔지니어들에게 전달됐다. 3시 16분부터 ChatGPT, API, Sora 를 포함한 OpenAI 의 모든 서비스가 크게 느려지거나 완전히 멈췄다.
- 촉발
오후 3시 12분 PST 에 쿠버네티스 컨트롤 플레인 지표를 자세히 수집하는 새 텔레메트리 서비스를 배포했다. 이 서비스의 설정 때문에 각 클러스터의 모든 노드가 무거운 쿠버네티스 API 요청을 보냈다. 이 요청은 클러스터가 클수록 비용이 커진다. 변경은 오후 2시 51분부터 3시 20분 사이에 모든 클러스터에 적용됐다.
- 원인
- 구성 요소
- 기여 요인
- 감지
변경이 모든 클러스터에 적용되던 오후 3시 13분 PST 에 알림이 울려 엔지니어들에게 전달됐다. 탐지 도구는 고객이 영향을 받기 몇 분 전에 문제를 잡았고, 엔지니어들은 3시 16분에 원인을 찾았다. 다만 노드의 DNS 캐시가 실제 실패를 늦춰, 문제의 전체 범위가 보이기 전에 배포가 계속 진행됐다.
- 조치
- 클러스터 규모를 줄여 쿠버네티스 API 부하의 총량을 낮췄다.
- 쿠버네티스 관리 API 로 가는 네트워크 접근을 막아 새로 들어오는 무거운 요청을 차단하고 API 서버가 회복할 시간을 벌었다.
- 쿠버네티스 API 서버를 증설해 밀린 요청을 처리할 자원을 늘리고 수정을 적용할 수 있게 했다.
- 컨트롤 플레인 제어권을 되찾은 뒤 문제의 텔레메트리 서비스를 지웠다.
- 오후 3시 27분부터 영향받은 클러스터에서 트래픽을 빼기 시작했고, 가능한 곳에서는 트래픽을 정상 클러스터로 옮겼다.
- 많은 서비스가 동시에 자원을 내려받아 자원 한도가 찬 클러스터에는 추가로 수동 조치를 했다.
- 후속 조치
- 모든 인프라 설정 변경에 단계적 배포를 적용하고, 서비스 워크로드와 쿠버네티스 컨트롤 플레인을 포함한 클러스터 상태를 계속 감시한다.
- 데이터 플레인이 컨트롤 플레인 없이 버티는 상황과 잘못된 변경을 일부러 배포하는 상황을 시험하는 장애 주입 테스트를 돌린다.
- 데이터 플레인이 컨트롤 플레인을 지나치게 압박할 때도 엔지니어가 쿠버네티스 API 서버에 접근할 수 있는 비상 접근 수단을 만든다.
- 데이터 플레인과 컨트롤 플레인을 분리한다. 서비스 디스커버리가 쿠버네티스 DNS 에 묶여 있는 구조를 풀어, 핵심 서비스가 요청을 처리할 때 컨트롤 플레인에 기대지 않게 한다.
- 클러스터 기동에 필요한 자원에 캐시와 동적 속도 제한을 더하고, 클러스터 하나를 통째로 빠르게 교체하는 훈련을 정기적으로 한다.
- 교훈
이 장애는 여러 시스템과 절차가 동시에 실패하며 예상하지 못한 방식으로 얽혀 생겼다. 테스트는 이 변경이 쿠버네티스 컨트롤 플레인에 주는 영향을 잡지 못했다. DNS 캐시 때문에 변경과 서비스 실패 사이에 시간 차가 생겼다. 컨트롤 플레인에 접근할 수 없게 되면서 복구가 매우 느렸다. 데이터 플레인이 컨트롤 플레인과 따로 돌도록 설계되어 있어도, DNS 기반 서비스 디스커버리가 컨트롤 플레인에 기대면 컨트롤 플레인 장애가 서비스 장애로 번진다. 배포 전 점검은 클러스터의 CPU 와 메모리 사용량만 봤고 API 서버 부하는 보지 않았다.
IL-0083멀티 테넌트 쿠버네티스 클러스터에서 노드 로컬 dnsmasq 가 동시 질의 한도에 걸리고 cluster.local 응답을 캐시하지 못한 데다 ndots 검색 도메인 질의가 CoreDNS 로 몰려, 서비스 간 호출이 간헐적인 5xx 를 냈다.Adevinta2023- 증상
어느 금요일 오후, 고객 한 곳이 SCHIP 에서 돌리는 일부 서비스에서 HTTP 5xx 오류가 튄다고 알려 왔다. 팀은 바로 장애를 선언했다.
- 원인
- 구성 요소
- 기여 요인
- 감지
고객이 SCHIP 에서 돌리는 일부 서비스의 HTTP 5xx 가 튄다고 알려 와서 알았다. DNS 와의 관계는 한참 뒤에야 드러났고, 그때 보니 그동안 무시해 온 이 클러스터의 DNS Latency SLI 가 다른 클러스터보다 낮아져 있었다.
- 조치
- dnsmasq 의 노드당 동시 DNS 질의 한도를 150에서 Google 권장값인 1500으로 올렸다.
- CoreDNS 가 응답에 RA 비트를 항상 넣도록 header 설정에 set ra aa, clear rd 를 넣어 dnsmasq 가 cluster.local 응답을 캐시하게 했다.
- 노드 로컬 dnsmasq 에서 ndots 때문에 생긴 풀 수 없는 도메인 질의를 가로채 NXDOMAIN 으로 응답하도록 설정해 CoreDNS 로 넘어가지 않게 했다.
- fluent-bit 가 로그 라우터에 접속할 때 쓰는 호스트 이름을 서비스 이름에서 FQDN 으로 바꿨다.
- 영향받은 고객에게 앱의 내부 이름 해석을 FQDN 으로 바꾸도록 요청했다.
- 교훈
SLO 를 보기 좋은 지표로만 두지 말고 안전장치로 써야 한다. 이번에는 나빠진 DNS Latency SLI 를 오래 무시한 탓에 원인을 늦게 찾았다. SLO 를 안전장치로 쓰려면 믿을 수 있는 SLI 가 먼저 있어야 한다. 조사가 여러 당직자에게 흩어져 있었고, 관찰 결과와 가설을 한곳에 모으지 않아 같은 가설이나 이미 버린 가설을 다시 붙잡기도 했다. 가설 하나를 버린 뒤에 다음 가설로 넘어가야 한다. 기존 지표에 없는 데이터는 DNStop 처럼 직접 모아야 한다. 멀티 테넌트 환경에서는 DNS 를 한 번 개선하면 모든 고객이 그 효과를 본다.
IL-0075클러스터가 EC2 인스턴스 약 290대로 커지자 노드마다 도는 Datadog 에이전트가 쿠버네티스 API 를 폴링하면서 API 서버가 CPU 와 메모리를 다 써 쿠버네티스 컨트롤 플레인을 쓸 수 없게 됐다.Civis Analytics2019- 증상
스크립트 실행 기반을 쿠버네티스로 옮긴 Croquet 를 사내에 공개한 뒤, 개발자들은 kubectl 명령이 느리다고 했다. 사용자들은 노트북과 서비스가 가끔 시작되지 않는다고 알렸다.
- 촉발
자체 인프라 Bocce 에서 쿠버네티스로 옮긴 스크립트 실행 기반 Croquet 를 2018년 9월 사내에 공개했다. 대량의 스크립트가 몰리면서 클러스터가 EC2 인스턴스 약 290대로 커졌고, 노드마다 도는 Datadog 에이전트가 쿠버네티스 API 를 폴링하는 부하도 함께 늘었다.
- 원인
- 구성 요소
- 기여 요인
- 감지
개발자들이 kubectl 명령이 느리다고 했고, 사용자들은 노트북과 서비스가 가끔 시작되지 않는다고 알렸다. 마스터 노드의 CPU 사용률이 높았고, 조사해 보니 API 서버 컨테이너 세 개가 CPU 를 꽉 채워 쓰고 있었다. 당시 팀이 볼 수 있던 지표는 마스터 노드 CPU 의 CloudWatch 지표와 Datadog 의 컨테이너별 CPU, 메모리 지표였다. API 요청 처리량과 5xx 오류율과 요청 지연은 볼 수 없었다.
- 조치
- 사내 사용자들을 예전 인프라로 되돌려 클러스터를 안정시켰다.
- 마스터 노드를 m4.large 세 대에서 m4.4xlarge 세 대로 키웠다.
- 노드마다 도는 Datadog 에이전트가 서비스 메타데이터를 얻으려고 API 서버를 폴링하지 않도록 Datadog 설정을 바꿨다.
- 상태를 바꾸지 않는 요청의 max-requests-inflight 한도를 400 에서 1200 으로 올렸다.
- etcd 의 EBS 볼륨을 20 GB 에서 100 GB 로 늘려 IOPS 를 100 에서 300 으로 올렸다.
- 스크립트의 DNS 정책을 ClusterFirst 에서 Default 로 바꿔 DNS 타임아웃을 줄였다.
- 후속 조치
- Kops 가 안전한 이전을 지원하면 etcd 를 2.2.1 에서 3.x 로 올린다.
- 스크립트가 클러스터 안의 다른 워크로드와 통신할 수 있도록 DNS 타임아웃 문제를 근본적으로 해결한다.
- 교훈
가장 큰 실수는 쿠버네티스가 모든 것을 알아서 해 준다고 가정한 것이었다. 쿠버네티스는 노드 5,000대와 파드 100,000개를 지원한다고 하지만, 그 규모에 이르려면 손봐야 할 설정이 많다. 클러스터에 넣는 서드파티 도구, 특히 DaemonSet 을 조심해야 한다. 많은 도구가 보통 규모에 맞춰 만들어졌고 큰 규모에서는 시험되지 않았다. 클러스터 상태를 watch 하는 서비스가 데이터를 지나치게 많이 가져가도록 설계되면 규모 문제가 생긴다. kube2iam 은 모든 파드의 메타데이터를 메모리에 들고 있다가 메모리가 바닥났고, Fluentd Kubernetes Metadata Filter 플러그인도 같은 문제가 있다. 대개 설정 하나로 고칠 수 있지만, 부하 테스트를 해 보기 전에는 잘 드러나지 않는다.
이 3건에서 가장 많이 나오는 구성 요소: 텔레메트리 에이전트, 클라이언트 쪽 DNS 리졸버와 캐시. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.