Incident Library
적용된 필터 구성 요소쿠버네티스 API 서버증상컨트롤 플레인 지연모두 풀기검색어 없이 필터만 적용한 목록입니다. 최근 사례부터입니다.
추천 필터 검색하면 검색어에서 찾은 분류 값이 여기에 나옵니다.

그래프

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

사례8건

8건 중 1~5번째

  1. 증상

    10월 17일부터 fra3 리전에서 패킷이 드문드문 버려지기 시작했다. 처음 이틀은 TCP 와 QUIC 의 재전송이나 컨트롤 플레인의 재시도로 대부분 넘어갔지만, 시스템이 조금씩 불안정했다. 이런 실패는 비결정적이라 겉으로 잘 드러나지 않았다.

    촉발

    fra3 에서 베어메탈 업체의 vSwitch 를 지나는 패킷이 무작위로 드문드문 버려지기 시작했다. 두 번째 장애는 컨트롤 플레인 노드 하나의 느린 NVMe 가 쿠버네티스의 변경 속도를 더는 따라가지 못하면서 일어났다.

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

    패킷 드롭은 비결정적이라 바로 보이지 않았다. 주요 상호작용에 잡아 둔 백분위 지연 SLO 의 에러 버짓이 줄어드는 것을 보고 영향을 알아챘다.

    조치
    • fra3 의 고객 트래픽을 모두 다른 리전으로 돌렸다.
    • vSwitch 대신 Wireguard 로 업체의 물리 머신 하나하나를 zrh1 클러스터에 연결했다.
    • 각 머신을 새 신원, 새 인증서, 새 저장 데이터 암호화 키로 다시 깔았고, 복구를 앞당기려고 캐시를 버렸다.
    • 팀 일부가 데이터셋을 더 분산된 방식으로 복제해 머신을 다시 까는 작업을 앞당겼다.
    • 준비된 머신을 묶음으로 새 리전에 넣고, 충분히 모이자 리전을 컴퓨트 풀에 다시 넣었다.
    • 두 번째 장애에서 워크로드를 zrh1 밖으로 돌렸다.
    • 실패하던 컨트롤 플레인 노드의 핵심 상태를 더 큰 노드로 복제하고, 새 노드가 같은 IP 주소로 옛 노드의 역할을 넘겨받게 했다.
    후속 조치
    • 장애 동안 실행된 모든 인스턴스의 요금을 고객에게 크레딧으로 환급했다.
    • 비슷한 상황이 다시 와도 고객에게 영향을 주지 않도록 백업 리전과 대안을 만든다.
    교훈

    비결정적인 네트워크 드롭은 재시도에 가려져서 SLO 기반 모니터링으로 긴 시간을 봐야 영향이 드러난다. 핵심 인프라의 문제를 직접 고칠 수단을 갖고 있어야 한다. 큰 장애 직후에는 같은 종류의 원인에 매이기 쉽다. 이번 두 번째 장애는 전혀 다른 종류였다. 미리 해 둔 모의 위기 훈련 덕분에 대응을 바로 체계적으로 시작할 수 있었다.

  2. 증상

    운영 EKS 클러스터가 읽기 전용 상태가 됐다. etcd 데이터베이스 공간이 한도를 넘자 API 서버가 새 파드 생성이나 디플로이먼트 스케일 조정처럼 객체를 바꾸는 요청을 모두 거부했다. 글쓴이는 이를 P1 장애로 다뤘다.

    촉발

    Kyverno 1.12 가 ephemeralreports 객체를 너무 많이 만들어 etcd 에 쌓았다.

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

    클러스터가 읽기 전용이 되어 쓰기 요청이 거부되면서 드러났다. 글쓴이는 kube-apiserver 감사 로그에서 mvcc: database space exceeded 를 찾는 CloudWatch Logs Insights 쿼리로 오류가 처음 나온 시각을 확인하는 방법을 소개했다.

    조치
    • AWS 의 EKS 팀과 etcd 팀이 8GB 와 10GB 이던 etcd 저장 공간을 12GB 로 늘려 잠금을 풀었다.
    • AWS 엔지니어가 여러 승인을 거친 뒤, 정리되지 않고 쌓인 ephemeralreports 객체를 etcd 에서 직접 지웠다.
    후속 조치
    • apiserver_storage_size_bytes 지표로 etcd 데이터베이스 크기를 모니터링해 8GB 한도에 닿지 않게 한다.
    • Kyverno 1.12 를 쓰고 있다면 ephemeralreports 가 쌓이는 문제를 고친 v1.12.4 로 업그레이드한다. ephemeralreports 가 계속 생기면 admission 이벤트 보고를 끄거나 --aggregationWorkers 를 늘린다.
    교훈

    EKS 의 etcd 데이터베이스 한도는 8GB 다. 한도를 넘으면 클러스터가 읽기 전용이 되고, 컴팩션도 막혀 객체를 지워 공간을 되찾을 수 없다. 글쓴이가 관찰한 바로는 객체를 지우는 스크립트도 etcd 가 잠기기 전에만 통한다. 그러므로 etcd 크기를 모니터링하고 8GB 에 절대 닿지 않게 해야 한다. EKS 에서는 etcd 에 직접 접근할 수 없어 잠긴 etcd 를 스스로 풀 수 없다. AWS 지원팀에 의존해야 하고, 해결 방법을 알아도 실행되기까지 오래 걸릴 수 있다. apiserver_storage_objects 지표로 리소스 종류별 객체 수를 보면 무엇이 etcd 공간을 차지하는지 찾을 수 있다.

  3. 증상

    2024년 2월 13일 01:04 CET 에 FR-PAR 리전의 Kubernetes API 에서 RAM 과 CPU 사용량이 치솟아 OOM 이 났다. 노드들이 컨트롤 플레인에 인증하지 못해 일부가 "Not Ready" 상태가 됐다.

    촉발

    2월 12일 새 쿠버네티스 릴리스가 모든 사용자에게 나온 뒤, 12일에서 13일로 넘어가는 밤에 많은 클러스터가 동시에 자동 업그레이드를 시작했다.

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

    타임라인의 첫 기록은 01:04 CET 다. 이때 Kubernetes API 의 RAM 과 CPU 사용량이 치솟아 OOM 이 났고, 노드들이 컨트롤 플레인에 인증하지 못해 일부가 "Not Ready" 가 됐다. 기록된 첫 조치는 42분 뒤인 01:46 에 API 자원을 늘린 일이었다.

    조치
    • Kubernetes API 에 배정한 자원을 01:46 과 02:20 두 차례 늘렸다.
    • 02:30 에 API 트래픽을 제한해 들어오는 트래픽을 고르게 만들고 혼잡을 줄였다.
    • 03:20 부터 트래픽 제한을 50-100 개 배치로 나눠 차례로 풀어 노드들이 다시 인증하고 "Ready" 가 되게 했다.
    • 03:40 에 API 혼잡 중에 만들어진 고장 노드를 교체하는 스크립트를 돌렸다.
    • 15:45 부터 노드 인증이 한꺼번에 몰리지 않게 일부 클러스터부터 예전 인증 방식으로 차례로 롤백했고, 2월 19일 모든 클러스터에서 롤백을 마쳤다.
    • 노드 인증이 동시에 몰릴 수 있는 클러스터 업그레이드와 설정 갱신 기능을 2월 20일 10:30 까지 껐다.
    후속 조치
    • Kubernetes API 자원 배정을 늘렸다.
    • 예전 인증 방식으로 롤백했다.
    • 노드에 로컬 인증 캐시를 둔다.
    • 부하가 치솟을 때 더 잘 버티도록 자원 배정 전략을 다시 짠다.
    • 쿠버네티스에 새 요청 큐잉 방식을 넣는다.
    • 높은 부하나 장애가 다른 구성 요소로 번지지 않게 구성 요소를 서로 분리한다.
    • 몇몇 지표를 꼼꼼히 지켜봐 이상 패턴을 더 일찍 찾는다.
    • 이 기간에 노드를 배포했지만 제대로 쓰지 못한 고객에게 환불한다.
    교훈

    고객의 클러스터와 노드가 빠르게 늘면서 기존 트래픽 제어로는 혼잡을 막기 어려워졌다. 많은 클러스터의 자동 업그레이드가 한 번에 시작되면 Kubernetes API 에 부하가 몰리고, 계속 실패하고 재시도하는 노드 인증 방식이 혼잡을 더 키운다. 1월 24일 장애 뒤 넣은 단기 완화 조치로는 재발을 막지 못했다.

  4. 증상

    2023년 3월 14일 19시 UTC 직후 엔지니어가 Old Reddit 이라 불리는 레거시 스택을 돌리는 클러스터의 업그레이드를 시작했다. 2분쯤은 괜찮아 보였지만 곧 사이트 전체가 갑자기 멈췄다. CDN 엣지의 상태 코드별 RPS 그래프가 이를 보여 주었다. 사용자는 오류 페이지나 글이 하나도 없는 홈페이지를 보았다.

    촉발

    Reddit 에서 가장 중요한 클러스터 가운데 하나인 레거시 클러스터를 쿠버네티스 1.23 에서 1.24 로 업그레이드했다.

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

    업그레이드를 시작하고 2분쯤 뒤 CDN 엣지의 상태 코드별 RPS 그래프에서 사이트가 멈춘 것이 보였다. 팀은 곧바로 장애를 선언했고 3분 안에 대응 인원이 통화에 모였다. 엣지 지표는 일부러 클러스터와 분리되어 있어 살아 있었지만, 클러스터 자체의 지표는 모두 사라졌다.

    조치
    • API 서버에서 타임아웃을 내던 Open Policy Agent 의 웹훅 설정을 지웠다.
    • 복원 뒤 어차피 쓸 수 없게 될 워커 노드를 모두 종료했다.
    • 컨트롤 플레인 노드 두 대를 종료하고, 남은 한 대의 구성 요소를 다운그레이드한 뒤 그 노드에 백업 데이터를 복원했다.
    • 단일 노드 컨트롤 플레인이 부하에 무너지지 않도록 클러스터 오토스케일러를 껐다.
    • 새 컨트롤 플레인 노드를 띄우고, 호스트명이 맞지 않던 TLS 인증서를 새로 만들어 노드들을 합류시켰다.
    • 트래픽을 1% 에서 시작해 5%, 10%, 20%, 35%, 55%, 80%, 100% 로 조금씩 늘렸다.
    • 트래픽이 돌아올 때 문제를 일으키지 않도록 손으로 멈춰 두었던 민감한 레거시 서비스를 조심스럽게 다시 켰다.
    후속 조치
    • 클러스터 구성을 코드로 관리해 모든 선택에 기록이 남게 하고, 코드로 만들 수 없는 것은 자세히 문서로 남긴다.
    • 클러스터마다 다른 맞춤형 구성을 걷어 내고 모든 클러스터의 구성 요소를 표준화한다.
    • 모든 클러스터를 최대한 같은 모습으로 유지하고 필요하면 다시 만들거나 복제할 수 있도록 클러스터 전체의 수명 주기를 관리하는 도구를 만든다.
    • 믿고 테스트에 쓸 수 있는 프리프로덕션 클러스터를 더 둔다.
    • 백업 복원 절차를 개선하고 클러스터 업그레이드를 안전하게 만든다.
    교훈

    쿠버네티스 버전과 구성 요소 업그레이드는 여전히 위험하다. 미리 테스트하고 검증해도 이번처럼 처음 보는 방식으로 깨질 수 있다. 쿠버네티스에는 공식 다운그레이드 절차가 없어, 롤백하는 방법은 백업에서 복원하는 것뿐이다. 복원 절차가 환경 변화를 따라가지 못하면 실제 장애 때 그 자리에서 고쳐 써야 하고, 복원을 결정하기까지 오래 망설이게 된다. 이번 복원은 결국 성공했지만 절차는 개선해야 한다. 코드로 남기지 않은 설정은 아는 사람이 떠나면 아무 기록도 남지 않는다. 라우트 리플렉터 설정이 어디에도 커밋되어 있지 않아 장애 중에 누구도 의심하지 못했다. 지표가 클러스터 안에서만 수집되면 클러스터가 망가질 때 함께 사라진다. 이번에는 로그 수집 에이전트가 영향을 받지 않아 원인을 추적할 수 있었다. 클러스터마다 다른 맞춤형 구성이 쌓이면 장애가 잦아진다. 직접 원인은 노드 레이블이었지만 근본 원인은 일관성 부족이었다.

  5. 증상

    2022년 5월 10일 낮 12시 EST 에 헬스체크 시스템이 경보를 울렸다. EU 리전의 백엔드 API, 프런트엔드, 터널이 모두 내려가 있었다. 처음에는 클라이언트 쪽에서 요청이 끊겼거나, 메모리나 CPU 사용량 때문에 축출된 서버에 요청이 닿은 일시적 오류라고 생각했다. 메인 대시보드가 내려간 것을 보고 바로 대응을 시작했다.

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

    헬스체크 시스템이 서비스가 내려갔다는 첫 알림을 보냈다. 팀은 처음에 일시적 오류로 보고 자동 복구를 기대했지만, 메인 대시보드가 내려간 것을 확인하고 바로 대응을 시작했다.

    조치
    • 인증서 교체가 노드를 다시 만들지 않아 13시 20분 노드 풀을 손으로 다시 만들었다.
    • 14시 30분에는 이미 메인 클러스터의 서비스를 새로 만든 GKE 클러스터에 복제하고 있었다.
    • 16시 50분 기존 클러스터에서 쿠버네티스 Service 레코드를 지워 로드 밸런서를 새 클러스터에 붙일 수 있게 했다.
    • 17시 30분 StatefulSet 을 기존 클러스터에서 떼어 내고 모든 쓰기를 메인 디스크로 돌렸다.
    • 18시 30분 임시 ClickHouse 인스턴스의 데이터를 내보내 메인 인스턴스에 다시 넣었다.
    후속 조치
    • 디스크 데이터를 복잡하게 옮기지 않고도 클러스터 사이를 빠르게 바꿀 수 있도록 배포 매니페스트를 고쳤다.
    교훈

    기존 인프라를 살리는 작업에는 시간 상한을 정해야 한다. 장애 내내 서비스가 곧 살아날 것처럼 보였지만, 기존 클러스터를 훨씬 일찍 포기하고 새 클러스터에서 다시 시작했어야 했다. 이미 들인 노력이 아까워 살리기를 멈추지 못한 것이 판단을 늦췄다. 오래된 GKE 클러스터라면 클러스터 CA 인증서의 유효기간을 `gcloud container clusters describe <cluster name> --zone europe-north1-a --format "value(masterAuth.clusterCaCertificate)" | base64 --decode | openssl x509 -text | grep Validity -A 2` 로 확인할 수 있다.

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

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

원인별6

클라우드 제공자 장애1건

조직
  1. IL-0084 베어메탈 업체 vSwitch 의 패킷 드롭으로 Namespace 의 fra3 리전이 빠져 전 세계 용량이 모자랐고, 다음 날에는 컨트롤 플레인 노드의 느린 NVMe 쓰기로 쿠버네티스 API 서버 CPU 가 치솟아 zrh1 이 멈췄다.

소프트웨어 결함1건

  1. IL-0077 Kyverno 1.12 가 만든 ephemeralreports 객체가 쌓여 EKS 의 etcd 데이터베이스가 한도를 넘었고 운영 클러스터가 읽기 전용이 되어 모든 쓰기가 거부됐다

용량 한계3건

  1. IL-0168 새 쿠버네티스 릴리스 뒤 많은 Kapsule 클러스터가 동시에 자동 업그레이드되면서 Kubernetes API 가 과부하로 OOM 이 났고, 새 노드 인증 방식의 재시도가 혼잡을 키워 노드가 Not Ready 가 됐다.
  2. IL-0002 빌더 파드가 노드 한 대에 몰리자 kubelet 이 기본 API QPS 한도에 막혀 파드 상태를 늦게 갱신했고, CI 빌드가 AWS IAM 자격 증명을 받지 못해 실패했다
  3. IL-0075 클러스터가 EC2 인스턴스 약 290대로 커지자 노드마다 도는 Datadog 에이전트가 쿠버네티스 API 를 폴링하면서 API 서버가 CPU 와 메모리를 다 써 쿠버네티스 컨트롤 플레인을 쓸 수 없게 됐다.

업그레이드로 깨진 호환성1건

조직
  1. IL-0060 쿠버네티스 1.24 업그레이드로 node-role.kubernetes.io/master 레이블이 사라지자 이 레이블에 기대던 Calico 라우트 리플렉터가 동작을 멈춰 레거시 클러스터의 네트워크가 모두 끊기고 Reddit 이 314분 동안 멈췄다
    Reddit2023

인증서·자격 증명 만료1건

  1. IL-0113 한 번도 교체되지 않은 GKE API 서버 인증서 때문에 메인 클러스터의 컨트롤 플레인이 망가져 EU 리전의 백엔드 API, 프런트엔드, 터널이 모두 멈췄다

설정 변경1건

조직
  1. IL-0108 워크숍 중 운영 클러스터에 적용한 Alcide admission 컨트롤러 때문에 Deployment 생성과 수정이 타임아웃되었다
    DFDS2020