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

사례12건

12건 중 2~6번째

  1. 증상

    2025-05-28 21:27 부터 CirrusStreamingUpdaterFlinkJobUnstable 알림이 울렸다. 검색 업데이트 파이프라인이 red 상태가 된 인덱스 약 60개에 쓰지 못하고 있었다.

    촉발

    2025-05-28 21:08 에 폐기할 호스트 elastic/cirrussearch10[53-67] 의 클러스터 접근을 없애는 Puppet 패치가 머지됐다. 이 중 일부 호스트가 아직 primary 샤드를 가지고 있었다.

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

    사람이 발견했다. 2025-05-28 21:27 부터 CirrusStreamingUpdaterFlinkJobUnstable 알림이 울렸지만, 클러스터 유지보수 작업 때문에 다른 알림 다수가 억제돼 울리지 않았다. 엔지니어가 다음 날 07:24 에 조사를 시작했다.

    조치
    • 09:29 에 red 인덱스를 지워 클러스터를 green, 즉 쓸 수 있는 상태로 되돌렸다. 업데이트 파이프라인이 회복하기 시작했다.
    • 09:47 에 망가진 인덱스 복구를 시작했고 14:50 에 모든 인덱스가 돌아왔다.
    후속 조치
    • 운영 CirrusSearch 의 스냅샷 저장소를 다시 켠다.
    • 운영 대응에 맞춘 OpenSearch 대시보드를 만든다.
    • Search Platform 이 맡은 OpenSearch 클러스터의 Logstash 파이프라인을 확인하고 고친다.
    교훈

    노드 ban 은 성공을 보장하지 않는 동작이라 기대대로 되지 않았다. 같은 종류의 서버를 한꺼번에 여러 대 폐기하는 큰 작업에 유지보수 계획이나 런북이 없었다. 스냅샷과 대시보드, 로깅 같은 중요한 도구를 쓸 수 없거나 문서가 모자랐다. 데이터센터가 depool 돼 있던 덕분에 사용자 영향이 없었다.

  2. 증상

    2025-03-31 02:58 UTC 에 두 데이터센터의 sessionstore 서비스가 500 오류를 내기 시작했고 편집이 실패했다. 03:03 에 세션 손실을 알리는 MediaWikiEditFailures 가 critical 로 울렸고, 03:04 에 SessionStoreErrorRateHigh 가 호출을 보냈다.

    촉발

    세션 쓰기가 늘어 저장 장치를 채웠다. 쓰기가 늘어난 배경에는 세션을 높은 비율로 덮어쓰는 비정상적인 워크로드가 있었고, 이 워크로드는 SUL3 롤아웃과 시기가 강하게 겹쳤다.

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

    03:04 UTC 에 SessionStoreErrorRateHigh 가 높은 5xx 비율로 울려 batphone 으로 호출이 나갔고, 그 1분 앞서 03:03 에 MediaWikiEditFailures 가 critical 로 울렸다. Cassandra 노드의 디스크 사용률이나 증가 속도에는 자동 알림이 없었다. 사용자 신고도 task T390512 로 들어왔다.

    조치
    • 03:36 UTC 에 스토리지를 지우고 Cassandra 를 재시작해 편집이 다시 들어오게 했다. 모든 세션이 사라졌고, 편집 비율은 03:40 무렵 평소 수준으로 돌아왔다.
    후속 조치
    • 디스크 사용률 추세가 비정상적으로 오르면 호출한다.
    • sessionstore 의 저장 용량을 늘린다.
    • sessionstore 에 네임스페이스 구분을 둔다.
    • sessionstore 워크로드의 관측성을 높인다.
    • sessionstore Cassandra 의 저장 공간이 빠르게 늘어난 원인을 찾는다.
    • Cassandra 오류율에 호출하지 않는 알림을 둘지 검토한다.
    • Cassandra 노드가 down 상태가 되면 호출이나 알림을 보낼지 검토한다.
    교훈

    노드 장애는 디스크 공간이 모자라서 났고, 그 전의 저장 증가 속도로 장애 시점을 내다볼 수 있었다. 노드가 죽기 한참 전에 높은 저장 사용률을 알렸다면 영향이 생기기 전에 막을 기회가 있었다. 5xx 비율로 호출한 것은 맞았다. 다만 Cassandra 노드가 치명적인 수만큼 죽었다는 알림이 따로 있었다면 대응하는 엔지니어에게 상황을 더 잘 알려 줬을 것이다. 지나치게 넉넉하다고 여긴 클러스터도 비정상적인 워크로드가 생기면 감당할 수 없이 빠르게 찰 수 있다. 디스크가 고갈됐을 때 스토리지를 비우는 완화책도 서비스를 흔든다. 그래도 편집이 계속 멈추는 것보다는 영향이 작다. sessionstore 쓰기 비율이 오른 데 워크로드 변화와 SUL3 마이그레이션 같은 요인이 어떻게 얽혔는지는 지금도 파악하기 어렵다.

  3. 증상

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

  4. 증상

    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 근무가 시작되기 바로 전에 발견되었다. 이 시간대는 오래전부터 대응 인력이 비는 때로 알려져 있었다. 트랜스코딩 작업을 미국의 금요일 저녁에 넣지 않은 것도 다행이었다.

  5. 증상

    2024년 9월 18일 데이터센터 전환을 앞두고 cookbook 으로 원형 복제를 설정하던 중, 21:28 UTC 쯤 엔지니어가 x1 섹션의 primary master 가 복제를 하지 않는 것을 orchestrator 에서 먼저 알아챘다. es6 섹션도 같은 상태였다.

    촉발

    다음 주 데이터센터 전환을 앞두고 cookbook 이 핵심 데이터베이스를 eqiad 에서 codfw 로 가는 한 방향 복제에서 원형 복제로 바꿨다. ROW 기반 복제를 쓰는 x1 섹션에 codfw 에서 eqiad 로 가는 복제를 설정하고 pt-heartbeat 를 시작하자, eqiad 서버에 없는 heartbeat 행을 갱신하려다 복제가 멈췄다.

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

    원형 복제의 일반 모니터링이 아직 켜지지 않아, 엔지니어가 orchestrator 에서 먼저 알아챘다. 복제 자동화가 처음 도는 날이라 평소보다 많은 사람이 데이터베이스 상태를 지켜보고 있었다. 사용자에게 영향을 준 eqiad 에서 codfw 로 가는 방향의 고장은 Icinga 알림이 잡았다. 온콜 호출을 받은 사람은 없었다.

    조치
    • SET GLOBAL Replication_wild_ignore_table='heartbeat.%'; 로 heartbeat 테이블 복제를 건너뛰게 해 복제가 다시 흐르게 했다.
    • es 호스트에는 원래 고장이 난 방향에 맞춰, binlog 기록을 끈 채 eqiad 서버마다 빠진 codfw heartbeat 행을 직접 넣었다. 명령은 set sql_log_bin=0; INSERT INTO heartbeat.heartbeat (server_id, shard, datacenter) VALUES (<codfw-server-id>, 'es6' [or 'es7'], 'codfw'); 였다. es6 에서 먼저 시험했고, es7 에는 원형 복제를 설정하기 전에 미리 넣었다.
    • x1 codfw 호스트마다 binlog 기록을 끈 채 빠진 heartbeat 행을 넣어, 임시로 걸어 둔 heartbeat 무시 설정을 대신했다. 명령은 set sql_log_bin=0; INSERT INTO heartbeat.heartbeat (server_id, shard, datacenter) VALUES (<eqiad-server-id>, 'x1', 'eqiad'); 였다.
    후속 조치
    • 같은 문제를 다시 겪지 않게 한다. 빠진 행을 찾으면 직접 넣는 방식을 유력하게 본다.
    • 유지 보수 뒤 복제가 의도대로 양방향으로 동작하는지 확인하는 상태 점검을 cookbook 에 넣는다.
    • 유지 보수를 다른 순서로, 또는 섹션마다 따로 돌릴 수 있는 옵션을 더한다.
    • Phabricator 를 마지막에 한 번만 갱신하지 않고 섹션마다 갱신한다.
    • 모니터링의 빈틈을 메운다.
    • x1 과 ROW 를 쓰는 읽기·쓰기 es 호스트에서 pt-heartbeat-wikimedia 가 자기 세션을 STATEMENT 로 쓰도록 고쳐 배포했다.
    교훈

    원형 복제는 평소 운영 방식이 아니어서 heartbeat 테이블을 지우는 첫 조치가 문제를 eqiad 에서 codfw 로 옮기기만 했다. TRUNCATE 는 DDL 이라 늘 STATEMENT 모드로 전달되므로 이번에는 DELETE 보다 나았겠지만, 더 위험해서 고려하지 않았다. ROW 기반 복제, pt-heartbeat, 서버마다 다른 heartbeat 테이블 행이 겹친 문제는 이전 유지 보수 기록에 없었다. 자동화의 점검은 설정 직후 한 번이 아니라 모든 작업이 끝난 뒤에도 복제 채널을 확인했어야 했다. Wikimedia 는 어느 호스트에서도 sql_skip_slave_counter 를 쓰지 않아 더 큰 문제나 데이터 손실을 피한 것을 잘된 점으로 꼽았다.

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

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

원인별7

업그레이드로 깨진 호환성1건

  1. IL-0236 머신러닝 모델 서빙 클러스터 두 곳에서 투명 프록시로 MediaWiki API 를 부르던 모델 서버들이 약 24시간 5XX 를 냈다

설정 변경5건

  1. IL-0299 Wikimedia CirrusSearch 의 OpenSearch 클러스터에서 인덱스 약 60개가 red 상태가 되어 쓸 수 없었다
  2. IL-0392 데이터센터 전환을 앞두고 원형 복제를 설정하던 중 Wikimedia x1 섹션의 eqiad·codfw 사이 MariaDB 복제가 6분 멈췄다
  3. IL-0459 쿠버네티스 위 MediaWiki 가 TLS 종료에 엉뚱한 인증서를 써서 약 30분 동안 트래픽 1% 가 오류를 받았다
  4. IL-0266 eqiad 코어 라우터 두 대 사이에 라우팅 루프가 생겨 eqiad 가 다른 데이터센터의 공인 IP 주소에 닿지 못했다
  5. IL-0458 Toolforge 쿠버네티스 API 서버가 재시작 뒤 올라오지 못해 몇 시간 동안 클러스터 전체가 멈췄다

용량 한계2건

  1. IL-0298 Wikimedia sessionstore 의 Cassandra 노드가 디스크가 가득 차 잇따라 죽고 쿼럼을 잃어 편집이 실패했다
  2. IL-0232 codfw WikiKube 클러스터에서 Calico 구성 요소가 자원 한도에 걸려 calico-node 파드가 하나씩 죽고 노드가 차례로 빠지면서 MediaWiki 지연과 오류가 났다

배포 결함1건

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

소프트웨어 결함1건

  1. IL-0216 데이터센터 전환 직후 CirrusSearch Elasticsearch 지연이 치솟아 위키 검색이 일부 사용자에게 늦거나 안 됐다

의존성 장애1건

  1. IL-0267 싱가포르 캐시 거점 eqsin 의 전송 회선 두 개가 함께 끊겨 BGP 가 내려가고 eqsin 의 호스트에 닿을 수 없게 됐다

하드웨어 고장1건

  1. IL-0323 s3 주 데이터베이스 마스터 db1075 가 완전히 멈춰 s3 위키 전체가 읽기 전용이 됐다