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

사례14건

14건 중 7~11번째

  1. 증상

    2022-06-02 10:10 US/Pacific 부터 Vertex AI Online Prediction 의 오류율이 올라갔다. 리전과 사용 패턴에 따라 요청의 30% 에서 100% 가 실패했다.

    촉발

    잘못된 리소스 정리 작업이 Vertex 예측 엔드포인트를 전역에서 삭제된 것으로 표시했다.

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

    Google 은 13:58 US/Pacific 에 상태 페이지에 첫 공지를 올렸고, 이 공지는 문제가 10:20 US/Pacific 에 시작됐다고 적었다. 나중에 나온 짧은 장애 보고서는 시작 시각을 10:10 으로 적었다.

    조치
    • 삭제된 것으로 표시된 Vertex 예측 엔드포인트를 복구했고, 서비스가 완전히 회복됐다.
  2. 증상

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

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

  3. 증상

    Jetstack 은 europe-west1 에 있는 GKE 리전 클러스터의 마스터를 업그레이드하고 있었다. 이 개발 클러스터는 여러 팀이 낮 동안 앱을 시험하는 데 쓴다. GKE Terraform 파이프라인으로 업그레이드를 시작했는데, 마스터 업그레이드가 20분으로 잡아 둔 Terraform 타임아웃 안에 끝나지 않았다. GKE 콘솔에는 클러스터가 여전히 업그레이드 중으로 나왔다.

    촉발

    마스터 업그레이드 중 두 번째 마스터 인스턴스의 API 서버가 ca-registration PostStartHook 을 실행하면서 kube-system 의 extension-apiserver-authentication ConfigMap 을 갱신하려 했다. 이 요청은 설정해 둔 OPA 검증 웹훅의 백엔드가 응답하지 않아 타임아웃 났다.

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

    GKE Terraform 파이프라인으로 시작한 마스터 업그레이드가 20분으로 잡아 둔 Terraform 타임아웃 안에 끝나지 않은 것이 첫 신호였다. 파이프라인을 다시 돌리자 kube-apiserver 가 unhealthy 라는 오류가 났다. 원인은 Google Support 의 도움을 받아 찾았다.

    조치
    • API 서버에 간헐적으로 접근될 때를 이용해 OPA 의 ValidatingAdmissionWebhook 리소스를 지워 클러스터를 복구했다.
    후속 조치
    • OPA 의 ValidatingAdmissionWebhook 이 정책이 적용되고 개발 팀이 접근하는 네임스페이스만 보도록 범위를 좁혔다.
    • 웹훅을 정책이 실제로 검증하는 Ingress 와 Service 리소스에만 켰다.
    • OPA 가 응답하지 않으면 재시작되도록 liveness probe 를 더하고 문서를 고쳤다.
    • 이 동작을 개선하자는 쿠버네티스 업스트림 이슈가 아직 열려 있어, 그 진행을 지켜본다.
    교훈

    API 서버 응답 시간에 알림을 걸어 두었다면, OPA 웹훅을 처음 배포한 뒤 모든 CREATE 와 UPDATE 요청의 응답 시간이 늘어난 것을 알아챘을 수도 있다. 모든 워크로드에 프로브를 설정하는 것이 중요하다. 팀은 OPA 배포가 너무 간단해 보여서 Helm 차트를 쓰지 않았는데, 그 차트에는 어드미션 컨트롤러 컨테이너의 livenessProbe 를 포함해 튜토리얼 기본 설정에 없는 조정이 여럿 들어 있었다. 노드 자동 복구를 끄는 것도 검토했지만 끄지 않기로 했다. 같은 문제를 겪은 것은 Jetstack 이 처음이 아니며, 관련 업스트림 이슈는 아직 열려 있다.

  4. 증상

    2019년 7월 19일 금요일, Grafana Cloud 의 Hosted Prometheus 서비스가 장애를 겪었다. 오류 예산 기반 Prometheus 알림이 장애 시작 4분 안에 당직자를 호출했다.

    촉발

    7월 19일 한 엔지니어가 큰 고객을 위한 전용 Cortex 클러스터를 새로 띄웠다. 새 클러스터 설정에는 새로 도입한 파드 우선순위 지정이 없어서, 모든 파드가 기본값인 medium 우선순위를 받았다. 쿠버네티스 클러스터에는 새 Cortex 클러스터를 올릴 자원이 부족했다.

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

    새로 도입한 오류 예산 기반 Prometheus 알림이 장애 시작 4분 안에 당직자를 호출했다.

    조치
    • 쿠버네티스 클러스터를 늘려 새 Cortex 클러스터와 기존 운영 Cortex 클러스터가 모두 들어가게 했다.
    • Cortex 앞의 인증 리버스 프록시에서 난 OOM 을 찾아 고쳤다.
    후속 조치
    • 운영 Ingester 에 high 우선순위 지정을 반영했다.
    • 클러스터 전역 설정처럼 네임스페이스 밖에 있는 객체의 배포는 더 많은 사람이 리뷰한다.
    • 네임스페이스 밖 설정 변경에는 모두 설계 문서를 요구한다.
    • 인증 리버스 프록시의 규모 조정을 자동화해 과부하 때 OOM 이 나지 않게 한다.
    • 한꺼번에 몰려드는 재시도를 막으려고 Prometheus 의 기본 백오프와 확장 동작을 조사한다.
    교훈

    운영 Ingester 에 high 우선순위를 지정하기 전에 medium 을 기본 우선순위로 만들지 말았어야 했다. 운영 Ingester 의 high 지정도 더 일찍 배포했어야 했다. 팀은 이 변경이 설계 문서를 쓸 만큼 크지 않다고 보고 GitHub 이슈에서만 논의했다. 좋은 점도 있었다. Cortex 는 자원이 충분해지자 추가 조치 없이 스스로 회복했다. 팀은 새 로그 수집 시스템인 Grafana Loki 로 Ingester 가 정상적으로 종료됐는지 확인했다.

  5. 증상

    사용자들이 작업이 시작되지 않는다고 알려 왔다. 평소에는 모니터링이 먼저 잡아내는 편이었지만 이번에는 사용자 보고가 먼저였다. 처음부터 이미지 풀과 관련된 흔적이 보였다.

    촉발

    애플리케이션 하나가 읽어야 하는 버킷의 권한을 바꾸면서 그 애플리케이션이 시작하지 못하게 됐다. 이 애플리케이션은 약 1,000대 노드에서 도는 DaemonSet이었고 크래시 루프에 빠졌다. imagePullPolicy가 Always여서 재시작할 때마다 노드에 이미 있는 이미지를 다시 받았다.

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

    사용자들이 작업이 시작되지 않는다고 알려 와서 알았다. 모니터링보다 사용자 보고가 먼저였다. 팀은 파드 상태, 이미지 풀 지표, 레지스트리 응답 코드를 차례로 확인해 429 속도 제한을 찾았다.

    조치
    • 영향을 받은 NAT 인스턴스를 교체해 레지스트리로 나가는 출발지 IP를 바꿨다.
    • Cloud SQL 접속에 쓰던 고정 IP 설정과 방화벽 규칙을 다시 맞춰 데이터베이스 연결을 되살렸다.
    후속 조치
    • latest 같은 유동 이미지 태그를 막는 어드미션 웹훅을 만들어 워크로드 리소스와 파드에 걸었다.
    • 웹훅이 클러스터가 만드는 파드까지 거부하자, 파드 객체에서는 빼고 워크로드 객체에만 적용하도록 바꿨다.
    교훈

    imagePullPolicy가 Always인 DaemonSet이 크래시 루프에 빠지면 노드 수만큼 이미지 풀이 반복된다. 레지스트리 트래픽이 NAT 몇 대로 모이면 출발지 IP 몇 개가 속도 제한에 걸려 리전 전체가 이미지를 받지 못한다. NAT를 바꾸면 그 IP를 허용해 둔 외부 서비스 연결도 함께 끊긴다. 파드에 거는 어드미션 웹훅은 사용자가 아니라 컨트롤러가 만드는 파드까지 막는다. 발표자들은 대규모 클러스터에서는 DaemonSet을 특히 조심하라고 했다. DaemonSet이 기대는 DNS, Vault, 이미지 저장소도 모두 망가뜨려 본 적이 있다고 했다. 수천 대 단위로 무언가를 다루면 그만큼 망가뜨리기 쉽다는 것이다. kubelet 아래에도 인프라가 있다는 것을 잊지 말라고도 했다.

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

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

원인별5

용량 한계5건

  1. IL-0102 배포와 워커 오토스케일링 폭주가 겹치자 크기를 고정해 둔 CoreDNS 가 메모리 한도를 넘겨 재시작된 뒤 회복하지 못했고, Buildkite 사이트 전체가 약 30분 멈췄다.
  2. IL-0202 갑자기 몰린 쿼리와 데이터베이스 쓰기로 Honeycomb 수집 호스트가 메모리 부족으로 죽었고, 쿠버네티스 CrashLoopBackOff 가 용량 회복을 막아 US1 이벤트 수집이 한 시간 넘게 불안정했다
  3. IL-0037 imagePullPolicy가 Always인 DaemonSet이 크래시 루프를 돌며 이미지를 계속 받아, NAT 세 대를 같이 쓰던 리전 전체가 이미지 레지스트리에서 429로 막혔다
  4. IL-0064 CPU 를 많이 쓰는 파드가 Google Cloud 노드 하나에 몰려 노드가 커널 패닉으로 죽었고, 다시 배치된 파드가 다음 노드를 또 죽이며 웹사이트와 API 가 멈췄다.
  5. IL-0036 재시도를 멈추지 않는 쿠버네티스 Job 이 노드 자원을 다 써 버려 클러스터의 노드가 차례로 죽고 검색과 리포트가 멈췄다.

의존성 장애1건

  1. IL-0187 Spring Cloud Config Server 가 잠깐 내려가자 이를 헬스 체크에 포함한 모든 앱의 Liveness Probe 가 실패해 쿠버네티스가 파드를 계속 죽이고 다시 띄우면서 한 계열사 서비스가 마비됐다.

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

조직
  1. IL-0198 systemd 보안 패치가 Ubuntu 22.04 노드의 systemd-networkd 를 재시작해 Cilium 이 넣은 IP 규칙을 지웠고, 여러 리전과 세 클라우드의 Kubernetes 노드가 한꺼번에 네트워크를 잃었다.

설정 변경6건

  1. IL-0109 로그 수집을 고치려던 EKS 노드 롤오버가 꼬이면서 Auto Scaling 그룹이 정상 워커 노드를 모두 종료해 클러스터에 노드가 하나도 남지 않았다.
    DFDS2023
  2. IL-0009 ArgoCD Application 이름이 겹쳐 InfluxDB Cloud 운영 환경 하나가 통째로 삭제됐다
  3. IL-0010 템플릿 중괄호가 빠진 설정 변경으로 ArgoCD 가 전 세계 모든 클러스터의 서비스를 지웠다
  4. IL-0008 응답하지 않는 OPA 검증 웹훅 때문에 GKE 마스터 업그레이드가 멈추고 API 서버가 간헐적으로 끊기면서 노드가 끝없이 재생성됐다
  5. IL-0004 새 Cortex 클러스터에서 기본 우선순위를 받은 파드가 우선순위가 없는 운영 Ingester 를 연쇄적으로 선점해 Hosted Prometheus 쓰기가 실패했다
  6. IL-0055 실패하는 CronJob 이 기본 concurrencyPolicy 때문에 겹겹이 쌓여 재시작하는 파드가 수천 개로 늘었고 클러스터가 내려갔다
    Target2018

소프트웨어 결함1건

  1. IL-0132 잘못된 리소스 정리 작업이 Vertex AI 예측 엔드포인트를 전역에서 삭제된 것으로 표시해 고객 모델이 내려가고 예측 요청이 4시간 넘게 실패했다.