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

사례5건

5건 중 1~5번째

  1. 증상

    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 도 장애 중에 쓰지 않았다.

  2. 증상

    2024-10-09 05:01:36 UTC 에 codfw 의 rest-gateway 에서 page-analytics_cluster 의 5xx 오류가 늘었다는 GatewayBackendErrorsHigh 알림이 울렸다. 05:03:32 UTC 에는 KubernetesCalicoDown 알림이 16건 묶여 울렸고, 알림 문구는 kubernetes2037.codfw.wmnet is not running calico-node Pod 였다. 05:04:15 UTC 에는 MediaWiki memcached 오류율이 전 세계에서 올랐다는 MediaWikiMemcachedHighErrorRate 알림이 울렸다.

    촉발

    한 운영자가 새 mwscript-k8s 도구로 TimedMediaHandler 의 requeueTranscodes.php 를 돌려 동영상 트랜스코딩을 일괄 정비했다. mwscript-k8s 는 스크립트를 실행할 때마다 helm 릴리스를 통째로 배포하므로, 이 작업이 몇 시간 동안 리소스를 계속 만들었다.

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

    자동 모니터링이 알아채고 당직 SRE 가 대응했다. 05:01:36 UTC 에 GatewayBackendErrorsHigh, 05:03:32 UTC 에 KubernetesCalicoDown 16건, 05:04:15 UTC 에 MediaWikiMemcachedHighErrorRate 알림이 울렸다.

    조치
    • calico 와 typha 의 자원 한도를 올리는 변경을 CI 를 기다리지 않고 반영하고, helmfile -e codfw --selector name=calico apply -i --context 5 로 적용했다. 적용 중 새 calico 파드가 정상으로 떴고, 06:10 UTC 에 Calico 가 회복되었다.
    후속 조치
    • mwscript-k8s 가 리소스를 너무 많이 만드는 문제를 해결한다.
    교훈

    완전한 장애 직전까지 갔다. 자동 모니터링이 장애를 잡았다. 새로 들어온 여러 사람이 함께 본 덕에 근본 원인을 찾았다. 미주 SRE 에서 EMEA SRE 로 장애 대응을 문제없이 넘겼다. 반면 최종 사용자에게 영향이 갔고, 비상시에 eqiad 로 전환할 수 있는지 확신하지 못했다. 운도 따랐다. 장애는 미주 SRE 근무가 끝나고 EMEA SRE 근무가 시작되기 바로 전에 발견되었다. 이 시간대는 오래전부터 대응 인력이 비는 때로 알려져 있었다. 트랜스코딩 작업을 미국의 금요일 저녁에 넣지 않은 것도 다행이었다.

  3. 증상

    MediaWiki 설정 변경을 배포한 11:41 부터 쿠버네티스로 가는 MediaWiki 트래픽이 오류를 받기 시작했다. 11:47 에 mw-api-ext 와 mw-api-int 서비스의 프로브 실패 알림이 온콜 담당자를 호출했다. 전체 트래픽의 1%, 초당 120건의 요청이 약 30분 동안 오류를 받았다.

    촉발

    09:37 에 쿠버네티스 전역 기본값을 바꾸는 변경이 머지됐다. 이 변경으로 이 기본값을 따르는 차트가 cert-manager 인증서를 쓰게 됐다. 11:41 에 MediaWiki 설정 변경을 배포하면서 쿠버네티스 위 MediaWiki 배포가 이 기본값을 받아 TLS 종료에 엉뚱한 인증서를 쓰게 됐다.

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

    11:47 에 "(ProbeDown) firing: (6) Service mw-api-ext:4447 has failed probes (http_mw-api-ext_ip4)" 와 "(ProbeDown) firing: Service mw-api-int:4446 has failed probes (http_mw-api-int_ip4)" 알림이 온콜 담당자를 호출해 알아챘다. 두 사람이 호출을 받았다.

    조치
    • 11:58 에 원인을 찾고 패치 https://gerrit.wikimedia.org/r/947331 을 준비했다.
    • 12:08 에 MediaWiki 디플로이먼트를 모두 다시 배포하기 시작했고, 12:16 에 장애가 끝났다.
    후속 조치
    • 배포 절차와 테스트를 더 강화해야 하는지 검토한다. 다음 배포에 뜻밖의 변경이 함께 실리는 문제와 쿠버네티스 카나리 배포도 검토 대상이다.
    • 배포 중에 일부 지표를 볼 수 없거나 비정상이 되는 문제를 지표 쪽에서 고칠지, 배포의 영향을 줄일지 검토한다.
    교훈

    문제를 일으킨 변경을 낸 사람이 대응자 가운데 있어 원인을 빨리 찾았다. 근본 원인은 CI 에서 보였어야 했다. 그러나 변경은 hieradata 저장소에서 했고 원인은 deployment-charts 저장소 쪽에 있어, 변경한 저장소의 CI 에서는 보이지 않았다. 당시에는 트래픽의 1% 만 쿠버네티스로 가서 피해가 작았다. 오류의 양이 적어 문제를 쿠버네티스 쪽으로 좁히는 데 시간이 걸렸다. 보고서는 쿠버네티스를 서비스 풀에서 더 일찍 뺐어야 했는지를 묻는다.

  4. 증상

    2022-03-31 07:53 UTC 에 GitLab.com 웹 서비스의 50x 오류가 늘기 시작했고, 1분 뒤 당직 엔지니어가 오류율 증가 페이지를 받았다. 사용자에게는 GitLab.com 이 느려졌고 간헐적으로 500 오류 페이지가 떴다.

    촉발

    gitlab-com/gl-infra/k8s-workloads/gitlab-com!1643 머지 요청을 배포하는 파이프라인이 07:49 UTC 에 gprd-cny 로 배포를 시작했다. 이 변경에는 GitLab 차트 버전 업그레이드가 들어 있었고, 새 차트는 Prometheus ServiceMonitor, PodMonitor 설정과 관련된 변경으로 Kubernetes Service 와 Deployment 의 포트 이름을 바꿨다.

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

    07:53 UTC 에 50x 오류가 늘기 시작했고 07:54 에 PagerDuty 알림이 당직 엔지니어를 호출했다. 변경을 배포하던 엔지니어가 오류를 보고 그 변경과 연결해 원인을 짚었다.

    조치
    • 08:05 UTC 에 당직 엔지니어가 카나리 환경을 트래픽에서 뺐다가 08:25 에 다시 넣었다.
    • 08:15 에 cluster c 와 cluster d 배포 작업을 시작 전에 취소했다.
    • 08:51 에 HAProxy 에서 gprd-us-east1-d 클러스터를 뺐다가 08:56 에 다시 넣었다.
    • 09:31 에 최소 레플리카 수를 100 넘게 올리는 변경 !1650 을 머지했다.
    • 09:53 에 HAProxy 에서 gprd-us-east1-c 클러스터를 빼고, 09:57 에 이 클러스터에 !1643 을 배포한 뒤 10:07 에 다시 넣었다.
    • 10:19 에 최소 레플리카 상향을 되돌리는 변경 !1652 를 머지했다.
    후속 조치
    • 리전 클러스터 하나에서 트래픽을 통째로 안전하게 빼는 graceful drain 기능을 만든다.
    • PagerDuty 를 유지보수 모드로 바꾸는 ChatOps 명령을 만든다.
    교훈

    알림은 정확하게 울렸다. 원인이 바로 직전에 배포한 변경이라는 것을 알았기 때문에, 그 변경을 배포하던 파이프라인을 멈추는 것이 자연스러운 첫 대응이었다.

  5. 증상

    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 에 있었기 때문에 이번 같은 작업이 필요해지는 시점이 오래 늦춰졌다.

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

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

원인별3

배포 결함1건

  1. IL-0324 External Storage 데이터베이스 클러스터에 과부하가 걸려 mw-api-int, mw-parsoid, mw-jobrunner 의 지연과 데이터베이스 오류가 늘었다

용량 한계2건

  1. IL-0232 codfw WikiKube 클러스터에서 Calico 구성 요소가 자원 한도에 걸려 calico-node 파드가 하나씩 죽고 노드가 차례로 빠지면서 MediaWiki 지연과 오류가 났다
  2. IL-0518 GKE 위 gitlab.freedesktop.org 의 디스크가 모자라 저장소를 늘리려던 30분 작업이 GitLab 전체의 4시간 장애가 됐다

설정 변경2건

  1. IL-0459 쿠버네티스 위 MediaWiki 가 TLS 종료에 엉뚱한 인증서를 써서 약 30분 동안 트래픽 1% 가 오류를 받았다
  2. IL-0208 GitLab Helm 차트 업그레이드가 Service 와 Deployment 의 포트 이름을 바꿔 GCP 로드 밸런서가 다시 구성되는 동안 GitLab.com 요청이 느려지고 50x 오류가 났다
    GitLab2022