Incident Library
적용된 필터 증상API 조회 결과 불일치도메인쿠버네티스모두 풀기검색어 없이 필터만 적용한 목록입니다. 최근 사례부터입니다.
추천 필터 검색하면 검색어에서 찾은 분류 값이 여기에 나옵니다.

그래프

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

사례3건

3건 중 1~3번째

  1. 증상

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

  2. 증상

    mybinder.org 의 실행 성공률이 0으로 떨어졌고 새 실행이 모두 실패했다. 다운타임 알림이 없어서, 문제는 4시간쯤 지나 gitter 에 이상하다는 신고가 올라온 뒤에야 알려졌다.

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

    18:30 무렵 시작된 실패를 22:48 에 gitter 에 올라온 신고로 알았다. 다운타임 알림이 아직 없었다.

    조치
    • 4시간보다 오래된 파드를 지웠다.
    • ipython-in-depth 처럼 가장 많이 쓰는 이미지의 파드는 더 공격적으로 정리했다.
    • 파드 600개쯤을 정리하고 Hub 파드를 재시작해 실행을 정상으로 돌렸다.
    • 파드가 몰려 새로 할당된 노드 몇 개를 cordon 해서 오토스케일러가 회수하게 했다.
    • 다음 날 아침 최대 수명을 넘긴 파드를 손으로 정리해 남은 노드 일부를 비웠고, 클러스터는 3개 노드로 줄었다.
    후속 조치
    • 다운타임 알림을 만든다.
    • 스케일 다운을 자동화한다.
    • 다운타임 복구 절차를 문서로 남긴다. 이번에는 잘 됐지만 팀원 모두가 그 절차를 아는 것은 아니었다.
    • pod reflector 가 실패할 때 파드를 지우지 못하는 버그를 고친다.
    • KubeSpawner 가 pod reflector 의 실패에 더 잘 견디게 한다.
    • event reflector 를 파드마다 하나씩 두지 않고 하나로 합친다. event reflector 는 KubeSpawner 의 큰 새 기능이었고 이번 실패와 관련이 있을 수 있지만 아직 분명하지 않다.
    • Hub 상태가 나빠 보이는 것을 자동으로 찾아 사람 손 없이 Hub 를 재시작하는 방법을 시도한다.
    교훈

    mybinder.org-deploy 의 scripts/delete-pods.py 스크립트로 오래된 파드를 한꺼번에 지울 수 있었고, 문제를 알고 나서는 몇 분 안에 클러스터가 정상으로 돌아왔다. KubeSpawner 의 pod reflector 가 이벤트를 받지 못해 Hub 를 재시작할 때까지 실행이 모두 실패했다. 여기에 pod reflector 가 시작을 알아채지 못한 파드를 처음부터 만들어지지 않은 것으로 보고 지우지 않는 버그가 겹쳤다. 다운타임 알림이 없어서 5시간 동안 알아채지 못했다. 클러스터 스케일 다운에는 노드를 cordon 하고 drain 하는 손 작업이 여러 단계 남아 있었다.

  3. 증상

    사용자가 파드가 떴다가 사라진다고 클러스터 운영 팀에 알렸다.

    촉발

    etcd 의 쓰기 지연이 크게 늘었다. 발표자는 정상인 etcd 의 쓰기 지연이 한 자릿수 밀리초이고, 데이터베이스 동기화 지연이 두 자릿수나 수백 밀리초를 넘으면 문제가 시작된다고 설명했다.

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

    팀은 사용자가 파드가 떴다가 사라진다고 알려 와서 장애를 알게 됐다. 팀이 kubectl 로 확인하자 같은 명령이 실행할 때마다 다른 결과를 냈다.

    조치
    • 새 클러스터를 만들어 애플리케이션을 다시 배포하고 서비스를 복구했다.
    • 볼륨을 옛 클러스터에서 하나씩 손으로 풀어 새 클러스터에서 바인딩했다.
    • 로드 밸런서를 쓰던 팀들이 DNS 레코드를 새 클러스터의 로드 밸런서 이름으로 손으로 바꿨다.
    후속 조치
    • API 서버가 etcd 에서 읽을 때 항상 쿼럼 읽기를 하도록 설정한다.
    교훈

    etcd 는 쿼럼 읽기를 요청하지 않으면 오래된 데이터로 응답할 수 있고, 이 동작은 문서에 적혀 있다. 쿠버네티스 1.9 부터는 쿼럼 읽기가 기본이므로, 그 전 버전을 쓰면서 API 서버 설정을 직접 관리한다면 설정을 확인해야 한다. 쿼럼 읽기는 성능 걱정 때문에 처음에는 권장되지 않았지만, etcd 3.1 에서는 읽기가 디스크를 거치지 않아 부담이 크게 줄었다. etcd 는 쓰기 지연에 매우 민감하므로 데이터베이스 동기화 지연을 지켜봐야 한다. 고가용성 문서처럼 계속 바뀌는 문서는 꾸준히 다시 읽어야 한다. 로드 밸런서 이름을 직접 가리키는 DNS 레코드와 한 노드에 묶이는 볼륨은 클러스터 교체를 느리게 만든다.

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

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

원인별2