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

사례6건

6건 중 3~6번째

  1. 증상

    ICT 기준 2023-04-09 새벽 2시쯤 클러스터 노드 하나가 평소와 다른 CPU 사용을 보였다. 팀은 containerd 와 runc 의 상위 프로젝트에 있는 CRI 버그로 추정했다. 이 노드가 다른 서비스를 모두 스로틀링해 서비스가 실패하고 있었다.

    촉발

    평소와 다른 CPU 사용을 보인 노드를 바로잡으려고, 시스템을 쓰는 사람이 없는 시간이라고 보고 클러스터를 정비 상태로 내린 뒤 영향받은 노드를 전부 재부팅했다.

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

    새벽 2시쯤 노드 하나의 평소와 다른 CPU 사용을 발견했다. 재부팅 뒤 2시 30분쯤 일부 서비스에서 이상한 문제가 보여 네트워크 장애를 알아챘고, 6시 31분에는 개발자들이 Terra 저장소가 내려갔다고 알려 왔다.

    조치
    • Multus 와 Calico 를 완전히 지우고 Cilium CNI 로 바꿨다.
    • 14:30 ICT 까지 CNI 를 뺀 클러스터 설정 대부분을 되돌려 모든 서비스를 다시 올렸다.
    교훈

    팀은 처음 장애를 저절로 풀릴 일시적인 문제로 보고 다른 노드까지 재부팅했는데, 이 판단은 완전히 틀렸고 장애가 모든 노드로 번졌다. 바꿔 넣은 Cilium 은 이 클러스터에서 Calico 보다도 잘 동작했다. 팀은 한 블로그 글의 자원 사용량 비교를 보고 Cilium 을 피했었지만, 실제로는 Calico, Canal, Flannel 과 마찬가지로 노드당 1코어라는 허용 범위 안에서 돌았다. 작은 클러스터에서는 Cilium 의 조금 더 큰 자원 사용량이 문제가 되지 않았다.

  2. 증상

    2023-02-14 09:33 UTC, 최종 사용자들이 CloudWatch 로그가 제대로 들어오지 않는다고 알려 왔다. 팀은 fluentd 를 조사하다가 컨테이너 런타임이 docker-shim 이 아니라 containerd 로 바뀌어 있다는 것을 찾았다. 전날 07:30 UTC 의 정기 노드 롤오버 때 containerd 가 실수로 기본 런타임으로 설정돼 있었다.

    촉발

    쿠버네티스 로그가 CloudWatch 로 가지 않는 문제를 고치려고 예정에 없던 노드 롤오버를 시작했다.

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

    로그 문제는 최종 사용자들이 CloudWatch 로그가 이상하다고 알려 오면서 드러났다. 노드가 사라진 장애는 사후 분석 기준으로 2분 만에 감지됐다.

    조치
    • 10:49 UTC 에 노드 롤오버 스크립트로 새 노드를 추가하려 했지만 Docker Hub 타임아웃으로 실패했다.
    • 10:52 UTC 에 노드 롤오버 스크립트를 다시 돌려 새 노드를 추가했고, 11:01 UTC 에 로드밸런서가 새 노드를 정상으로 판단해 트래픽을 다시 보냈다.
    후속 조치
    • 롤오버 절차를 문서로 남기고, 특히 롤오버가 잘못됐을 때 할 수 있는 일을 적는다.
    • 롤오버 절차를 개선할 방법을 찾는다.
    • QA 시험에 fluentd 로그 수집을 넣어 로그가 처음부터 끝까지 전달되는지 확인한다.
    • fluentd 가 보내는 로그 데이터가 부족하거나 없을 때 울리는 경보를 추가한다.
    • 스테이징 환경을 만든다.
    • 잘못된 컨테이너 런타임을 고르지 못하게 막는 장치를 넣었다.
    교훈

    상황이 심각해져도 침착해야 한다. 서둘러 고치다 피해를 키우기보다 알려진 정상 설정으로 롤백하는 편이 낫다. 새 워커 노드를 띄우는 일은 cloudinit 스크립트의 어느 단계도 실패하지 않는다는 전제에 크게 기대고 있다.

  3. 증상

    어느 저녁 데이터센터 OpenStack 의 네트워크 하위 시스템을 업그레이드한 뒤 Kafka 연결이 몇 시간 동안 간헐적으로 끊겼다. 개발 환경 워크로드 약 2,000개를 올린 큰 쿠버네티스 클러스터에서 노드들이 쿠버네티스에 비정상이라고 보고하기 시작했다.

    촉발

    OpenStack 의 네트워크 하위 시스템을 업그레이드하다가 예상과 달리 네트워크가 몇 시간 동안 끊겼고, Kafka 에는 간헐적으로만 닿았다. 그러자 모든 워크로드에 딸린 로깅 사이드카가 한꺼번에 깨어나 노드의 Docker 데몬에 높은 부하를 주었다.

    원인
    구성 요소
    기여 요인
    조치
    • Consul 의 gossip 암호화를 켜서 오염된 gossip 메시에서 오는 메시지를 바로 거부하게 했고, 이것으로 Consul 과 Vault 를 되살렸다.
    • 배포 엔진을 안정시킨 뒤 암호화 설정을 반영하려고 개발 환경 전체를 다시 배포했고, 암호화가 설정되지 않은 인스턴스는 종료했다.
    • 큰 클러스터를 다루는 수정이 들어간 Consul 1.2.3 으로 제자리 업그레이드했고, UI 버그 때문에 최종적으로 1.3.0 으로 올렸다. 운영 환경의 오염된 gossip 메시도 이 업그레이드로 빠르게 정리됐다.
    후속 조치
    • 노드의 워크로드가 함께 쓰는 Docker 데몬은 깨지기 쉬운 장애 지점이므로, 데몬 하나의 장애가 미치는 범위를 줄이는 데 더 힘쓴다. 작은 클러스터를 여러 개 두는 방침과 같은 방향이다.
    교훈

    글쓴이는 작은 클러스터를 여러 개 두라는 자신의 원칙이 옳았다고 확인했다. 더 작은 개발 클러스터와 운영 클러스터의 워크로드는 큰 클러스터처럼 영향을 받지 않았고, 개발과 운영이 한 클러스터에 있었다면 훨씬 큰 일이 났을 것이다. 노드의 워크로드가 함께 쓰는 Docker 데몬은 깨지기 쉬운 장애 지점이다. 워크로드마다 자기 로깅 사이드카와 메트릭 사이드카를 두는 방식이 옳다고도 확신하게 됐다. 이것들이 클러스터 공용 자원이었다면 문제가 거의 틀림없이 더 커졌고 고치기도 훨씬 어려웠을 것이다.

  4. 증상

    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 와 디스크 공간이 모두 모자랐다. 새로 만드는 파드 수를 조절할 수단이 있으면 문제를 풀지는 못해도 위험을 줄일 수 있고, 무언가 잘못됐을 때 제 손으로 클러스터를 마비시키는 일을 막을 수 있다.

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

이 6건에서 가장 많이 나오는 구성 요소: 컨테이너 런타임, 텔레메트리 에이전트. 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 가 됐다

unknown1건

조직
  1. IL-0087 RKE2 클러스터 노드를 재부팅한 뒤 Multus 가 쿠버네티스 API 에 닿지 못해 파드가 IP 를 받지 못했고, 같은 장애가 모든 노드로 번져 전체 서비스가 멈췄다.

의존성 장애1건

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