IL-0401 Kubernetes project · 2019-05-30kubernetesgcp
Kubernetes 프로젝트의 Prow 빌드 클러스터 노드가 GCP 디스크 IOPS 스로틀링에 걸려 테스트가 이상하게 실패하고 PR 머지가 몇 시간 멈췄다
Prow 잡은 노드 100개짜리 k8s-prow-build 클러스터에서 돈다. 노드마다 CPU 8개, RAM 52 GB, 디스크 250 GB 다. GCP 는 디스크 크기에 비례해 IOPS 를 제한하므로 250 GB 디스크는 인스턴스당 187.5 IOPS 였다. 대부분의 노드는 디스크를 거의 쓰지 않았지만, 어떤 작업을 받은 노드는 디스크 사용량이 그 몇 배까지 치솟았다. 테스트 부하는 시간이 지나며 늘었고, Kubernetes 1.15 code freeze 를 앞두고 사용량이 뛰었다. 그러자 I/O 작업이 너무 오래 걸려 노드에서 파드 실패, kubelet 크래시, 커널 패닉이 났고, 테스트 코드도 이상하게 동작했다. 한 번에 영향을 받은 노드는 소수였다. 그러나 잡 하나가 머지되려면 많은 파드가 성공해야 해서 머지가 사실상 멈췄다.
13:26 의 신고 뒤 14:11 에 노드와 테스트 파드에 문제가 많다는 것을 확인했고, 14:43 에 원인이 심한 I/O 스로틀링이라는 것을 찾았다. 15:02 에 온콜 담당자가 용량을 늘리는 방법을 안내받고 디스크 quota 를 요청해 15:14 에 받았다. 그러나 그 뒤 두 시간 동안 아무것도 하지 않았다. 17:10 에 용량이 늘지 않은 것을 알고 500 GB 디스크 노드 55개를 띄웠고, 17:41 부터 노드를 500GB 노드 풀로 차례로 옮겨 23:55 에 모든 노드가 500 GB 디스크를 쓰게 됐다. 다음 날 07:00 에 Prow 는 평소 속도로 머지했다. 문제는 적어도 7시간 이어졌고, 정점에 PR 60개가 머지 큐에 걸렸으며, 1.15 code freeze 는 하루 밀렸다. 관련 없는 모니터링 장애로 사고 전 한 주의 prow/tide 모니터링 데이터 대부분이 영구히 사라졌다. 그래서 클러스터가 언제부터 망가졌는지 알기 어려웠다.
- 심각도
- –
- 영향 범위
- Prow CI jobs failed, were aborted or did not upload artifacts; at peak 60 PRs were stuck in the merge queue and no PRs merged for many hours; the Kubernetes 1.15 code freeze slipped a day
- 영향 사용자
- Kubernetes contributors whose PRs depended on Prow
- 지역
- us-central1-f
- 감지까지
- –
- 복구까지
- –
증상
2019년 5월 30일 13:26 PDT 에 Slack 으로 Prow 가 이상하다는 신고가 들어왔다. GitHub 에는 잡이 실패했다고 올라왔는데 Deck 에서는 같은 잡이 아직 실행 중으로 보였다. 많은 테스트가 뜻밖의 방식으로 실패하거나 실행 도중 뚜렷한 이유 없이 중단됐다.
파드가 finished.json 을 올리지 못하고 끝나 아티팩트가 자주 올라가지 않았다. 도구 대부분이 이 파일로 잡 상태를 판단하므로 Spyglass 와 Testgrid 는 잡이 끝난 것을 알지 못했다. 업로드가 안 된 잡 때문에 Testgrid 가 잘못된 flake 알림을 보냈다. 한 파드는 State: Terminated, Exit Code: 0 이면서 Started 와 Finished 가 모두 Mon, 01 Jan 0001 00:00:00 +0000 으로 찍혀 있었다.
containerd 노드 풀의 노드가 NotReady 였고, NotReady 인 노드는 계속 바뀌었다. gke-prow-containerd-pool-99179761-02q6, gke-prow-containerd-pool-99179761-313j, gke-prow-containerd-pool-99179761-4377, gke-prow-containerd-pool-99179761-t05g, gke-prow-containerd-pool-99179761-s4k7 이 NotReady 목록에 올랐고, 버전은 모두 v1.13.5-gke.10 이었다.
노드에서는 커널 패닉이 났고 kubelet 은 재부팅을 되풀이했다. 파드는 제대로 죽지 않았고, 팀이 하지 않은 무언가가 파드를 evict 하고 있었다. 30분째 PodInitializing 에 머문 파드도 있었고, 나흘 동안 2,420번이나 kill 시도를 받은 잡 파드도 있었다.
13:50 에 온콜 담당자는 큰 이상 신호를 찾지 못했다. 신고된 잡은 너무 오래돼 쓸 만한 정보를 얻을 수 없었다. 온콜 담당자는 완료 상태를 Prow 에 올리는 잡의 일시적인 문제로 봤다. 14:17 무렵에는 kubelet 과 CRI 사이 RPC 문제와 파드 삭제 중의 교착을 의심했다. 전에는 이 증상을 COS 나 containerd 문제로 보고 넘겼다.
14:43 에 원인이 심한 I/O 스로틀링으로 밝혀졌다. 250 GB 디스크의 Sustained random IOPS limit 은 읽기 187.50, 쓰기 375.00 이고, Sustained throughput limit 은 30.00 MB/s 였다. 스로틀링될 때 실제 사용량은 80MB/s 와 450 IOPS 이상이었다. 스로틀링된 디스크 작업 그래프는 최근 하루 이틀 사이 크게 나빠져 있었다.
16:05 기준으로 마지막 머지는 5시간 전이었다. 정점에는 PR 60개가 머지 큐에 걸려 있었고, 몇 시간 동안 PR 이 하나도 머지되지 않았다. CI 가 계속 실패해 큐는 천천히 빠졌다.
원인
- 촉발
- Kubernetes 1.15 code freeze 를 앞두고 테스트 사용량이 치솟아, k8s-prow-build 클러스터 노드의 디스크 I/O 가 GCP 의 스로틀링 한도에 걸렸다.
감지
여러 사용자가 GitHub 에는 실패로 올라왔지만 잡 상태로는 아직 실행 중인 잡이 있다고 신고했다. 첫 신고는 13:26 에 Slack 으로 들어왔다. 이런 장애를 잡는 알림은 없거나 동작하지 않았다.
조치
- 디스크 quota 를 더 요청해 15:14 에 받았다.
- 17:10 에 500 GB 디스크 노드 55개를 띄웠다.
- 23:55 에 새 노드 풀로 옮기는 일을 마쳐 모든 노드가 500 GB 디스크를 쓰게 됐다.
후속 조치
- tide 가 일을 멈추면 온콜 담당자가 호출을 받도록 모니터링을 만들거나 고친다. 이 일은 이슈 #12829 에서 다룬다.
- 온콜 순번에 새 사람을 넣는 절차와 지침을 만들어, 새 사람이 준비나 추가 지원 없이 혼자 맡겨지지 않게 한다.
교훈
사고 전에 Prow 지표가 기록되지 않아 무슨 일인지 파악하기 어려웠다. 이런 장애를 잡는 알림은 없거나 동작하지 않았다. 원인을 찾고 해결책을 정한 뒤에도 두 시간 동안 아무것도 하지 않았다. 사고로 1.15 code freeze 가 밀렸다. IOPS 가 문제라는 것을 알아본 사람이 마침 자리에 있었던 것은 운이었다.
출처
참고 문서
관련 사례
IL-0071작은 파일이 4만 개 넘게 든 단일 스테이지 이미지의 containerd 스냅샷이 쌓여 워커 노드의 inode 가 디스크보다 빠르게 소진되고 있었다Onkar Raghunath Shelke · 2026같은 원인 · 공통 노드 루트 디스크, kubelet
IL-0002빌더 파드가 노드 한 대에 몰리자 kubelet 이 기본 API QPS 한도에 막혀 파드 상태를 늦게 갱신했고, CI 빌드가 AWS IAM 자격 증명을 받지 못해 실패했다Zalando · 2019같은 원인 · 공통 CI 시스템, kubelet
IL-0040비운영 쿠버네티스 클러스터에 Helm 차트를 한꺼번에 설치하자 작은 gp2 루트 볼륨의 IOPS 가 바닥나, 워커 노드 세 대에서 kubelet 이나 Docker 가 내려가 세 대 모두 NotReady 가 됐다Saltside · 2017같은 원인 · 공통 노드 루트 디스크, kubelet
같은 원인 · 공통 CI 시스템
같은 원인 · 공통 CI 시스템
같은 원인 · 공통 kubelet
같은 원인 · 공통 클라우드 블록 스토리지
IL-0169FR-PAR 의 Scaleway Kubernetes API 가 메모리 부족으로 쓰러져 노드 인증이 막히고 Kapsule 노드가 NotReady 가 됐다.Scaleway · 2024같은 원인 · 공통 kubelet
같은 원인 · 공통 클라우드 블록 스토리지
IL-0176시계열 급증으로 호스트 메모리가 바닥나자 oom_score_adj 999 를 받은 Prometheus 컨테이너가 커널 OOM Killer 에게 먼저 죽어 CrashLoopBackOff 에 빠졌다.LINE · 2020같은 원인 · 공통 kubelet
IL-0518GKE 위 gitlab.freedesktop.org 의 디스크가 모자라 저장소를 늘리려던 30분 작업이 GitLab 전체의 4시간 장애가 됐다freedesktop.org · 2018같은 원인 · 공통 클라우드 블록 스토리지
같은 원인 · 공통 클라우드 블록 스토리지
같은 원인 · 공통 클라우드 블록 스토리지
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0401
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0401/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.