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

사례11건

11건 중 4~8번째

  1. 증상

    2023-05-18 20:01 에 Slack 알림이 왔고, 운영 GKE 클러스터의 Istio 가 제대로 동작하지 않았다.

    촉발

    2023-05-18 19:52 에 GKE 컨트롤 플레인이 1.22.17-gke.7500 에서 1.23.17-gke.1700 으로 자동 업그레이드됐다. 클러스터의 Istio 1.7.4 는 networking.k8s.io/v1beta1 과 admissionregistration.k8s.io/v1beta1 API 를 쓰고 있었다.

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

    GKE 자동 업그레이드 9분 뒤인 20:01 에 Slack 알림이 왔다.

    조치
    • Istio 를 1.7.4 에서 1.13.3 으로 업그레이드해 GKE 1.23 과 호환되게 맞췄다.
    교훈

    Kubernetes, Istio 처럼 함께 쓰는 패키지는 버전 호환성 매트릭스를 GitHub 이나 문서에서 확인한다. 업그레이드는 운영 환경에 올리기 전에 테스트 환경에서 먼저 해 본다. ArgoCD 같은 자동화 도구로 배포와 버전을 관리한다. 운영 환경은 버전을 최소 6개월 유지하되 지원 종료 3개월 전에는 업그레이드한다. 업그레이드 전에는 항상 백업한다. 처음에는 Istio 지원 종료를 원인으로 봤지만, GKE 업그레이드 기록을 다시 보고 나서야 진짜 원인을 찾았다.

  2. 증상

    2022년 6월 14일 03:03 US/Pacific 부터 us-central1 의 GKE API 호출이 느려지고 오류를 냈다. gcloud 와 Google Cloud Console 에서 보내는 GKE API 호출이 모두 영향을 받았다.

    촉발

    GKE 백엔드로 들어오는 트래픽이 예상하지 못하게 늘었다.

    원인
    구성 요소
    기여 요인
    조치
    • 늘어난 트래픽을 감당하도록 GKE 컨트롤 플레인을 증설했다.
    교훈

    실패한 요청을 클라이언트가 재시도하면 갑자기 늘어난 트래픽이 더 커진다. 관리형 컨트롤 플레인이 느려져도 클러스터 워크로드는 계속 돌지만, 클러스터를 조회하거나 바꾸는 작업은 막힌다.

  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. 증상

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

  5. 증상

    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 이 처음이 아니며, 관련 업스트림 이슈는 아직 열려 있다.

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

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

원인별6

클라우드 제공자 장애4건

  1. IL-0463 Harness Secure Connect 의 내부 로드 밸런서에 닿을 수 없게 되어 Secure Connect 를 쓰는 git 커넥터 검사와 CI 파이프라인이 실패했다
  2. IL-0542 Twingate 의 인증과 인가 요청 일부에서 약 30분 동안 오류율이 올라갔다
  3. IL-0014 GKE 를 1.12.5-gke.10 으로 올리는 중 노드 풀 업그레이드가 멈추고 인그레스와 HPA 가 망가졌다
  4. IL-0505 GKE 에서 kubectl logs 가 모든 파드에서 실패해 mybinder.org 사용자에게 빌드 로그가 가지 않았다

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

  1. IL-0101 자동 업그레이드를 꺼 둔 GKE 클러스터의 컨트롤 플레인이 지원 종료 기한에 1.33.2 로 강제 업그레이드된 뒤 새 노드가 모두 초기화에 실패해, 오토스케일링과 스팟 노드 복구가 15시간 멈췄다.
  2. IL-0180 GKE 컨트롤 플레인이 1.22 에서 1.23 으로 자동 업그레이드되면서 v1beta1 API 를 쓰던 Istio 1.7.4 가 제대로 동작하지 않았다

용량 한계1건

기여 요인
  1. IL-0140 us-central1 의 GKE API 가 지연과 오류를 내면서 고객이 클러스터 상태 확인, 업그레이드, 생성과 삭제를 하지 못했다.

소프트웨어 결함1건

  1. IL-0403 mybinder.org 의 prod hub 가 실제로는 넘지 않은 파드 quota 를 넘었다는 오류 때문에 새 파드를 만들지 못했다

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

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

설정 변경2건

  1. IL-0008 응답하지 않는 OPA 검증 웹훅 때문에 GKE 마스터 업그레이드가 멈추고 API 서버가 간헐적으로 끊기면서 노드가 끝없이 재생성됐다
  2. IL-0061 Terraform 상태 파일이 리뷰 빌드에서 바뀐 데다 권한 차이까지 겹쳐 Terraform 이 운영 GKE 클러스터 세 개 중 두 개를 삭제했다