Incident Library
  • 원인
  • 구성 요소
  • 증상
  • 기여 요인
  • 사례

사례7건

7건 중 6~7번째

  1. 증상

    학생 두 명이 서버를 시작할 수 없다고 강의 Piazza 에 알렸고, /hub/admin 화면에서도 서버가 시작되지 않았다. 처음에는 학생들이 메모리를 다 썼을 수 있다는 말이 나왔다.

    원인
    구성 요소
    기여 요인
    –
    감지

    학생들이 강의 Piazza 와 강의 slack 에 서버가 시작되지 않는다고 알렸다.

    조치
    • Terminating 에 멈춘 사용자 파드를 kubectl --namespace=prod delete pod jupyter-<name> --grace-period=0 --force 로 강제로 지웠다. 그 뒤 /hub/admin 에서 서버가 제대로 시작됐다.
    • docker ps 가 멈춘 노드 k8s-pool1-19522833-13 을 cordon 했다.
    • 같은 상태인 k8s-pool2-19522833-9 에서 멈춘 파드를 모두 강제로 지우고 그 노드도 cordon 했다.
    • pool1-...-13 을 Azure 포털에서 손으로 멈췄다가 다시 시작했다. 노드가 돌아와 Docker 가 응답하자 uncordon 했다.
    • pool2-...-9 가 완전히 멈춘 뒤 Azure 포털에서 손으로 다시 시작했다.
    후속 조치
    • 학생 서버가 시작되거나 멈추지 않는다는 신고가 여러 건 오면 그 사용자 파드들이 같은 노드에서 돌았는지 확인한다.
    • /var/lib/docker 를 sdb1 에 마운트하지 않은 노드가 몇 대인지 알아본다.
    • Terminating 에 멈춘 파드 수가 늘어나는지 지켜본다. 예를 들어 kubectl --namespace=prod get pod -o wide| grep Terminating 으로 본다.
  2. 증상

    SRE 팀장이 애플리케이션 Helm 차트를 고친 뒤 자기 머신에서 CI 과정을 돌렸다. watch kubectl get pods 로 지켜보니 파드가 모두 Running 이 되었는데, 그중 일부가 다시 Pending 으로 바뀌었다. 그는 저절로 풀릴 일시적인 문제라고 보고 회의에 들어갔다.

    촉발

    CI 과정을 로컬에서 돌려 시장 네 곳의 Helm 차트를 비운영 클러스터에 한꺼번에 설치했다. 그 결과 t2.medium 워커 노드 세 대가 여러 컨테이너의 이미지를 동시에 받고 컨테이너를 동시에 만들었다.

    원인
    구성 요소
    기여 요인
    감지

    담당자가 CI 과정을 돌리며 watch kubectl get pods 로 지켜보다가 Running 이던 파드가 Pending 으로 바뀌는 것을 보았다. 두 시간 뒤 Unknown 상태의 파드를 보고서야 내부에서 무언가 확실히 잘못됐다고 판단했다. 워커 노드 세 대가 모두 NotReady 였지만 어떤 모니터링도 이를 잡지 못했다.

    조치
    • 워커 노드 세 대를 종료하고 오토스케일링 그룹이 새 인스턴스를 띄우게 했고, 약 10분 뒤 클러스터가 정상으로 돌아왔다.
    후속 조치
    • 비운영 AWS 계정과 DataDog 의 연동 문제를 고쳐 지표가 들어오게 하고, 그 지표를 보며 설치 과정을 다시 돌렸다.
    • 워커 노드의 루트 EBS 볼륨을 20GB 에서 120GB 로 늘렸다.
    • ruby:2.4, alpine:3.2 같은 공통 베이스 이미지 안에서 sleep 루프만 도는 DaemonSet 을 배포해 노드에 이미지를 미리 받아 두었다. kops 가 사용자 훅을 지원할 때까지 쓰는 임시 방편이다.
    • 쿠버네티스의 계층마다 할당 한도를 다르게 설정한다.
    • tiller 가 크래시 루프에 빠지면 차트 설치와 업그레이드로 수정을 배포할 수 없으므로 tiller 고가용성을 Helm 팀과 논의한다.
    • 새로 만드는 파드 수를 조절할 방법을 찾는다.
    교훈

    평소 하던 애플리케이션 배포만으로도 클러스터가 무너질 수 있었다. 워커 노드를 종료하는 방법은 효과가 있었지만 파드를 다른 노드로 옮기지 않으므로 운영 환경에서는 고객이 서비스를 못 쓰게 된다. 그래서 이런 장애의 표준 절차가 될 수 없다. 노드 상태, 파드 단계, 노드 리소스 지표가 없으면 이런 장애를 알아채지 못한다. kops 의 기본 20GB gp2 루트 볼륨은 IOPS 와 디스크 공간이 모두 모자랐다. 새로 만드는 파드 수를 조절할 수단이 있으면 문제를 풀지는 못해도 위험을 줄일 수 있고, 무언가 잘못됐을 때 제 손으로 클러스터를 마비시키는 일을 막을 수 있다.

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

이 7건에서 가장 많이 나오는 구성 요소: 컨테이너 런타임, 텔레메트리 에이전트. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.

원인별4

설정 변경2건

  1. IL-0179 DEBUG 로그가 쏟아지자 동기 로깅을 하던 요청 스레드들이 가득 찬 stdout 파이프에서 멈춘 채 DB 커넥션을 쥐고 있어, HikariCP 커넥션 풀이 고갈되고 요청이 30초 주기로 한꺼번에 실패했다.
  2. IL-0109 로그 수집을 고치려던 EKS 노드 롤오버가 꼬이면서 Auto Scaling 그룹이 정상 워커 노드를 모두 종료해 클러스터에 노드가 하나도 남지 않았다.
    DFDS2023

용량 한계2건

  1. IL-0071 작은 파일이 4만 개 넘게 든 단일 스테이지 이미지의 containerd 스냅샷이 쌓여 워커 노드의 inode 가 디스크보다 빠르게 소진되고 있었다
  2. IL-0040 비운영 쿠버네티스 클러스터에 Helm 차트를 한꺼번에 설치하자 작은 gp2 루트 볼륨의 IOPS 가 바닥나, 워커 노드 세 대에서 kubelet 이나 Docker 가 내려가 세 대 모두 NotReady 가 됐다

unknown2건

  1. IL-0087 RKE2 클러스터 노드를 재부팅한 뒤 Multus 가 쿠버네티스 API 에 닿지 못해 파드가 IP 를 받지 못했고, 같은 장애가 모든 노드로 번져 전체 서비스가 멈췄다.
  2. IL-0507 Azure 쿠버네티스 노드 두 대에서 Docker 데몬이 멈춰 학생 파드가 시작되거나 종료되지 않았다

의존성 장애1건

조직
  1. IL-0073 Kafka 연결이 끊기자 로깅 사이드카가 Docker 데몬에 부하를 주어 노드가 줄줄이 비정상이 되었고, 재스케줄링으로 생긴 노드 약 41,000개가 Consul gossip 메시를 오염시켜 Vault 와 배포 엔진까지 멈췄다
    Target2019