그래프
사례2건
2건 중 1~2번째
- 증상
2025-03-12 10:58 UTC 부터 백엔드 응답 시간이 높다는 알림이 들어왔다. 3월 12일과 13일 이틀 동안 mw-api-int, mw-parsoid, mw-jobrunner 에서 지연이 커지고 데이터베이스 오류가 늘었다. External Storage 클러스터의 부하와 연결 수도 크게 늘었다.
- 촉발
mw-api-int, mw-parsoid, mw-jobrunner 를 PHP 8.1 로 옮기는 예정된 Scap 배포가 장애를 일으켰다. 3월 12일 10:44 UTC 에 1126607[puppet] 과 1126650 [deployment-charts] 를, 3월 13일 11:15 UTC 에 1127476[puppet] 과 1127478[deployment-charts] 를 배포했다.
- 원인
- 구성 요소
- 기여 요인
- 감지
3월 12일 10:58 UTC 에 백엔드 응답 시간이 높다는 알림이 들어오기 시작했다. 처음 세운 가설은 특정 네트워크나 클라이언트의 많은 트래픽, 잘못 실행된 예약 작업, 자원을 많이 먹는 changeprop-jobqueue 작업이었다. 원인을 가리켰을 MediaWikiMemcachedHighErrorRate 알림은 logstash-prometheus 파이프라인이 밀려 빠지거나 곧바로 회복됐다. 장애 중에는 알림 78개가 울리고 있어서, 그 알림이 울렸더라도 부수 증상으로 보고 넘겼을 가능성이 컸다.
- 조치
- 3월 12일 13:19 UTC 에 cirrus-streaming-updater 의 SUP 병렬도를 낮추는 패치 1126988[deployment-charts] 를 배포했다.
- 13:33 에 1127000[deployment-charts] 로 changeprop-jobqueue 의 categoryMembershipChange 작업 동시성을 낮췄다.
- 13:44 에 1126607[puppet] 과 1126650 [deployment-charts] 를 되돌리고 Scap 을 다시 돌렸다.
- 3월 13일 11:34 UTC 에 changeprop-jobqueue 를 롤링 재시작했다.
- 11:43 에 mw-api-int 를 롤링 재시작했다.
- 11:44 에 1127500[deployment-charts] 로 changeprop-jobqueue 의 categorymembership 작업을 껐다.
- 11:46 에 1127476[puppet] 과 1127478[deployment-charts] 를 되돌렸다.
- 11:58 에 되돌린 내용을 반영하려고 mw-api-int 를 다시 배포했다.
- 12:07 에 mw-api-int 의 레플리카 수를 늘렸다.
- 12:28 에 되돌린 내용을 반영하려고 mw-jobrunner 를 다시 배포했다.
- 14:06 에 되돌린 내용을 반영하려고 mw-parsoid 를 다시 배포했다.
- 후속 조치
- 장애 때 channel:Memcached 로 보내는 메시지 양을 줄인다.
- Scap 에 helm 롤백 기능을 넣는다.
- -Dbuild_mw_container_image:False 로 실행할 때도 Scap 이 helmfile-defaults 를 갱신해야 하는지 검토한다.
- MediaWiki 이미지에서 envvars.inc 를 뺄지 검토한다.
- 서로 관련된 구성 요소를 한꺼번에 보여 주고 따라갈 링크를 담은 "Why" 대시보드를 만들지 검토한다.
- 장애 대응 조율을 개선한다. 누가 무엇을 맡았는지, 누가 대응에 들어오고 나갔는지 장애 조율자가 알 수 있어야 한다. 또 맥락 없는 의견과 대응과 관계없는 논의로 채널이 시끄러워지지 않아야 한다.
- 장애 중에 MediaWiki 개발자와 연락해 개발자의 관점을 바로 들을 수 있게 한다.
- 교훈
Wikimedia 는 기술적 원인보다, 3월 12일 장애 때부터 MediaWiki 배포 세 곳이 Memcached 클러스터에 닿지 못하고 있다는 것을 알아채지 못한 이유가 더 중요하다고 봤다. 알림에 연결된 대시보드는 무엇이 일어나는지만 보여 줬다. Wikimedia 는 서로 의존하거나 영향을 주는 구성 요소를 함께 보여 주는 대시보드가 있었다면 달랐을 것이라고 적었다. 예를 들어 SQLBlobStore 키는 External Storage 와 바로 이어져 있다. 원인을 가리킬 알림은 곧바로 회복됐다. 그 알림이 울렸더라도 알림 78개 사이에서는 부수 증상으로 봤을 수 있었다. 응답자가 많았지만 누가 무엇을 하는지, 누가 대응에 들어오고 나갔는지 분명하지 않아 장애 조율자가 조율하기 어려웠다. 외부 사용자 영향을 제대로 가늠하지 못해 실제보다 심각하게 여겼다. trace.wikimedia.org 도 장애 중에 쓰지 않았다.
IL-0518GKE 위 gitlab.freedesktop.org 의 디스크가 모자라 저장소를 늘리려던 30분 작업이 GitLab 전체의 4시간 장애가 됐다freedesktop.org2018- 증상
9am UTC 조금 넘어 gitlab.freedesktop.org 의 디스크 공간이 위급하다는 것이 분명해졌다. 디스크가 모자라 일부 API 요청이 실패했고, 매일 도는 백업 cron 작업도 같은 이유로 실패하기 시작했다. 관리자는 사람들이 IRC 에서 장애를 말하고 나서야 문제를 알았다.
- 촉발
최근 Mesa 포크가 많이 만들어지면서 GitLab 클러스터의 디스크가 거의 찼다. 관리자가 디스크 볼륨을 늘리려고 몇 시간 전에 알린 작업 시간에 GitLab 을 내리고 저장소 업그레이드를 시작했다.
- 원인
- 구성 요소
- 기여 요인
- 감지
사람들이 IRC 에서 장애를 말하고 나서야 문제를 알았다. 디스크 사용량이나 API 오류율을 지켜보고 알리는 모니터링은 없었다.
- 조치
- 관리자가 일하던 IP 를 빼고 GitLab 으로 들어오는 트래픽을 모두 버리도록 방화벽 규칙을 고쳤다. 그래서 다른 사람들은 잠깐씩 나는 실패 대신 연결 타임아웃만 봤고, 관리자는 그 시점 뒤의 변경을 잃을 걱정 없이 한 시점의 데이터를 스냅샷으로 뜰 수 있었다.
- GCS 에 있는 것을 뺀 GitLab 데이터 전부를 손으로 백업했다. 평소의 백업 Rake 작업은 데이터 모으기까지만 돌렸다. tar 를 돌리면 디스크가 넘치므로, tar 출력을 SSH 로 로컬의 안전한 기계에 있는 암호화된 파티션에 흘려보냈다.
- 모든 데이터 디스크의 스냅샷을 떴다. Kubernetes PersistentVolume 마다 Google Compute Engine 디스크가 있어 손으로 스냅샷을 뜨고 태그를 붙였다.
- Kubernetes 서비스를 모두 멈추고, 새로 키운 PV 와 옛 디스크 스냅샷을 새 임시 GCE VM 에 함께 붙여 직접 복사한 뒤 VM 을 멈추고 Kubernetes 를 다시 켰다.
- 첫 복사가 MySQL 하위 디렉터리를 지키지 못해 MySQL 이 빈 데이터베이스를 봤다. 그래서 어긋남을 막으려고 자원을 모두 지우고, 비어 있는 새 볼륨과 새 GCE VM 을 만들어 올바른 디렉터리 구조로 다시 복사했다. 저장소와 사용자 목록이 전과 같은지, UI 일부와 흔한 작업 흐름이 되는지 손으로 확인했다. 다음 날 아침 백업 cron 작업이 또 다른 장애 없이 성공하도록 전체 백업을 백그라운드로 돌렸다.
- 18:45 UTC 쯤 공개 접근을 되살리고 장애가 끝났다고 알렸다.
- 후속 조치
- 모니터링, 로깅, 알림을 켠다. 이 일은 gitlab.freedesktop.org 의 freedesktop 이슈 8번으로 오래전에 열어 두었고, 이 분야를 아는 사람의 도움을 구한다.
- 소통을 개선한다. 이번 장애는 급하게 잡혀 IRC 에만 알렸고 메일링 리스트에는 알리지 않았으며, 장애가 길어질 때도 리스트에 알리지 않았다. 이런 일을 훨씬 잘 알리는 방법을 찾는다.
- Cloud Console 웹 UI 는 페이지 사이 로딩이 길고 이동이 많아 대화형 작업에 거의 쓸 수 없다. 그 대신 콘솔 클라이언트를 실제 상황에서 쓰는 데 익숙해지고, 되도록 콘솔 클라이언트를 쓴다.
- GitLab 관리자가 한 명뿐인 상태는 지속할 수 없으므로 관리자를 늘린다. 특히 Kubernetes 배포에 익숙한 사람이 있으면 큰 도움이 된다.
- Omnibus 컨테이너에서 벗어난다. 지금은 gitlab.fd.o 뒤의 모든 서비스가 파드 하나에 있고, 시작할 때 Chef 가 2~3분 동안 파일 시스템을 설정해 변경마다 최소 4~5분 동안 GitLab 전체가 내려간다. GitLab 이 만드는 cloud native 배포로 옮기려면 몇 시간의 장애가 필요하므로 충분히 앞서 알린다.
- 저장소를 크기를 바꿀 수 있는 볼륨이나 GCS 로 옮긴다. 할 수 있는 만큼 클라우드 스토리지로 옮기고, GCP 에서 Kubernetes 1.11.x 를 쓸 수 있게 되면 디스크를 필요에 따라 커지는 볼륨으로 다시 만든다.
- 교훈
잘못된 것이 많았다. 디스크 사용량이나 API 오류율을 재고 알리는 장치가 없어서 IRC 에서 사람들이 말하고 나서야 알았다. GitLab 관리자가 한 명뿐이라 그 사람이 없으면 다른 사람이 Kubernetes 계정을 만들고 배포를 익히는 데서 시작해야 했고, 그 관리자도 Kubernetes 운영 경험이 비교적 적었다. 백업 크기가 크게 늘었으니 백업이 전보다 오래 걸린다는 것을 미리 알았어야 했고, 그렇지 않더라도 작업 시간을 알리기 전에 시험 작업으로 걸리는 시간을 잴 수 있었다. 오전에 일부 변경을 시험했지만 실제와 똑같은 변경은 시험하지 않았고, 디스크 스냅샷 같은 것은 시험을 더 철저하고 실제에 가깝게 할 수 있었다. 잘된 것도 있었다. 파괴적인 작업을 시작한 뒤로 어느 시점에나 백업이 적어도 세 벌 있어서 데이터를 영영 잃을 위험은 없었다. 다만 그중 일부는 복원 원본으로 쓰려면 받아들일 수 없을 만큼 긴 장애가 필요했다. 데이터의 많은 부분이 GCS 에 있었기 때문에 이번 같은 작업이 필요해지는 시점이 오래 늦춰졌다.
이 2건에서 가장 많이 나오는 구성 요소: Helm, 클라우드 블록 스토리지. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.