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

사례46건

46건 중 24~28번째

  1. 증상

    GKE 를 1.22 이상으로 업그레이드한 뒤 Calico 네트워크 정책을 쓰는 클러스터에서 파드가 Terminating 이나 Pending 상태에서 빠져나오지 못했다. 실제로 파드가 멈춘 클러스터는 소수였다.

    촉발

    Calico 네트워크 정책을 켠 GKE 클러스터를 1.22 이상 버전으로 업그레이드했다.

    원인
    구성 요소
    기여 요인
    –
    조치
    • 1.24.4-gke.800 에 수정을 넣고 1.23 과 1.22 로 백포트했으며, 고객이 수정 버전으로 직접 업그레이드할 수 있게 했다.
    • 영향받는 버전의 고객에게 Google Cloud 지원팀을 통해 내부 패치를 적용받도록 권했다.
    • kubelet 과 calico-node 를 재시작해 멈춘 파드를 풀어 주는 우회책을 안내했다.
    • Calico 가 꼭 필요하지 않은 고객에게는 Calico 네트워크 정책을 끄는 우회책을 안내했다.
    후속 조치
    • 1.22 나 1.23 을 쓰는 RAPID, REGULAR, STABLE 릴리스 채널의 클러스터를 앞으로 몇 주에 걸쳐 수정 버전으로 자동 업그레이드한다.
    교훈

    클러스터 오토스케일러를 쓰면 이 경쟁 조건에 걸릴 확률이 높아진다. 수정 버전으로 올리기 전에는 kubelet 과 calico-node 를 재시작해 멈춘 파드를 풀 수 있고, Calico 가 꼭 필요하지 않다면 Calico 네트워크 정책을 끄는 방법도 있다.

  2. 증상

    DevOps 팀이 아직 운영 트래픽을 받지 않는 notification-preferences 마이크로서비스의 `resources.requests.cpu` 를 2에서 1로 줄였다. 작업을 마치고 몇 분 뒤 메모리 사용량이 90% 를 넘었다는 경보가 왔다. 메모리 할당량이나 JVM 의 GC 관련 인자는 건드리지 않은 상태였다.

    촉발

    리소스 최적화 작업 중 notification-preferences 디플로이먼트의 `resources.requests.cpu` 를 2에서 1로 줄였다. CPU limit 은 설정하지 않은 상태였다.

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

    CPU requests 를 줄이고 몇 분 뒤 메모리 사용량이 90% 를 넘었다는 경보가 울렸다.

    조치
    • JVM 옵션에 `-XX:ActiveProcessorCount=1` 을 넣어 JVM 이 쓸 CPU 수를 강제로 지정했다. 자원을 다시 늘리거나, CPU limit 을 걸거나, requests 를 1001m 이나 999m 으로 두는 방법은 각각 문제가 있어 고르지 않았다.
    후속 조치
    • 이 문제를 사내 공지로 알렸다.
    교훈

    cgroup v1 환경에서 JVM 은 `cpu.shares` 값이 정확히 1024 일 때 이를 설정 없음으로 보고 노드의 CPU 수를 쓴다. CPU limit 없이 requests 만 1로 준 JVM 파드는 노드가 클수록 스레드를 많이 띄우고 메모리를 더 쓴다. 이 문제는 쓸 수 있는 CPU 수로 스레드 수를 정하는 WebFlux 같은 프레임워크에서 특히 크게 드러난다. 이런 설정이라면 `-XX:ActiveProcessorCount` 나 CPU limit 으로 CPU 수를 명시해야 한다. Hyperconnect 는 원래 운영 JVM 애플리케이션에 CPU requests 를 2 이상 주었고, 마이크로서비스가 늘어 자원을 아끼려다 이 문제를 만났다.

  3. 증상

    2022년 6월 2일 10:00 CET 부터 mybinder.org 가 새 파드를 하나도 띄우지 못했다. 21:00 에 사용자가 Matrix 채널에 Binder 장애를 알렸고, 팀원이 살펴보니 몇 시간째 파드가 뜨지 않고 있었다.

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

    21:00 에 사용자가 Matrix 채널에 Binder 장애를 알렸고, 팀은 이 채널에서 소식을 받았다. 이를 본 팀원이 확인해 보니 몇 시간째 파드가 뜨지 않고 있었다. 큰 장애를 알아채기까지 11시간이 걸렸다.

    조치
    • 21:24 에 gke-resource-quotas 를 지웠고, 곧바로 배포가 파드를 다시 만들 수 있게 돼 launch 성공률이 금방 100%로 돌아왔다.
    후속 조치
    • 가동 시간 감시와 알림 문제를 이슈 https://github.com/jupyterhub/mybinder.org-deploy/issues/611 에서 다룬다.
    교훈

    Binder 에 큰 장애가 났다는 것을 알아채기까지 11시간이 걸렸다. resource quota 객체를 지우자 시스템이 아주 빨리 바로잡혔고, 지울 객체를 알고 나면 고치는 일은 비교적 간단했다. 변경할 기술과 권한을 가진 팀원이 현지 시각 밤 11시에 마침 컴퓨터 앞에 있었던 것은 운이었다.

  4. 증상

    KateSQL 의 인스턴스 교체 작업에서 MySQL 파드 생성 시간이 10분에서 30분까지 들쭉날쭉했다. 일부 MySQL 파드는 데이터가 같은 다른 파드보다 시작과 종료가 훨씬 느렸고, 설정 변경이나 업그레이드 같은 유지 보수 때 MySQL 인스턴스를 빨리 교체하기 어려워졌다.

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

    KateSQL 인스턴스 교체 작업에서 MySQL 파드 생성 시간이 10분에서 30분까지 들쭉날쭉한 것을 보고 알았다.

    조치
    • 옛 노드를 cordon 하고, KateSQL 인스턴스 교체로 MySQL 파드를 새 노드로 옮기며 GKE 오토스케일러가 노드를 늘리게 한 뒤, 옛 노드를 drain 해 클러스터를 줄였다. 새 MySQL 파드의 성능이 좋아졌다.
    • `echo 1 | sudo tee /sys/fs/cgroup/memory/kubepods/memory.force_empty` 로 kubepods cgroup 이 죽은 cgroup 을 비우게 해 메모리 cgroup 수를 약 1800개로 줄였다. 재시작한 MySQL 파드는 80G 버퍼 풀을 5초 만에 초기화했다.
    • GKE 1.18 로 새 GKE 클러스터를 만들어 새 MySQL 파드를 그 클러스터에 띄웠다. 몇 주 동안 버퍼 풀 초기화 시간과 질의 성능이 고르게 유지됐다.
    교훈

    이번 조사는 Shopify 데이터베이스 플랫폼 그룹이 한 조사 가운데 가장 오래 걸린 축에 들었다. 문제의 성격, 재현의 어려움, 따를 만한 정해진 방법이 전혀 없었다는 점 때문에 근본 원인을 찾는 데 오래 걸렸다. 그래도 문제를 풀 방법은 여러 가지가 있었다.

  5. 증상

    2021-09-06 08:00 UTC 에 Kubernetes 의 모든 서비스가 404 를 내기 시작했다. 30분 전인 07:30 에는 노드를 자동으로 교체하는 롤오버가 시작됐다.

    촉발

    2021-09-01 11:34 UTC 에 형식이 잘못된 IngressRoute 가 Kubernetes 에 적용됐다. 이 매니페스트는 2.5 미만 Traefik v2 의 버그를 건드렸지만, 버그는 Traefik v2 파드가 모두 재시작된 뒤에야 드러났다. 2021-09-06 07:30 에 자동 노드 롤오버가 시작됐고, 08:00 에 모든 서비스가 404 를 냈다.

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

    08:00 UTC 에 모든 서비스가 404 를 내기 시작했고 08:05 에 원인 조사를 시작했다. 감지까지 5분이 걸렸다.

    조치
    • ALB 헬스체크 경로를 바꿔 08:15 에 ALB 대상을 healthy 로 되돌렸지만 404 는 멈추지 않았다.
    • 08:50 에 주 인그레스 컨트롤러를 Traefik v1 으로 되돌리기로 하고, 09:00 에 손으로 롤백했다.
    • 09:10 에 잘못된 IngressRoute 를 손으로 지워 근본 원인과 Traefik v2 버그를 확인했다.
    • 09:20 에 바꾼 내용을 업스트림에도 반영했다.
    후속 조치
    • 버그가 고쳐진 Traefik v2.5 로 올리고 버그가 사라졌는지 확인한다.
    • Traefik v2 헬스체크 경로를 더 믿을 만한 경로로 바꾼다.
    • 인그레스 컨트롤러를 클러스터 바깥에서 확인하는 liveness 점검을 둔다.
    • 워크로드를 나눠 장애가 번지는 범위를 줄이는 방안을 검토한다.
    • Traefik v2 API 에서 짧은 시간에 많은 변경이 일어나는지 모니터링하는 방법을 알아본다.
    • 노드 롤오버 중과 롤오버 뒤에 스모크 테스트를 돌리는 방법을 알아본다.
    교훈

    Traefik v2 는 오류를 드러내지 않고 실패해서 조사를 ALB 쪽으로 잘못 이끌었다. 공식 API 스키마도 잘못된 매니페스트 적용을 막지 못했다. 팀은 대응 과정에서 장애 관리자를 정했다면 도움이 됐을 것으로 봤다. 그리고 워룸 회의를 녹화하고, 대응에 참여하지 않는 사람은 글로만 제안하고, 일지를 남기자고 정리했다. 대응 초반에 각자의 생각과 직감을 짧게 나누는 시간도 갖자고 했다.

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

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

원인별1

소프트웨어 결함46건

  1. IL-0058 Argo CD 에서 여러 앱이 함께 선언한 네임스페이스가 force 동기화로 지워져 앱 약 97개가 Missing/OutOfSync 상태에서 빠져나오지 못했다.
  2. IL-0150 DynamoDB DNS 자동화의 경쟁 조건이 us-east-1 리전 엔드포인트의 DNS 레코드를 비워 DynamoDB 와 EC2 인스턴스 시작이 실패했고, 그 여파로 EKS, ECS, Fargate 의 컨테이너 시작과 클러스터 스케일링이 14시간 넘게 막혔다
  3. IL-0104 Istio 의 공격적인 DNS 캐시 갱신과 클라이언트 포트 재사용, kube-proxy 가 종료된 파드의 conntrack 항목을 정리하지 않는 문제, 2분짜리 UDP conntrack 기본 타임아웃이 겹쳐 CoreDNS 파드가 OOMKilled 됐다.
  4. IL-0171 Bottlerocket AMI 에 libdcgm.so 가 없어 GPU 노드의 AcceleratedHardwareReady 가 False 가 됐고, Karpenter 노드 자동 복구가 Ready 뒤 10~11분마다 GPU 노드를 교체하는 일을 끝없이 되풀이했다.
    Inflab2025
  5. IL-0147 AKS 202508 노드 이미지가 캐시되지 않은 쿠버네티스 바이너리를 받을 때 HTTP 프록시 설정을 쓰지 않아, 프록시 뒤에 있는 노드의 프로비저닝이 CSE 종료 코드 31 로 실패했다.
  6. IL-0247 쿠버네티스로 옮긴 검색 시스템 Manas 에서 요청 백만 건에 한 건이 평소보다 100배 느려졌다
  7. IL-0078 EKS 업그레이드 중 Terraform 으로 KMS 시크릿 암호화를 켜자 워커 노드의 IAM 권한이 빠져 운영 ZenML Pro 워크스페이스에 모두 접속할 수 없게 됐다
    ZenML2025
  8. IL-0053 Ingress NGINX Controller의 어드미션 웹훅이 인증 없이 열려 있어, 조작한 Ingress 객체로 NGINX 설정을 주입해 원격 코드를 실행하고 클러스터의 모든 Secret을 읽을 수 있었다
    Wiz2025
  9. IL-0233 eu-west1 에서 Managed Kubernetes 의 거의 모든 파드가 네트워크 연결을 잃었고 롤백으로도 돌아오지 않았다
    Nebius2025
  10. IL-0081 ingress-nginx 의 enable-serial-reloads 옵션이 NGINX 리로드 중에 엔드포인트 동적 갱신을 막아, 배포 중 트래픽이 이미 없는 파드로 가면서 API 요청이 타임아웃됐다.
    Cresta2025
  11. IL-0157 IP ACL 을 켠 LKE 클러스터에 새 노드가 붙지 못해 오토스케일링이 실패했다
    Linode2025
  12. IL-0138 nvidia-dkms-390 드라이버 빌드 실패로 망가진 커널 헤더가 몇 주 동안 방치됐다가, 정전 뒤 재부팅하자 하나뿐인 마스터 노드가 커널 패닉에 빠져 홈랩 쿠버네티스 클러스터가 6일 동안 멈췄다.
  13. IL-0347 FR-PAR-1 가용 영역에서 하이퍼바이저 약 25% 의 VPC 연결이 11분 동안 끊겼다
  14. IL-0495 쿠버네티스에서 도는 내부 로드 밸런서 일부가 헬스 체크 실패로 한꺼번에 내려가고 남은 인스턴스가 연결 폭증으로 무너졌다
  15. IL-0148 클러스터에 없는 노드를 가리키는 노드 어피니티를 가진 파드 하나 때문에 kube-scheduler 가 패닉에 빠져 AKS 클러스터에서 파드가 하나도 스케줄되지 않았다
  16. IL-0077 Kyverno 1.12 가 만든 ephemeralreports 객체가 쌓여 EKS 의 etcd 데이터베이스가 한도를 넘었고 운영 클러스터가 읽기 전용이 되어 모든 쓰기가 거부됐다
  17. IL-0161 앞선 API 업데이트가 의도대로 동작하지 않아 토론토 데이터센터에서 새 LKE 클러스터 프로비저닝이 타임아웃으로 사흘 넘게 실패했다.
    Linode2024
  18. IL-0173 Let's Encrypt 가 기본 체인을 바꾼 뒤 cert-manager 의 preferredChain 처리 버그로 만료된 DST Root CA X3 체인 인증서가 발급돼, 구버전 BoringSSL 을 쓰는 클라이언트가 개발 서버에 접속하지 못했다.
  19. IL-0065 Argo CD의 Redis 캐시가 기본으로 암호 없이 클러스터 안 모든 파드에 열려 있어, 캐시된 매니페스트를 바꿔치기해 클러스터를 장악할 수 있었다
    Cycode2024
  20. IL-0141 Workload Identity 를 쓰는 GKE 클러스터에서 gke-metadata-server 가 "Unable to sync sandbox" 디버그 로그를 대량으로 내 Cloud Logging 할당량을 소모하고 추가 요금이 나왔다
  21. IL-0151 us-east-1 의 Lambda 셀 하나가 처음 겪는 규모로 커지며 잠재 결함이 드러나 Lambda 호출이 실패했고, Lambda 에 기대는 EKS 의 새 클러스터 생성도 오류와 지연을 겪었다.
  22. IL-0174 Fluent Bit 2.0 으로 올린 로그 수집 사이드카 가운데 Kafka output 플러그인을 쓰는 컨테이너가 SIGSEGV 로 계속 재시작됐다.
  23. IL-0112 나중에 회수된 EKS 노드 AMI 로 노드를 교체한 뒤 노드가 PLEG is not healthy 를 보고하며 NotReady 를 오갔고 파드 네트워크 타임아웃이 났다
    DFDS2022
  24. IL-0139 Calico 네트워크 정책을 쓰는 GKE 클러스터를 1.22 이상으로 업그레이드하자 경쟁 조건 때문에 CNI 정리가 Unauthorized 로 실패해 파드가 Terminating 이나 Pending 에 멈췄다.
  25. IL-0175 JVM 파드의 CPU requests 를 1코어로 줄이자 JVM 이 노드의 CPU 36개를 인식해 Reactor Netty 스레드가 늘고 메모리 사용량이 경보 기준을 넘었다
  26. IL-0403 mybinder.org 의 prod hub 가 실제로는 넘지 않은 파드 quota 를 넘었다는 오류 때문에 새 파드를 만들지 못했다
  27. IL-0462 GKE 위 MySQL 파드 일부가 시작과 종료에 오래 걸려 KateSQL 인스턴스 교체가 느려졌다
  28. IL-0106 잘못된 IngressRoute 매니페스트가 Traefik v2 버그를 건드려 Traefik 파드가 모두 재시작된 뒤 Kubernetes 의 모든 서비스가 404 를 냈다
    DFDS2021
  29. IL-0032 mutating admission controller 의 JSON 패치 버그로 일주일 동안 새 코드가 배포되지 않았고, 운영 서비스 하나는 파드가 두 개만 남아 오류율이 치솟았다
    Airbnb2020
  30. IL-0146 Central India 에서 새로 만든 Azure CNI 클러스터의 VM 이 높은 값의 MAC 주소를 받으면서 bridge 모드 Azure CNI 의 오래된 버그가 드러나 터널 연결이 끊기고 kubectl exec 와 파드 간 통신이 타임아웃됐다.
  31. IL-0041 fluent-bit 이 오류 없이 멈춰 운영 노드 한 대의 애플리케이션 로그가 Elasticsearch 로 전혀 가지 않았다.
  32. IL-0029 CPU 한도를 건 컨테이너가 사용량이 한도에 한참 못 미치는데도 스로틀링되어 사용자 대면 서비스의 지연 시간이 늘었다.
    Buffer2020
  33. IL-0190 쿠버네티스 업그레이드로 etcd 리더가 있던 노드가 갑자기 종료된 뒤, Cortex distributor 두 개가 옛 리더와 맺은 TCP 연결이 멈춘 채 그 연결을 계속 써서 런던 리전 Hosted Prometheus 쓰기가 12분 동안 일부 실패했다.
  34. IL-0196 Redis Operator 로 레플리카를 늘리면서 메모리 한도를 낮추자 데이터를 가진 유일한 Redis 파드가 재시작됐고, Sentinel 이 빈 레플리카를 마스터로 올려 데이터가 모두 지워졌다.
    Palark2020
  35. IL-0012 CPU limit 과 커널 CFS 쿼터 버그로 파드가 과하게 스로틀링돼 헬스 체크가 실패하고 애플리케이션이 멈췄다
    Omio2020
  36. IL-0143 GKE 1.13 과 1.14 의 특정 버전으로 업그레이드한 노드에서 커널 패닉이 늘었다.
  37. IL-0062 GKE Ingress 뒤의 파드가 SIGTERM 을 받자마자 새 연결을 받지 않고 정상 종료해서 API 에 가끔 502 오류가 났다
  38. IL-0011 HAProxy 인그레스 템플릿이 백엔드 파드를 IP 순으로 정렬해 일부 파드에 요청이 몰리고 인그레스 컨테이너가 OOMKilled 됐다
  39. IL-0030 쿠버네티스 v1.7.4 클러스터에서 노드들이 한꺼번에 NotReady 가 되어 쓸 수 있는 노드가 20% 미만으로 줄었다.
  40. IL-0050 ndots:5, Alpine 의 musl 리졸버, Netty 4.1.30 의 DNS 처리 문제가 겹쳐 쿠버네티스 서비스가 클러스터 밖 Redis 호스트 이름을 반복해서 해석하지 못했다
  41. IL-0051 외부 업체의 로그 클라이언트가 새 컨테이너가 뜰 때마다 파일 디스크립터를 다시 열고 이전 것을 닫지 않아 쿠버네티스 노드가 too many open files 로 내려갔다
  42. IL-0074 워커 노드가 잇달아 Not Ready 에 빠지고 네트워크와 DNS 실패로 사이드카가 죽으면서, AirMap 플랫폼의 모든 서비스가 다섯 시간 동안 응답하지 않았다.
    AirMap2018
  43. IL-0504 mybinder.org 에서 사용자 파드가 지워지지 않고 쌓여 클러스터가 가득 차고 실행이 약 5시간 동안 실패했다
  44. IL-0038 kubelet 설정 변경을 롤링 업데이트하다 쿠버네티스 버그로 kubelet 이 올라오지 못해 한 클러스터의 노드가 NotReady 가 되고 파드 절반쯤이 축출됐다
    Oath2018
  45. IL-0072 etcd 쓰기 지연으로 API 서버가 오래된 데이터를 읽어 클러스터 상태가 두 가지로 번갈아 보였고, 주 운영 클러스터 전체가 약 4시간 멈췄다
  46. IL-0003 etcd 클러스터 재구성 뒤 쿠버네티스 버그로 linkerd 가 서비스 위치 갱신을 받지 못했고, linkerd 를 모두 재시작하자 엔드포인트가 없는 서비스를 파싱하지 못하는 오류가 드러나 플랫폼 전체가 멈췄다
    Monzo2017