Incident Library

IL-0518 freedesktop.org · 2018-07-17kubernetesgcp

GKE 위 gitlab.freedesktop.org 의 디스크가 모자라 저장소를 늘리려던 30분 작업이 GitLab 전체의 4시간 장애가 됐다

gitlab.freedesktop.org 는 Google Cloud Platform 의 Google Kubernetes Engine 위에서 Helm 차트로 돌고, 클러스터는 Kubernetes 1.10.x 였다. 서비스는 gitlab.org 의 GitLab CE 이미지로 Kubernetes 파드 하나에서 돌았고, Git 저장소와 PostgreSQL 데이터는 PersistentVolumeClaim 에 있었다. 이 Kubernetes 버전에서는 PersistentVolume 의 크기를 바꿀 수 없었다. 매일 5am UTC 에 도는 백업은 데이터를 로컬 디렉터리에 모은 뒤 압축하지 않은 tarball 을 만들어 올리므로, 백업 크기의 두 배가 넘는 빈 공간이 필요했다.

7월 17일 9am UTC 조금 넘어 Mesa 포크가 많이 생기며 디스크가 위급해져 API 요청 일부와 백업 cron 작업이 실패했다. 관리자는 몇 시간 전에야 알린 작업 시간 2pm 부터 2:30pm UTC 에 볼륨을 늘리기로 했다. 방화벽으로 들어오는 트래픽을 막은 뒤 수동 백업과 디스크 스냅샷을 떴는데, 백업 크기가 크게 늘어 예상보다 훨씬 오래 걸렸다. 클러스터를 1.10.x 로 올리고 볼륨 크기를 바꾸려 했으나 고정 크기 디스크는 늘릴 수 없었고 GKE 는 이 알파 기능을 켤 수 없었다. 볼륨을 다시 만들고 데이터를 옮겨야 했다.

옮기는 과정에서 Helm 이 없는 자원을 끝없이 기다렸고, 관리자의 인터넷 연결이 크게 나빠졌다. GCE 스냅샷은 살아 있는 디스크에 바로 복원할 수 없었고, GCE 디스크에서 만든 PV/PVC 는 디스크 내용을 지웠다. 결국 Kubernetes 서비스를 모두 멈추고 새로 키운 PV 와 옛 디스크 스냅샷을 임시 GCE VM 에 함께 붙여 복사했다. 첫 복사에서 MySQL 하위 디렉터리가 빠져, 볼륨을 새로 만들고 올바른 디렉터리 구조로 다시 복사했다. 14:00 부터 18:00 UTC 까지 GitLab 전체가 내려갔고, 18:45 UTC 쯤 공개 접근을 되살렸다. 데이터 손실은 없었다.

심각도
–
영향 범위
The GitLab web UI, API and HTTPS git clones on gitlab.freedesktop.org were completely unavailable; anongit and cgit kept working
영향 사용자
–
지역
–
감지까지
–
복구까지
4h 45m

증상

9am UTC 조금 넘어 gitlab.freedesktop.org 의 디스크 공간이 위급하다는 것이 분명해졌다. 디스크가 모자라 일부 API 요청이 실패했고, 매일 도는 백업 cron 작업도 같은 이유로 실패하기 시작했다. 관리자는 사람들이 IRC 에서 장애를 말하고 나서야 문제를 알았다.

디스크를 채운 것은 최근 많이 만들어진 Mesa 포크였다. Mesa 는 저장소 하나에 약 2.1GB 가 들고, 포크는 객체를 나누지 않고 git clone 을 그대로 하므로 포크 사이에 저장 공간이 중복 제거되지 않았다. Mesa 나 커널 포크가 하나만 더 생기면 디스크가 완전히 바닥날 상황이었다.

디스크를 늘리려고 잡은 2pm UTC 부터 2:30pm UTC 까지의 작업 시간 동안 GitLab 웹 UI, API, https://gitlab.freedesktop.org 를 통한 HTTPS git clone 이 모두 연결 타임아웃을 냈다. 관리자가 방화벽 규칙으로 자기 IP 에서 오는 것을 빼고 들어오는 트래픽을 모두 버렸기 때문이다. anongit 과 cgit 은 계속 정상으로 돌았다.

백업과 디스크 스냅샷이 예상보다 훨씬 오래 걸려 작업 시간을 3pm UTC 까지 늘렸다. 그 뒤 클러스터를 Kubernetes 1.10.x 로 올리고 PersistentVolume 의 크기를 바꾸려 했으나 곧바로 실패했다. 크기가 고정된 디스크를 그 자리에서 늘릴 수 없었고, GKE 에서는 디스크 크기 변경이 켤 수 없는 알파 기능이었다.

복구하는 동안 여러 방법이 막혔다. Helm 은 오타로 없는 자원을 기다리며 바로 실패하지 않고 끝없이 멈췄다. GCE 디스크에서 새 Kubernetes PV/PVC 를 만들자 디스크의 내용이 모두 지워졌다. 새 VM 에서 스냅샷을 새 볼륨으로 복사한 뒤에는 Git 데이터는 보였다. 그러나 Kubernetes 는 '$disk/mysql/' 를 MySQL 데이터 볼륨의 루트 마운트 지점으로 쓰는데, 복사가 이 하위 디렉터리 구조를 지키지 못해 MySQL 이 빈 데이터베이스를 봤다.

증상 영구 볼륨 가득 참오류율 상승서비스 중단

원인

촉발
최근 Mesa 포크가 많이 만들어지면서 GitLab 클러스터의 디스크가 거의 찼다. 관리자가 디스크 볼륨을 늘리려고 몇 시간 전에 알린 작업 시간에 GitLab 을 내리고 저장소 업그레이드를 시작했다.

감지

사람들이 IRC 에서 장애를 말하고 나서야 문제를 알았다. 디스크 사용량이나 API 오류율을 지켜보고 알리는 모니터링은 없었다.

조치

후속 조치

교훈

잘못된 것이 많았다. 디스크 사용량이나 API 오류율을 재고 알리는 장치가 없어서 IRC 에서 사람들이 말하고 나서야 알았다. GitLab 관리자가 한 명뿐이라 그 사람이 없으면 다른 사람이 Kubernetes 계정을 만들고 배포를 익히는 데서 시작해야 했고, 그 관리자도 Kubernetes 운영 경험이 비교적 적었다. 백업 크기가 크게 늘었으니 백업이 전보다 오래 걸린다는 것을 미리 알았어야 했고, 그렇지 않더라도 작업 시간을 알리기 전에 시험 작업으로 걸리는 시간을 잴 수 있었다. 오전에 일부 변경을 시험했지만 실제와 똑같은 변경은 시험하지 않았고, 디스크 스냅샷 같은 것은 시험을 더 철저하고 실제에 가깝게 할 수 있었다.

잘된 것도 있었다. 파괴적인 작업을 시작한 뒤로 어느 시점에나 백업이 적어도 세 벌 있어서 데이터를 영영 잃을 위험은 없었다. 다만 그중 일부는 복원 원본으로 쓰려면 받아들일 수 없을 만큼 긴 장애가 필요했다. 데이터의 많은 부분이 GCS 에 있었기 때문에 이번 같은 작업이 필요해지는 시점이 오래 늦춰졌다.

출처

참고 문서

관련 사례

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

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: 영구 볼륨과 스테이트풀셋, 클라우드 블록 스토리지, Helm. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.