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

사례28건

28건 중 13~17번째

  1. 증상

    2023-05-25 14:11 UTC 에 Linode 는 프랑크푸르트 데이터센터의 일부 LKE 사용자가 kubectl 로 자기 kube-apiserver 에 닿지 못한다는 것을 알게 되었다.

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

    Linode 는 14:11 UTC 에 문제를 알게 되었다. 백엔드 서비스가 실패하기 시작한 지 11분 뒤였다.

    조치
    • 메모리 한도를 올렸다.
    후속 조치
    • 영향받은 LKE 구성 요소의 복원력, 이중화, 모니터링을 늘린다.
  2. 증상

    Aqua 의 쿠버네티스 허니팟 클러스터에 공격이 들어왔다. 공격자는 Secret 목록을 조회하는 HTTP 요청 몇 개를 보내고, kube-system 네임스페이스의 리소스 목록을 조회하는 API 요청 두 개로 클러스터 정보를 모았다.

    촉발

    API 서버가 잘못 설정되어, 권한을 가진 익명 사용자의 인증 없는 요청을 받아들였다.

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

    Aqua 가 운영하는 쿠버네티스 허니팟에 들어온 공격을 기록하고 분석해 찾았다. 허니팟에 일부러 노출해 둔 AWS 액세스 키가 쓰이자 비컨 신호가 왔다.

    교훈

    API 서버에 익명 접근을 허용하는 설정 실수 하나로 클러스터 전체를 내줄 수 있다. 공격자가 ClusterRoleBinding 으로 지속적인 접근 경로를 만들어 두면 잘못된 설정을 고친 뒤에도 계속 들어올 수 있다. 공격자는 system:controller: 로 시작하는 정상 구성 요소 같은 이름과 kube-controller-manager 를 닮은 이미지 이름으로 감사 로그와 사람의 눈을 피한다. Aqua 는 Trivy 같은 도구로 취약점, 노출된 Secret, 잘못된 설정을 찾으라고 권한다.

  3. 증상

    일상적인 kube-apiserver 재시작 직후 etcd 메모리 사용량이 거의 세 배로 치솟았고, 그 여파로 모든 마스터 노드가 연쇄적으로 재시작했다. 고객사의 운영 클러스터였다.

    촉발

    일상적인 kube-apiserver 재시작 뒤, Vector 로그 수집기 DaemonSet 의 파드 전부가 캐시를 다시 채우려고 한꺼번에 파드 list 요청을 보냈다.

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

    kube-apiserver 재시작 직후 마스터 노드 전체 메모리와 etcd 메모리 그래프가 치솟고 마스터 노드가 연쇄적으로 재시작하면서 알았다. 원인이 된 DaemonSet 은 감사 로그를 보고 찾았다.

    조치
    • limit-list-custom 이라는 PriorityLevelConfiguration 을 만들어 요청 대기열을 설정했다. 값은 문서의 표준 설정을 그대로 썼다.
    • 같은 이름의 FlowSchema 를 만들어, 이 DaemonSet 서비스 어카운트가 보내는 파드 list 와 get 요청을 그 대기열로 보냈다.
    후속 조치
    • 쿠버네티스 Rust 라이브러리에 resourceVersion 설정을 넣는 PR 을 냈다.
    • Vector 로그 수집기 쪽에 이 문제를 고치는 PR 을 열었다.
    • Cilium CNI 에서도 비슷한 문제를 찾아 같은 방법으로 해결했다.
    교훈

    etcd 는 필드 셀렉터와 레이블 셀렉터를 모르기 때문에, kube-apiserver 에는 가벼워 보이는, 필터를 건 list 요청도 etcd 에서는 그 종류의 객체 전체를 읽는 일이 된다. 데이터가 꼭 최신이어야 하는 컨트롤러가 아니라면 resourceVersion=0 으로 kube-apiserver 캐시에서 읽게 할 수 있다. 다만 kube-apiserver 가 여러 대면 인스턴스마다 다른 데이터를 받을 수 있다. 여러 파드가 한꺼번에 보내는 요청은 Priority and Fairness 로 대기열에 넣어 kube-apiserver 와 etcd 를 지킬 수 있다. 위험한 것은 파드 요청만이 아니어서 Cilium CNI 에서도 비슷한 문제가 나왔다.

  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` 로 확인할 수 있다.

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

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

원인별9

자격 증명 유출1건

  1. IL-0069 공격자가 탈취한 서비스 어카운트 토큰으로 운영 쿠버네티스 클러스터에서 클라우드 백엔드와 금융 인프라까지 옮겨 가 암호화폐 거래소의 자금을 훔쳤다.

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

  1. IL-0183 kubeadm 으로 만든 클러스터의 1년짜리 인증서가 만료되어 kube-apiserver 가 etcd 와 TLS 연결을 맺지 못하고 재시작을 반복했고, 클러스터에 접속할 수 없게 됐다.
  2. IL-0113 한 번도 교체되지 않은 GKE API 서버 인증서 때문에 메인 클러스터의 컨트롤 플레인이 망가져 EU 리전의 백엔드 API, 프런트엔드, 터널이 모두 멈췄다
  3. IL-0184 kubeadm 클러스터의 API 서버와 내부 인증서가 만료돼 JupyterHub KubeSpawner 가 컨테이너를 만들지 못하고 kubectl 연결이 거부됐다
    dbhang2021

소프트웨어 결함5건

  1. IL-0138 nvidia-dkms-390 드라이버 빌드 실패로 망가진 커널 헤더가 몇 주 동안 방치됐다가, 정전 뒤 재부팅하자 하나뿐인 마스터 노드가 커널 패닉에 빠져 홈랩 쿠버네티스 클러스터가 6일 동안 멈췄다.
  2. IL-0077 Kyverno 1.12 가 만든 ephemeralreports 객체가 쌓여 EKS 의 etcd 데이터베이스가 한도를 넘었고 운영 클러스터가 읽기 전용이 되어 모든 쓰기가 거부됐다
  3. IL-0030 쿠버네티스 v1.7.4 클러스터에서 노드들이 한꺼번에 NotReady 가 되어 쓸 수 있는 노드가 20% 미만으로 줄었다.
  4. IL-0072 etcd 쓰기 지연으로 API 서버가 오래된 데이터를 읽어 클러스터 상태가 두 가지로 번갈아 보였고, 주 운영 클러스터 전체가 약 4시간 멈췄다
  5. IL-0003 etcd 클러스터 재구성 뒤 쿠버네티스 버그로 linkerd 가 서비스 위치 갱신을 받지 못했고, linkerd 를 모두 재시작하자 엔드포인트가 없는 서비스를 파싱하지 못하는 오류가 드러나 플랫폼 전체가 멈췄다
    Monzo2017

용량 한계9건

  1. IL-0204 Render 프랑크푸르트 클러스터에서 etcd 메모리 급증으로 컨트롤 플레인이 과부하에 걸렸고, 컨트롤 플레인 노드를 재부팅하자 그 위의 CoreDNS 가 다시 뜨지 못해 DNS 가 멈췄다.
    Render2024
  2. IL-0168 새 쿠버네티스 릴리스 뒤 많은 Kapsule 클러스터가 동시에 자동 업그레이드되면서 Kubernetes API 가 과부하로 OOM 이 났고, 새 노드 인증 방식의 재시도가 혼잡을 키워 노드가 Not Ready 가 됐다.
  3. IL-0195 200개가 넘는 노드의 고객 클러스터에서 Cilium 파드가 LIST 요청을 한꺼번에 쏟아내 kube-apiserver 가 메모리를 다 쓰고 죽기를 되풀이했다.
    Palark2023
  4. IL-0165 프랑크푸르트 LKE 의 백엔드 서비스가 메모리 부족으로 실패해 일부 사용자가 kubectl 로 kube-apiserver 에 접속하지 못했다
    Linode2023
  5. IL-0194 kube-apiserver 재시작 뒤 Vector DaemonSet 의 파드 list 요청이 한꺼번에 몰려 etcd 메모리가 세 배 가까이 늘고 마스터 노드가 연쇄적으로 재시작했다.
    Palark2023
  6. IL-0002 빌더 파드가 노드 한 대에 몰리자 kubelet 이 기본 API QPS 한도에 막혀 파드 상태를 늦게 갱신했고, CI 빌드가 AWS IAM 자격 증명을 받지 못해 실패했다
  7. IL-0076 dex의 AuthRequest 리소스가 끝없이 쌓였고, 이를 치우려고 네임스페이스를 지우자 목록 조회 타임아웃과 재시도가 반복되며 쿠버네티스 마스터가 내려갔다
  8. IL-0075 클러스터가 EC2 인스턴스 약 290대로 커지자 노드마다 도는 Datadog 에이전트가 쿠버네티스 API 를 폴링하면서 API 서버가 CPU 와 메모리를 다 써 쿠버네티스 컨트롤 플레인을 쓸 수 없게 됐다.
  9. IL-0031 API 서버가 OOMKill로 죽자 Skipper 인그레스가 라우트를 잃었고, 고객 트래픽이 끊기며 IAM 서비스에서 404 오류가 났다

설정 변경6건

  1. IL-0005 새 텔레메트리 서비스가 모든 노드에서 무거운 쿠버네티스 API 요청을 보내 대형 클러스터의 컨트롤 플레인이 무너졌고, DNS 기반 서비스 디스커버리가 깨져 OpenAI 의 모든 서비스가 멈췄다
    OpenAI2024
  2. IL-0118 쿠버네티스 네임스페이스 라벨을 전역으로 바꾸자 네트워크 계층이 메타데이터를 다시 계산하면서 가장 큰 GPU 클러스터들 가운데 세 곳의 컨트롤 플레인이 과부하에 빠졌고, ChatGPT 와 API 가 타임아웃과 503 오류를 냈다.
    OpenAI2024
  3. IL-0152 정비 작업 중 FRA1 내부 인프라 클러스터에 잘못된 설정이 들어가 그 위에서 돌던 DOKS 클러스터 200개의 컨트롤 플레인이 자동으로 삭제됐다.
  4. IL-0068 익명 요청을 허용한 쿠버네티스 API 서버로 공격자가 들어와 RBAC 로 백도어를 만들고, DaemonSet 으로 Monero 채굴기를 모든 노드에 띄웠다.
  5. IL-0108 워크숍 중 운영 클러스터에 적용한 Alcide admission 컨트롤러 때문에 Deployment 생성과 수정이 타임아웃되었다
    DFDS2020
  6. IL-0008 응답하지 않는 OPA 검증 웹훅 때문에 GKE 마스터 업그레이드가 멈추고 API 서버가 간헐적으로 끊기면서 노드가 끝없이 재생성됐다

클라우드 제공자 장애1건

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

DNS·네트워크 장애1건

기여 요인
–
  1. IL-0154 SFO3 코어 라우터의 라인 카드가 하드웨어 오류로 한꺼번에 재부팅된 뒤 게스트 네트워킹이 돌아오지 않은 DOKS 노드가 비정상으로 남아, 일부 클러스터의 연결과 컨트롤 플레인 접속이 01:40 UTC까지 불안정했다.

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

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

unknown1건

조직
  1. IL-0059 kubeadm이 만든 etcd 정적 파드의 liveness probe가 실패해 kubelet이 약 2분마다 etcd를 재시작했고, 단일 마스터 클러스터의 API 서버가 계속 끊겼다