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

사례4건

4건 중 1~4번째

  1. 증상

    data100 클러스터의 쿠버네티스 API 서버에 닿지 않아 새 자원을 만드는 요청이 실패했다. 허브 파드가 멈춘 뒤 새 파드가 만들어지지 않아 사용자들은 프록시 오류 메시지를 보았다.

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

    11:34 에 인프라 담당자가 Slack 으로 알림을 받았다. API 서버가 멈춘 시각인 11:21 은 장애가 끝난 뒤 클라우드 사업자의 모니터링 지표로 확인했다.

    조치
    • 13:00 에 새 클러스터를 만들고, 그 클러스터의 리소스 그룹에 새 nfs 서버를 요청했다.
    • 데이터 볼륨을 옛 nfs 서버에서 떼어 옛 클러스터의 리소스 그룹에서 새 클러스터의 리소스 그룹으로 옮겼다.
    • ZFS 풀을 새 nfs 서버로 가져왔다.
    • helm 으로 staging 허브를 띄우고 DNS 를 바꿨다.
    • helm 으로 prod 허브를 띄우고 DNS 를 바꿨다.
    후속 조치
    • API 서버 엔드포인트를 외부에서 감시하고, 응답하지 않으면 알림을 보낸다.
  2. 증상

    학생 두 명이 서버를 시작할 수 없다고 강의 Piazza 에 알렸고, /hub/admin 화면에서도 서버가 시작되지 않았다. 처음에는 학생들이 메모리를 다 썼을 수 있다는 말이 나왔다.

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

    학생들이 강의 Piazza 와 강의 slack 에 서버가 시작되지 않는다고 알렸다.

    조치
    • Terminating 에 멈춘 사용자 파드를 kubectl --namespace=prod delete pod jupyter-<name> --grace-period=0 --force 로 강제로 지웠다. 그 뒤 /hub/admin 에서 서버가 제대로 시작됐다.
    • docker ps 가 멈춘 노드 k8s-pool1-19522833-13 을 cordon 했다.
    • 같은 상태인 k8s-pool2-19522833-9 에서 멈춘 파드를 모두 강제로 지우고 그 노드도 cordon 했다.
    • pool1-...-13 을 Azure 포털에서 손으로 멈췄다가 다시 시작했다. 노드가 돌아와 Docker 가 응답하자 uncordon 했다.
    • pool2-...-9 가 완전히 멈춘 뒤 Azure 포털에서 손으로 다시 시작했다.
    후속 조치
    • 학생 서버가 시작되거나 멈추지 않는다는 신고가 여러 건 오면 그 사용자 파드들이 같은 노드에서 돌았는지 확인한다.
    • /var/lib/docker 를 sdb1 에 마운트하지 않은 노드가 몇 대인지 알아본다.
    • Terminating 에 멈춘 파드 수가 늘어나는지 지켜본다. 예를 들어 kubectl --namespace=prod get pod -o wide| grep Terminating 으로 본다.
  3. 증상

    2017-03-20 12:44 에 새 학생 서버가 500 오류를 내며 로그인을 막는다는 보고가 들어왔다. 한 사람의 문제가 아니라 널리 퍼진 증상이었다.

    촉발

    2017-03-18 16:30 에 자원을 아끼려고 학생 한 명에게 주는 메모리를 2G 에서 1G 로 줄였지만, 노드 크기는 26G RAM 그대로 두었다. 그 결과 Google Cloud 의 노드당 디스크 개수 한도에 닿았다.

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

    12:44 에 새 학생 서버가 500 오류로 로그인을 막는다는 보고가 들어왔고, 팀은 이것이 한 사람의 문제가 아니라 널리 퍼진 장애라고 판단했다.

    조치
    • Google Container Engine 이 쓰는 인스턴스 템플릿을 복사해 n1-highmem-4 대신 더 작은 n1-highmem-2 노드를 띄우도록 고쳤다.
    • Google Container Engine 의 관리형 인스턴스 그룹이 새 템플릿을 쓰게 바꿨다.
    • 새 인스턴스 그룹을 30노드 늘렸다. 노드 하나에 학생 12명쯤이 들어가는 용량이었다.
    • populate.bash 를 돌려 새 노드에서 학생 파드가 제때 뜨게 했다.
    • 노드가 섞인 낯선 상태에서 오작동할까 봐 간단한 오토스케일러를 멈췄다.
    • 'redirected too many times' 오류를 알려 온 사용자마다 관리자가 제어판에서 그 사용자의 파드를 멈췄다가 다시 켰다.
    • 'redirected too many times' 오류가 많이 나서 허브 파드와 프록시 파드를 재시작했다.
    후속 조치
    • 이번에 부딪힌 쿠버네티스 버그인 kubernetes/kubernetes 이슈 24317 의 진행을 지켜본다.
    • JupyterHub 의 'too many redirects' 문제를 근원에서 찾아 고친다.
    • 더 이상 쓰지 않는 예전의 큰 노드를 모두 지운다.
    • 파드가 Pending 상태로 무시할 수 없을 만큼 오래 머물면 개수와 상관없이 알림을 보낸다.
  4. 증상

    새벽 1시쯤 DataHub 에 로그인하려는 사용자가 프록시 오류를 받았다. hub 파드는 떠 있었지만 로그가 sqlite 오류로 가득했다.

    촉발

    엔지니어가 앞서 난 400 오류를 디버깅하려고 hub 파드 안에서 sqlite3 를 다시 열고, 데이터베이스를 ATTACH 하지 않은 채 .save jupyterhub.sqlite 를 실행했다. 이 명령이 JupyterHub 데이터베이스 파일을 빈 데이터베이스로 덮어썼다.

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

    새벽 1시쯤 DataHub 가 다운됐다는 신고가 들어왔다. 1:12 에는 한 사용자가 로그인은 되지만 노트북이 모두 사라졌다고 알렸다.

    조치
    • hub 파드의 replicas 를 0으로 줄여 hub 를 내렸다.
    • 쿠버네티스 PVC 를 사용자 id 와 다시 짝지어 JupyterHub sqlite 데이터베이스를 다시 만들었다. PVC 이름에 정리된 사용자 이름과 사용자 id 가 들어 있어서 할 수 있었다.
    • 처음 넣은 가짜 cookie_id 값을 null 로 바꾸고, sqlite 파일을 DataHub 에 다시 붙였다.
    • 모든 사용자를 로그아웃시키려고 hub 파드의 /srv/jupyterhub/jupyterhub_cookie_secret 을 바꿨다. 끝 근처 한 글자를 바꿨을 때는 효과가 없었고, 앞쪽 한 글자를 바꾸고 재시작하자 모두 로그아웃됐다.
    • 사용자 파드를 모두 지워 모든 사용자를 확실히 로그아웃시켰다.
    • 모든 사용자의 cookie_id 를 채우는 스크립트를 돌렸고, 메모리에 남은 오래된 캐시를 없애려고 hub 를 재시작한 뒤 사용자 파드를 다시 모두 지웠다.
    • 이름에 '.' 이 들어간 새 사용자를 지우고, 이름에 '-' 가 있는 모든 사용자의 '-' 를 '.' 으로 바꾸는 스크립트를 돌렸다.
    후속 조치
    • JupyterHub 가 cookie secret 의 일정 길이만 쓰고 나머지를 버려서, 로그아웃시키려고 값을 바꿀 때 혼란이 생긴다는 문제를 JupyterHub 에 보고한다.
    • users 테이블의 cookie_id 열에 UNIQUE 와 NOT NULL 제약을 두자고 JupyterHub 에 제안한다.
    • 데이터베이스가 지워져도 파드와 PVC 이름이 그대로 남도록, 이름에 사용자 id 대신 사용자 이름 해시를 쓰는 기능을 KubeSpawner 에 요청한다.
    • 사용자 테이블의 id 를 Google 인증이 주는 'id' 와 같게 두어, 처음 로그인한 때와 상관없이 사용자 id 가 바뀌지 않게 하는 기능을 OAuthenticator 에 요청한다.
    • 관리형 MySQL 서비스인 Google Cloud SQL 로 옮긴다.
    • 데이터베이스를 정기적으로 백업하고 그 백업을 시험한다.
    • 해야 할 일과 하지 말아야 할 일을 담은 운영 FAQ 를 쓰기 시작한다.
    • 모니터링과 호출 체계를 개선한다.
    • 에스컬레이션 절차를 분명하게 문서로 남긴다.
내 클러스터에도 있는지 확인하기

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

원인별4