Incident Library

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 가 계속 실패해 큐는 천천히 빠졌다.

증상 노드 NotReady노드 커널 패닉파드 Terminating 정체처리량 저하

원인

촉발
Kubernetes 1.15 code freeze 를 앞두고 테스트 사용량이 치솟아, k8s-prow-build 클러스터 노드의 디스크 I/O 가 GCP 의 스로틀링 한도에 걸렸다.

감지

여러 사용자가 GitHub 에는 실패로 올라왔지만 잡 상태로는 아직 실행 중인 잡이 있다고 신고했다. 첫 신고는 13:26 에 Slack 으로 들어왔다. 이런 장애를 잡는 알림은 없거나 동작하지 않았다.

조치

후속 조치

교훈

사고 전에 Prow 지표가 기록되지 않아 무슨 일인지 파악하기 어려웠다. 이런 장애를 잡는 알림은 없거나 동작하지 않았다. 원인을 찾고 해결책을 정한 뒤에도 두 시간 동안 아무것도 하지 않았다. 사고로 1.15 code freeze 가 밀렸다. IOPS 가 문제라는 것을 알아본 사람이 마침 자리에 있었던 것은 운이었다.

출처

참고 문서

관련 사례

내 클러스터에도 있는지 확인하기

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: 클라우드 블록 스토리지, 노드 루트 디스크, kubelet. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.