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

사례35건

35건 중 21~25번째

  1. 증상

    PR 하나를 머지한 직후 InfluxDB Cloud 운영 환경 하나가 통째로 사라졌다. 쓰기와 읽기를 비롯한 모든 API 엔드포인트가 404 오류를 냈다.

    촉발

    팀원 한 명이 설정 파일에 새 객체 여러 개를 더하는 PR 을 올렸다. 그중 새 ArgoCD Application 과 AppProject 의 이름이 자동화 오류로 app02-cluster01 이 아니라 기존 것과 같은 app01-cluster01 로 정해졌다. 코드 리뷰에서도 app01 과 app02 의 차이를 알아채지 못해 PR 이 그대로 머지됐다.

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

    모니터링과 경보 시스템은 이 장애를 바로 잡아내지 못했다. 그래서 팀은 계획을 세워 복구하기 전에 먼저 변경을 되돌리려 했다. 팀이 장애를 무엇으로 알게 됐는지는 글에 나오지 않는다.

    조치
    • 머지된 PR 을 되돌리기 시작했다가 곧바로 멈췄다.
    • etcd 메타데이터 클러스터를 복원했다.
    • 지워진 쿠버네티스 객체를 다시 만들어 남아 있던 PersistentVolume 을 다시 쓸 수 있게 하고, StatefulSet 을 다시 만들었다.
    • Zookeeper 볼륨을 Velero 로 매시간 받아 둔 백업에서 복원했다.
    • 헬스 체크와 readiness 체크를 끈 채 Kafka StatefulSet 을 파드 하나씩 다시 만들었다.
    • 쓰기 선행 로그 역할을 하는 Kafka 로 다시 쓰기를 받고, 쓰기를 처리하는 컴포넌트의 레플리카 수와 메모리 request 와 limit 을 늘렸다.
    • 스토리지 파드를 다시 만들었다. 파드는 오브젝트 스토리지에서 데이터를 내려받아 인덱싱한 뒤 쓰기 선행 로그에 밀려 있던 데이터를 읽어 들였다.
    • ArgoCD, 쿼리, 대시보드, 예약 작업을 다시 켜고, 레플리카 수를 원래대로 돌린 뒤 최종 QA 점검을 했다.
    후속 조치
    • 상태를 되살리는 절차를 담은 런북을 만들었다. PVC 같은 쿠버네티스 객체는 지워졌지만 디스크와 볼륨에 데이터는 남아 있을 때 할 일을 자세히 적었다.
    • 모든 환경의 모든 볼륨이 PVC 객체가 지워져도 데이터를 유지하도록 설정했다.
    • 외부에 드러나는 장애를 다루는 절차를 개선했다.
    • 생성된 YAML 을 객체 하나당 파일 하나로 저장하도록 바꿨다. 예를 들어 etcd Service 는 v1.Service-(namespace).etcd.yaml 파일이 된다. 이제 이번과 같은 PR 은 새 객체를 더하는 변경이 아니라 기존 객체를 덮어쓰는 변경으로 보인다.
    • YAML 생성 도구가 중복 객체를 찾아 리뷰를 요청하기 전에 경고하도록 고쳤다. 파일 이름만 보지 않고, apiVersion 이 networking.k8s.io/v1beta1 과 networking.k8s.io/v1 처럼 달라도 네임스페이스와 이름이 같으면 같은 객체로 판단한다.
    • 모든 상태 저장 리소스와 ArgoCD 가 관리하는 Namespace 객체에 Prune=false 어노테이션을 달아, 설정이 잘못돼도 ArgoCD 가 지우지 않게 했다.
    • ArgoCD Application 에 FailOnSharedResource=true 옵션을 넣었다. 다른 Application 이 관리하거나 관리했던 객체를 바꾸려 하면 ArgoCD 는 변경을 적용하지 않고 동기화를 실패로 멈춘다.
    교훈

    무엇보다 모니터링과 경보가 장애를 바로 잡아내지 못했다. 그 탓에 팀은 계획된 복구 대신 롤백부터 시도했다. InfluxDB Cloud 인스턴스 일부나 전체를 잃었을 때 쓸 런북도 없었다. 상태 저장 애플리케이션은 변경을 되돌린다고 원래대로 돌아오지 않고, 데이터 없는 새 인스턴스가 생길 뿐이다. 이런 PR 은 시스템이 머지를 막았어야 했다. 볼륨을 Retain 으로 둔 데다 Telegraf 처럼 쓰기를 재시도하는 클라이언트가 있어서 데이터를 하나도 잃지 않았다.

  2. 증상

    2022-03-31 07:53 UTC 에 GitLab.com 웹 서비스의 50x 오류가 늘기 시작했고, 1분 뒤 당직 엔지니어가 오류율 증가 페이지를 받았다. 사용자에게는 GitLab.com 이 느려졌고 간헐적으로 500 오류 페이지가 떴다.

    촉발

    gitlab-com/gl-infra/k8s-workloads/gitlab-com!1643 머지 요청을 배포하는 파이프라인이 07:49 UTC 에 gprd-cny 로 배포를 시작했다. 이 변경에는 GitLab 차트 버전 업그레이드가 들어 있었고, 새 차트는 Prometheus ServiceMonitor, PodMonitor 설정과 관련된 변경으로 Kubernetes Service 와 Deployment 의 포트 이름을 바꿨다.

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

    07:53 UTC 에 50x 오류가 늘기 시작했고 07:54 에 PagerDuty 알림이 당직 엔지니어를 호출했다. 변경을 배포하던 엔지니어가 오류를 보고 그 변경과 연결해 원인을 짚었다.

    조치
    • 08:05 UTC 에 당직 엔지니어가 카나리 환경을 트래픽에서 뺐다가 08:25 에 다시 넣었다.
    • 08:15 에 cluster c 와 cluster d 배포 작업을 시작 전에 취소했다.
    • 08:51 에 HAProxy 에서 gprd-us-east1-d 클러스터를 뺐다가 08:56 에 다시 넣었다.
    • 09:31 에 최소 레플리카 수를 100 넘게 올리는 변경 !1650 을 머지했다.
    • 09:53 에 HAProxy 에서 gprd-us-east1-c 클러스터를 빼고, 09:57 에 이 클러스터에 !1643 을 배포한 뒤 10:07 에 다시 넣었다.
    • 10:19 에 최소 레플리카 상향을 되돌리는 변경 !1652 를 머지했다.
    후속 조치
    • 리전 클러스터 하나에서 트래픽을 통째로 안전하게 빼는 graceful drain 기능을 만든다.
    • PagerDuty 를 유지보수 모드로 바꾸는 ChatOps 명령을 만든다.
    교훈

    알림은 정확하게 울렸다. 원인이 바로 직전에 배포한 변경이라는 것을 알았기 때문에, 그 변경을 배포하던 파이프라인을 멈추는 것이 자연스러운 첫 대응이었다.

  3. 증상

    09:26 UTC 에 한 개발자가 HTTP 307 리다이렉트 응답이 유난히 많다고 알렸다. 특히 Okta 서비스에서 많았다. 6분 뒤인 09:32 UTC 에 온라인 예약 시스템이 다운됐다는 연락이 왔다.

    촉발

    Traefik v1 을 걷어 내는 마이그레이션 작업으로 08:22 UTC 에 AWS 로드밸런서가 새 Traefik v2 리버스 프록시로 요청을 보내도록 바뀌었다.

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

    09:26 UTC 에 한 개발자가 HTTP 307 리다이렉트가 많다고 보고하면서 문제가 드러났다. 특히 Okta 서비스에서 많았다. 변경 뒤 64분 만이었다. 09:32 UTC 에는 온라인 예약 시스템이 다운됐다는 연락을 받았다.

    조치
    • 조사보다 롤백을 먼저 하기로 하고 09:48 UTC 에 변경을 롤백했다.
    후속 조치
    • 중요한 공지가 더 잘 보이게 할 방법을 검토한다.
    • 시험에 쓴 ALB 를 각 팀에 알려 팀이 자기 시나리오를 직접 시험하게 했어야 하는지 검토한다. 이번에 멈춘 서비스는 ALB 앞에 CloudFront 가 있어서 그렇게 했어도 시험하기 어려웠을 수 있다.
    교훈

    Cloud Engineering 팀이 모든 시나리오를 시험할 수는 없었다. 팀은 자기 애플리케이션 몇 개로 몇 주 동안 시험했지만 Okta 로그인 흐름의 문제는 잡지 못했다. 마이그레이션 전후의 요청 헤더를 비교했다면 미리 알 수 있었을지도 모른다는 물음도 남았다.

  4. 증상

    2021년 8월 25일 Skyscanner 는 네 시간 반 동안 전 세계에서 완전히 멈췄다. skyscanner.net 웹사이트에 접속할 수 없었고 모바일 앱도 동작하지 않았다. 여행자와 비즈니스 파트너 모두 Skyscanner 를 쓸 수 없었다.

    촉발

    GMT 15:30 무렵 한 엔지니어가 앞으로 할 큰 변경을 준비하면서 템플릿 시스템에 변경을 올렸다. 시스템 동작은 바꾸지 않으려던 변경이었다. 셀 설정 루트 파일의 cell: {{ default $cluster.name $cluster.unique_name }} 줄을 cell: $cluster.name 으로 바꿨다. 변경은 동료 리뷰를 거쳐 master 에 머지됐고 자동으로 배포됐다.

    원인
    구성 요소
    기여 요인
    조치
    • 클러스터마다 올바른 설정을 되돌려 놓고, GitOps 로 클러스터가 스스로 올바른 상태로 돌아오게 했다.
    • 팀이 익숙하게 다루던 백업과 복원 절차로 서비스를 복원했다.
    • 리전 하나와 핵심 서비스를 먼저 복구해 GMT 20:30 무렵 리전 하나에서 모든 트래픽을 받았다.
    • 목요일과 금요일에 걸쳐 나머지 리전과 핵심이 아닌 서비스를 되살리고 확인했다.
    후속 조치
    • 이번처럼 드물게 쓰이는 변경 경로에서도 설정 변경을 전 세계에 한꺼번에 배포하지 않게 한다.
    • 템플릿과 로직이 들어간 설정을 코드로 다루고, 테스트와 린트를 도입한다.
    • 시나리오와 런북이 최악의 재해 규모까지 다루게 하고, 더 극단적인 상황을 워게임으로 연습한다.
    • 백업과 복원 절차를 검증한다. 필요할 때 백업을 실제로 꺼낼 수 있는지, 리전 하나가 내려간 경우에도 되는지 확인한다.
    • 새벽에 긴장한 엔지니어가 읽어도 맥락과 단계가 분명하고, 필요하면 여러 번 실행해도 결과가 같도록 런북을 고쳐 쓴다.
    • 이 설정을 리전마다 템플릿으로 찍어 낼 필요가 있었는지 다시 따지고, 리전마다 설정이 어긋날 위험과 자동화로 변경이 여러 리전에 한꺼번에 퍼질 위험 사이에서 균형을 찾는다.
    교훈

    설정에 템플릿과 로직을 넣는 순간 그 설정은 코드가 된다. 팀은 설정의 복잡도를 높이면서도 이 파일을 설정으로만 여겨 테스트도 린트도 두지 않았다. 전역 설정 배포를 막으려고 오래 공을 들였지만, 이 경로로 변경이 나가는 일은 아주 드물어서 미처 떠올리지 못했다. 시나리오와 런북은 이 정도 규모의 장애를 상정하지 않았다. 백업은 복원해 보기 전까지 백업이 아니다. 장애 대응을 지휘하는 인시던트 커맨더를 가장 경험 많은 사람이 맡아 누구도 탓하지 않고 상황을 이끈 것이 복구에 큰 도움이 됐다.

  5. 증상

    2021년 8월 24일 07:30 UTC에 웹 서비스의 지연 SLO 가 깨졌다. 웹 서비스의 Apdex 가 떨어졌고, 웹 프런트엔드로 가는 요청 일부가 잠시 느려졌다. Apdex 는 응답 시간이 목표 안에 든 요청의 비율로 계산하는 만족도 점수다.

    촉발

    웹 서비스를 VM 에서 쿠버네티스로 옮기면서 트래픽을 쿠버네티스 웹 파드로 넘겼다.

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

    07:30 UTC에 웹 지연 SLO 가 깨졌고, 10분 뒤인 07:40에 엔지니어가 Slack 에서 장애를 선언했다.

    조치
    • 웹 파드의 targetCPU 를 더 보수적인 값으로 낮추는 머지 요청 gitlab-com/gl-infra/k8s-workloads/gitlab-com!1149 를 머지했다.
    후속 조치
    • 목표 사용률을 조정하는 머지 요청 gitlab-com/gl-infra/k8s-workloads/gitlab-com!1149 를 재발 방지 조치로 올려 머지했다.
    교훈

    트래픽을 새 파드로 넘길 때 HPA 의 CPU 목표값이 너무 높으면 부하가 늘어도 파드가 제때 늘지 않는다. 팀은 목표값을 보수적으로 낮춰 이 문제를 풀었다.

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

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

원인별1

설정 변경35건

  1. IL-0179 DEBUG 로그가 쏟아지자 동기 로깅을 하던 요청 스레드들이 가득 찬 stdout 파이프에서 멈춘 채 DB 커넥션을 쥐고 있어, HikariCP 커넥션 풀이 고갈되고 요청이 30초 주기로 한꺼번에 실패했다.
  2. IL-0200 새로 띄운 쿠버네티스 노드가 호환되지 않는 etcd 버전으로 돌아 여러 운영 클러스터의 합의가 깨졌고, GitHub.com 의 git 작업과 웹 요청이 5XX 오류로 실패했다.
    GitHub2026
  3. IL-0063 Redis 스테이트풀셋을 다시 만들자 Redis 클러스터가 한꺼번에 재시작되며 일부가 망가졌고, 재연결 폭주로 백엔드가 OOM 으로 죽어 AdGuard VPN 이 약 50분 멈췄다.
  4. IL-0122 여러 핵심 서비스가 함께 읽는 설정에 잘못된 값이 들어가 ChatGPT 파드가 크래시 루프에 빠졌다
    OpenAI2025
  5. IL-0192 Crossplane 컴포지션의 병합 정책 변경이 Service 타입을 ClusterIP 로 바꿔 클라우드 로드 밸런서가 지워지고 Grafana Cloud 서비스의 약 25%가 끊겼다.
  6. IL-0005 새 텔레메트리 서비스가 모든 노드에서 무거운 쿠버네티스 API 요청을 보내 대형 클러스터의 컨트롤 플레인이 무너졌고, DNS 기반 서비스 디스커버리가 깨져 OpenAI 의 모든 서비스가 멈췄다
    OpenAI2024
  7. IL-0118 쿠버네티스 네임스페이스 라벨을 전역으로 바꾸자 네트워크 계층이 메타데이터를 다시 계산하면서 가장 큰 GPU 클러스터들 가운데 세 곳의 컨트롤 플레인이 과부하에 빠졌고, ChatGPT 와 API 가 타임아웃과 503 오류를 냈다.
    OpenAI2024
  8. IL-0130 내부 스토리지 프로비저닝 설정 오류로 Vertex Model Garden 의 100GB 넘는 대형 모델 배포가 13일 넘게 "Model server never became ready" 오류를 내며 실패했다.
  9. IL-0114 클러스터 용량을 늘리던 중 버전이 고정되지 않은 VPC CNI 플러그인이 자동으로 업데이트돼 새 파드가 IP 를 받지 못하고 Pending 에 머물렀고, 메인넷 운영 환경의 정산이 약 3.5시간 멈췄다.
  10. IL-0152 정비 작업 중 FRA1 내부 인프라 클러스터에 잘못된 설정이 들어가 그 위에서 돌던 DOKS 클러스터 200개의 컨트롤 플레인이 자동으로 삭제됐다.
  11. IL-0153 DOKS 1.27.6-do.0 과 1.28.2-do.0 워커 노드에서 매일 아침 도는 apt 자동 업그레이드가 15분 타임아웃에 걸려 강제 종료되면서 노드 네트워킹이 망가지고, 노드가 사흘 연속 NotReady 가 됐다.
  12. IL-0019 EKS 모듈 18 업그레이드로 새 노드의 디스크가 20Gb 로 줄어 이미지 풀이 no space left on device 로 실패했다
  13. IL-0017 live 클러스터 노드 6대에서 VPC CNI 가 IP 주소를 할당하지 못해 새 파드가 ContainerCreating 에 멈췄다
  14. IL-0091 Terraform 으로 노드 인스턴스 타입을 바꾸자 노드가 한꺼번에 교체되어 사용자 운영 파드가 모두 지워지고 서비스가 내려갔다
  15. IL-0068 익명 요청을 허용한 쿠버네티스 API 서버로 공격자가 들어와 RBAC 로 백도어를 만들고, DaemonSet 으로 Monero 채굴기를 모든 노드에 띄웠다.
  16. IL-0186 스토리지 구성 요소가 노드에 넣은 iptables REDIRECT 규칙 때문에 워커 노드 하나의 파드가 외부 HTTP 와 HTTPS 로 나가지 못했다.
  17. IL-0109 로그 수집을 고치려던 EKS 노드 롤오버가 꼬이면서 Auto Scaling 그룹이 정상 워커 노드를 모두 종료해 클러스터에 노드가 하나도 남지 않았다.
    DFDS2023
  18. IL-0116 CNI 설정 변경이 스테이징에 없던 하드웨어 종류와 호환되지 않아 GPU 클러스터 하나의 워크로드가 네트워크 연결을 잃었고, text-davinci-003 모델이 완전히 멈췄다.
    OpenAI2023
  19. IL-0177 다른 팀의 설정 배포로 공유 L7 HAProxy 가 재로드될 때마다 messaging-hub 의 웹소켓 연결이 한꺼번에 끊겼다.
    LINE+2022
  20. IL-0191 Loki distributor 서비스에 레이블 셀렉터가 하나 더 들어가 롤아웃 중 새 파드 몇 개에만 쓰기 트래픽이 몰렸고, 그 파드들이 OOM으로 죽으면서 로그 쓰기 경로가 약 25분간 멈췄다.
  21. IL-0009 ArgoCD Application 이름이 겹쳐 InfluxDB Cloud 운영 환경 하나가 통째로 삭제됐다
  22. IL-0208 GitLab Helm 차트 업그레이드가 Service 와 Deployment 의 포트 이름을 바꿔 GCP 로드 밸런서가 다시 구성되는 동안 GitLab.com 요청이 느려지고 50x 오류가 났다
    GitLab2022
  23. IL-0111 메인 인그레스 컨트롤러를 Traefik v2 로 바꾸자 X-Forwarded 헤더가 전달되지 않아 Okta 로그인이 깨졌고, DFDS 온라인 예약이 한 시간 넘게 멈췄다
    DFDS2021
  24. IL-0010 템플릿 중괄호가 빠진 설정 변경으로 ArgoCD 가 전 세계 모든 클러스터의 서비스를 지웠다
  25. IL-0209 웹 파드의 HPA CPU 목표값이 너무 높아 트래픽을 넘겨받는 동안 파드가 늘지 않았고, GitLab.com 웹 지연 SLO 가 약 15분 동안 깨졌다.
    GitLab2021
  26. IL-0105 VPC CNI 교체로 ALB 에서 타깃 그룹이 떨어져 나가 쿠버네티스 클러스터의 모든 서비스가 503 을 냈다
    DFDS2021
  27. IL-0108 워크숍 중 운영 클러스터에 적용한 Alcide admission 컨트롤러 때문에 Deployment 생성과 수정이 타임아웃되었다
    DFDS2020
  28. IL-0189 KIAM 이 준 15분짜리 AWS 자격 증명 때문에 쿠버네티스로 옮긴 Java 서비스가 요청마다 메타데이터 API 를 불러 지연이 최대 10배 늘었다.
  29. IL-0008 응답하지 않는 OPA 검증 웹훅 때문에 GKE 마스터 업그레이드가 멈추고 API 서버가 간헐적으로 끊기면서 노드가 끝없이 재생성됐다
  30. IL-0004 새 Cortex 클러스터에서 기본 우선순위를 받은 파드가 우선순위가 없는 운영 Ingester 를 연쇄적으로 선점해 Hosted Prometheus 쓰기가 실패했다
  31. IL-0061 Terraform 상태 파일이 리뷰 빌드에서 바뀐 데다 권한 차이까지 겹쳐 Terraform 이 운영 GKE 클러스터 세 개 중 두 개를 삭제했다
  32. IL-0066 ConfigMap 만 바꾸고 디플로이먼트는 그대로 둔 탓에 잘못된 설정이 몇 주 뒤 노드 교체 때 모든 브리지 파드에 퍼져 Pusher 의 모든 트래픽이 끊겼다
    Pusher2019
  33. IL-0052 인증 없이 인터넷에 열린 Weave Scope 대시보드를 통해 암호화폐 채굴기가 개발 클러스터와 스테이징 클러스터의 모든 노드에서 돌았다.
  34. IL-0035 ElastAlert 에 새로 넣은 알림 규칙 때문에 ElastAlert 파드가 메모리를 끝없이 써서 노드가 잇달아 NotReady 가 되었고, 같은 클러스터의 도구와 Grafana, Prometheus 가 함께 흔들렸다.
    NU.nl2019
  35. IL-0055 실패하는 CronJob 이 기본 concurrencyPolicy 때문에 겹겹이 쌓여 재시작하는 파드가 수천 개로 늘었고 클러스터가 내려갔다
    Target2018