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

사례33건

33건 중 8~12번째

  1. 증상

    2025년 9월 2일 디스크 용량을 늘리는 작업 중 11:17 UTC 에 primary 데이터베이스 서버 db-02 의 RAID 배열에서 기존 드라이브 하나가 사라졌고 모니터링 알림이 울렸다. RAID 10 이라 데이터는 잃지 않았고 배열은 degraded 모드로 계속 동작했지만, 드라이브가 하나 더 고장 나면 버티지 못할 수 있었다.

    촉발

    디스크 용량을 늘리는 정기 작업 중 primary 데이터베이스 서버 db-02 의 RAID 배열에서 드라이브가 빠져 secondary 인 db-01 로 장애 조치를 했다. 그 뒤 db-02 를 복원하던 운영자가 실패한 복원의 흔적을 지우려다 db-01 에 있던 새 primary 의 데이터 디렉터리를 지웠다.

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

    11:17 UTC 에 db-02 의 RAID 배열에서 드라이브가 빠지자 모니터링 알림이 울렸고 Mythic Beasts 가 문제를 확인했다. 운영자가 db-01 의 데이터 디렉터리를 지운 것을 스스로 알아챘다. 그 뒤 백엔드 팀을 호출하고, 장애 대응을 시작하며 비상 상황을 선언했다.

    조치
    • 16:11 UTC 에 새로 만든 RAID 10 배열로 db-02 서버를 다시 올렸다.
    • 16:50 UTC 에 db-01 에 있던 primary 에서 막혀 있던 WAL 의 S3 보관을 다시 돌아가게 했다. 그래서 db-01 이 쌓인 WAL 을 지울 수 있게 됐다.
    • 17:30 UTC 에 S3 에서 백업을 가져오는 wal-g 로 db-02 에 데이터베이스 복원을 시작했다.
    • 알 수 없는 데이터베이스 상태를 피하려고 Synapse 와 db-01 의 primary 데이터베이스를 모두 내렸다.
    • 18:06 UTC 에 db-01 의 데이터 파티션을 읽기 전용으로 다시 마운트해, 나중에 살릴 경우에 대비해 데이터베이스가 더 망가지지 않게 했다.
    • S3 로 보관되지 못한 WAL 을 db-01 에서 db-02 로 복사해, S3 백업 복원이 끝나면 바로 재생할 수 있게 준비했다.
    • wal-g 를 같은 메이저 버전의 최신 릴리스로 올린 뒤, 전체 백업이 이미 들어 있는 비어 있지 않은 데이터 디렉터리를 받아들이도록 wal-g 를 고쳐 빌드했다. 09:23 UTC 에 이 wal-g 를 db-02 에 써서 S3 에서 다시 받지 않고 증분 백업을 복원했다.
    • S3 와 db-01 에서 옮겨 온 파일 시스템 양쪽에서 WAL 을 가져오는 래퍼 스크립트로 restore_command 를 설정하고 Postgres 를 standby 모드로 띄웠다. 11:00 UTC 부터 WAL 을 재생했다.
    • 16:45 UTC 에 db-02 를 primary 데이터베이스로 승격하고, Synapse 시험 worker 를 띄워 새 WAL 이 S3 에 올라오는 것을 확인한 뒤 16:54 에 Synapse 를 시작했다. 18:00 에 모든 worker 가 안정됐다.
    • WAL 재생이 느렸기 때문에, 없어진 복제본 대신 primary 데이터베이스에서 백업을 받도록 다시 설정했다. 03:26 UTC 에 새 증분 백업이 끝났다.
    • db-01 에 NVMe 디스크 두 개를 RAID 배열과 LVM 볼륨 그룹에 넣었다. 배열 재구성 중 재부팅해 서버가 올라오지 않자 배열을 부팅할 수 있는 상태로 고쳤고, db-02 의 basebackup 을 복사해 db-01 을 다시 복제 상태로 두었다.
    후속 조치
    • 저장 공간이 늘어난 지금 pg_repack 을 돌려 빈 공간을 되찾는다.
    • 증분 백업은 WAL 재생보다 훨씬 빨리 복원되므로 증분 백업을 더 자주 받도록 이미 바꿨다.
    • Synapse 가 데이터를 저장하는 방식을 고쳐 앞으로 필요한 저장 공간을 크게 줄인다.
    • 데이터베이스가 클러스터에서 맡은 역할에 따라 터미널 배경색을 바꾸는 방법을 검토한다. 데이터 디렉터리에 standby.signal 파일이 있는지 보고 primary 인지 secondary 인지 판단해 배경색을 바꾸는 안이 나왔다.
    • rm 의 alias 처럼 위험한 명령을 감싸는 래퍼 스크립트를 두거나, primary 에서 secondary 로 base backup 을 시작하는 일 같은 작업을 자동화하는 방법을 논의했다.
    • 복구 목표 시간을 줄인다. 더 쉽고 빠르게 복구할 수 있는 무료 인프라를 얻으려고 서비스 제공자들과 이야기하고 있다.
    • 재해 복구 서버뿐 아니라 모든 서버의 wal-g 를 올렸고, 올린 wal-g 로 재해 복구 시험을 한 차례 했다. 재해 복구 서버와 운영 서버를 계속 같게 유지하는 방법은 아직 찾지 않았다.
    • 다음 하드웨어 교체 때 ZFS 를 검토해, 엉뚱한 데이터베이스를 지우는 사고에서도 로컬 스냅숏으로 훨씬 빨리 복구할 수 있게 한다.
    • 장애 대응 절차에 status.matrix.org 를 장애 중 공식 정보원으로 갱신하는 단계를 넣고, advocacy 팀과 함께 소셜 미디어도 계속 갱신한다.
    교훈

    이번 장애가 이렇게 힘들었던 데에는 데이터베이스가 너무 크다는 점이 크게 작용했다. 엉뚱한 서버에서 파괴적인 명령을 실행한 것이 결정적인 순간이었다. 하지만 팀은 개인을 탓하지 않고, 사람이 쓰는 도구와 절차를 고쳐 같은 일이 다시 일어날 가능성을 줄여야 한다고 보았다. 세 사람이 함께 작업했지만 급박한 상황에서는 실수를 잡지 못했다. db-01 은 primary, db-02 는 secondary 처럼 읽히지만 실제 역할은 서로 바뀔 수 있으므로, 뜻이 담긴 서버 이름은 혼란을 부른다. primary 와 secondary 를 모두 잃고도 데이터를 잃지 않은 것은 정기적으로 시험한 특정 시점 복구 절차 덕분이었다. 다만 복구 목표 시간은 줄여야 한다. 재해 복구 시험에서 찾은 wal-g 수정이 운영 서버에 빠져 있었으므로, 재해 복구 서버와 운영 서버를 같게 맞춰야 한다.

  2. 증상

    2025년 6월 25일 21:33 UTC 부터 OpenStreetMap.org 의 minutely, hourly, daily 복제 diff 가 새로 만들어지지 않았다. 21:40 UTC 에 Alertmanager 가 운영 팀에 "minutely replication feed delayed - 6m 2s" 라는 첫 알림을 보냈다.

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

    Alertmanager 가 이 일과 관련된 알림을 여러 번 보냈고, 첫 알림은 21:40 UTC 의 "minutely replication feed delayed - 6m 2s" 였다. 호출기나 SMS 로 가는 알림은 울리지 않았다.

    조치
    • 6월 26일 06:08 UTC 에 osmdbt 타이머를 멈췄다.
    • 12:56 UTC 에 OpenStreetMap.org 를 읽기 전용 점검에 들여 지도 편집을 막았다.
    • osmdbt 의 fakelog 도구를 손으로 써서 실패를 일으킨 PostgreSQL 복제 상태를 건너뛰었고, 13:13:47 부터 13:17:04 UTC 까지 replication/minute/006/658/640 부터 673 까지 diff 를 만들었다.
    • 13:21:10 UTC 에 osmdbt 타이머를 다시 켜 minutely diff 생성을 되살렸다.
    • 13:22 UTC 에 약 25분 동안의 읽기 전용 점검을 끝냈다.
    후속 조치
    • PostgreSQL 을 17.x 로 업그레이드한다.
    • PostgreSQL 개발자에게 이 문제를 이슈로 올린다.
    교훈

    osmdbt 개발자와의 소통이 우회 계획을 세우는 데 결정적이었다. 운영 팀은 osmdbt 를 충분히 이해하지 못하고 있었다.

  3. 증상

    AWS eu-west-1 에 복제본이 있는 Upstash 리전 Redis 데이터베이스 일부에서 성능이 떨어지고 지연이 높아졌다. 이 데이터베이스들의 CPU 부하가 매우 높았다.

    촉발

    AWS eu-west-1 의 리전 Upstash Redis 데이터베이스에 유지보수 업데이트를 하던 중, 그 리전의 여러 데이터베이스가 주 복제본과 백업 복제본 사이에서 필요 없는 전체 동기화를 시작했다.

    원인
    구성 요소
    기여 요인
    조치
    • AWS eu-west-1 의 리전 데이터베이스 클러스터에 자원을 더했다.
    • 15:06 UTC 에 영향받은 데이터베이스의 스로틀링을 풀고 처리량을 늘렸다.
    후속 조치
    • 리전 데이터베이스에서 불필요한 전체 동기화가 일어나지 않게 하는 수정을 배포한다.
    • 리전 데이터베이스 사용자에게 Upstash Global 로 옮기는 방법을 안내한다.
  4. 증상

    2024년 12월 15일 03:53 UTC 에 OpenStreetMap.org 에 접속할 수 없게 됐고, 04:01 UTC 에 StatusCake 모니터링이 장애를 잡아 SMS 알림을 보냈다. 웹사이트와 지도 API 가 완전히 내려갔다.

    촉발

    2024년 12월 15일 03:53 UTC 에 HE.net 의 암스테르담 라우팅 장비가 예기치 않게 고장 났다.

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

    04:01 UTC 에 StatusCake 모니터링이 장애를 잡아 SMS 알림을 보냈고, 곧바로 운영 팀에 알려졌다.

    조치
    • 11:31 UTC 에 더블린에 있는 OpenStreetMap.org 의 읽기 전용 백업 인스턴스를 켜 일부 기능을 되살렸다. 사이트에는 편집 내용을 저장할 수 없다는 점검 안내를 띄웠다.
    • 12월 17일 12:21 UTC 에 HE.net 을 거치지 않는 새 Equinix Internet 회선을 암스테르담에서 개통해 OpenStreetMap.org 와 API 의 모든 기능을 되살렸다.
    • 12월 18일 00:29 UTC 에 HE.net 이 암스테르담 서비스가 복구됐다고 확인했고, HE.net 경로가 정상으로 돌아와 OpenStreetMap.org 의 모든 네트워크 경로를 다시 쓸 수 있게 됐다.
    후속 조치
    • 한 사업자가 고장 나도 다른 사업자로 거의 끊김 없이 넘어가도록 여러 ISP 를 쓰는 구성으로 옮긴다.
    • 암스테르담 서버의 예비 ISP 후보를 대역폭, 신뢰성, 비용으로 비교한다. 2025년 2월 Karlsruhe Hack Weekend 에서 BGP 를 쓰는 방안과 HE.net 을 예비 ISP 로 남기는 방안을 포함해 실제 선택지를 논의한다.
    • 경로와 지연 시간을 더 깊이 모니터링해 ISP 문제를 빨리 잡고, 자동 에스컬레이션 절차를 만든다.
    • ISP 사이 트래픽 전환을 시험하는 페일오버 훈련 일정을 정하고, 복제 과정이 최신이며 믿을 만한지 확인해 사이트 페일오버를 부담 없이 쓸 수 있는 선택지로 만든다.
    • HE.net, Equinix Internet 과 계약상 SLA 를 협의하고, 정해진 에스컬레이션 절차와 응답 시간을 계약에 넣는다.
    • 대역 외 접속에 쓰는 Raspberry Pi 4 와 4G 모뎀을 ISP 장애 때 수동 예비 업링크로 쓸 수 있게 미리 설정한다. 이 회선으로 서버에 접속하고 Postgres 복제 데이터를 보조 사이트로 동기화한다. 대역 외 장비는 견고하고 이중화되도록 업그레이드한다.
    • 장애 소식을 알리는 일을 맡을 이해관계자와 각자의 책임, 권장 소통 채널을 정리한 문서를 만든다. 운영 팀은 소통을 다른 사람에게 맡기고 복구에 집중한다.
    • OpenStreetMap.org 의 "rails-port" 유지 관리자가 OAuth 서비스를 분리해, 사이트가 흔들릴 때도 제3자 서비스의 인증이 계속 동작하게 할 수 있는지, 그 방법이 현실적인지 조사한다.
    교훈

    암스테르담 서버가 HE.net 하나에만 기대고 있어 단일 장애 지점이 생겼고, 앞으로는 상위 사업자를 여럿 둔다. 4G 예비 회선을 쓴 대역 외 접속이 아주 쓸모 있었으므로, 데이터 동기화까지 할 수 있게 신뢰성과 기능을 넓힌다. 읽기 전용 백업으로 일부 서비스는 됐지만, 복제가 이어지고 있었다면 편집 기능을 더 빨리 되살렸을 것이다. ISP 와 자주 연락해도 쓸 만한 복구 예상 시각을 받지 못했으므로, SLA 를 더 잘 이해하고 ISP 에 더 투명하게 알려 달라고 요구해야 한다. 상위 연결의 알림을 다듬고 여러 모니터링 출처의 데이터를 한데 모아야 문제를 더 빨리 짚을 수 있다. OpenStreetMap.org 가 읽기 전용이 되면 새 토큰을 저장하지 못해, 장애와 무관한 community.openstreetmap.org 같은 서비스에도 로그인할 수 없게 된다.

  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 를 쓰지 않아 더 큰 문제나 데이터 손실을 피한 것을 잘된 점으로 꼽았다.

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

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

원인별11

용량 한계6건

  1. IL-0379 Azure West Europe 의 InfluxDB Cloud 에서 9월 27일부터 30일까지 쿼리가 느려지고 타임아웃됐다
  2. IL-0288 CDN77 의 ClickHouse 데이터 파이프라인에서 이중화된 인스턴스 세 곳의 ZooKeeperWait 가 수천 초로 치솟아 복제가 한 시간 넘게 느려졌다
    CDN772026
  3. IL-0305 Intercom 의 PlanetScale 샤드 하나에서 복제본이 CPU 100% 로 주 데이터베이스를 따라가지 못해 받은편지함에 최대 2.2시간 전의 데이터가 보였다
  4. IL-0443 Aurora MySQL reader 가 이유 없이 재시작한 뒤 writer 의 insert latency 가 7배쯤 오르고 replication lag 가 하루 넘게 이어졌다
    Repro2019
  5. IL-0334 RDS MySQL 의 bookmarks 테이블이 2TB 파일 크기 한도에 닿아 INSERT 가 실패하고 Instapaper 가 31시간 동안 멈췄다
  6. IL-0296 Transloadit 의 us-east 리전 Redis 클러스터가 대역폭에 막혀 작업과 하트비트를 잃었다

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

  1. IL-0569 MySQL master 장애 때 MHA 자동 Failover 뒤 slave 한 대가 relaylog를 적용하지 못해 레플리케이션이 멈췄다
    DeNA2026
  2. IL-0308 RevenueCat 이 Aurora PostgreSQL 10 에서 14 새 클러스터로 넘어간 직후 쿼리가 극도로 느려져 대시보드와 SDK 엔드포인트가 세 시간 넘게 실패했다

인증서·자격 증명 만료1건

  1. IL-0490 관리형 데이터베이스에서 자체 MySQL로 옮긴 뒤 이전 직전에 쓴 기록이 새 데이터베이스에 없어 LootLocker 서비스가 저하됐다

소프트웨어 결함5건

  1. IL-0281 PostHog US 리전 Logs 제품의 ClickHouse 클러스터가 S3 에 둔 로그 데이터를 거의 다 지워 3일보다 오래된 로그가 사라졌다
  2. IL-0527 OpenStreetMap.org 의 복제 diff 생성이 invalid memory alloc request size 오류로 16시간 멈춤
  3. IL-0376 AWS eu-west-1 의 Upstash 리전 Redis 데이터베이스가 CPU 부하로 몇 시간 동안 느려졌다
  4. IL-0589 Kickstarter 의 모든 MySQL 복제본이 중복 키 오류로 복제를 멈췄다
  5. IL-0303 GitHub 의 새 3노드 MySQL 클러스터에서 자동 페일오버가 잘못 일어나고 클러스터 상태가 갈라져 GitHub.com 이 두 번 멈췄다
    GitHub2012

클라우드 제공자 장애2건

  1. IL-0368 AWS us-east-1 장애 동안 PlanetScale 컨트롤 플레인이 멈추고, 이어 일부 데이터베이스 브랜치가 네트워크 분할로 쿼리에 실패했다
  2. IL-0488 EBS 성능 저하 뒤 Kit의 RDS MySQL 쓰기 지연이 100배 넘게 늘어 Sidekiq 작업 처리가 느려졌다
    Kit2022

운영 실수4건

  1. IL-0242 primary 와 secondary PostgreSQL 데이터베이스를 모두 잃어 matrix.org homeserver 가 약 24시간 동안 멈췄다
  2. IL-0431 AWS 로 옮기는 점검 중 PostgreSQL 이 의도하지 않게 장애 조치되어 한 시간 동안 갱신된 데이터가 사라졌다
    Hatena2017
  3. IL-0218 복제를 다시 맞추다 PostgreSQL 프라이머리의 데이터 디렉터리가 지워지고 백업이 작동하지 않아 GitLab.com 이 약 18시간 멈추고 데이터를 잃었다
    GitLab2017
  4. IL-0319 mysql2 를 다시 적재하려고 데이터베이스를 지우는 동안 mysql1 의 데이터베이스도 함께 지워졌다

의존성 장애2건

  1. IL-0526 HE.net 암스테르담 라우팅 장비 고장으로 OpenStreetMap.org 의 이중 광 회선이 모두 끊김
  2. IL-0255 데이터센터 사이 메트로 회선이 잠깐 끊긴 뒤 Redis 레플리카가 재동기화 루프에 빠져 BC3 가 느려지고 채팅이 멈췄다

설정 변경6건

  1. IL-0392 데이터센터 전환을 앞두고 원형 복제를 설정하던 중 Wikimedia x1 섹션의 eqiad·codfw 사이 MariaDB 복제가 6분 멈췄다
  2. IL-0374 DigitalOcean 내부 서비스 디스커버리가 전 리전에서 멈춰 생성, 이벤트 처리, 제어판과 API 관리가 실패했다
  3. IL-0331 RDS MySQL Multi-AZ 장애 조치 뒤 읽기 복제본 다섯 대의 복제가 모두 깨지고 데이터 5초 분량이 사라졌다
  4. IL-0430 Redis 장애 조치 뒤 Mackerel 전체가 느려지고 생존 여부 감시가 4시간 넘게 멈췄다
    Hatena2018
  5. IL-0325 주 데이터베이스가 지워져 DigitalOcean 제어판과 API 가 4시간 56분 동안 멈췄다
  6. IL-0215 Twilio 결제 시스템의 Redis 가 잔액 데이터를 잃고 읽기 전용이 되어 자동 충전 고객의 신용카드가 반복 결제됐다
    Twilio2013

데이터 손상1건

  1. IL-0311 주 PostgreSQL 데이터베이스가 트랜잭션 ID wraparound 보호로 읽기 전용이 되어 웹사이트와 백엔드 서비스가 멈췄다

DNS·네트워크 장애3건

  1. IL-0240 인증 데이터베이스가 과부하에 걸려 Cloudflare API 와 대시보드가 6시간 33분 동안 실패하고 느려졌다
  2. IL-0210 43초 네트워크 단절 뒤 MySQL 프라이머리가 미국 서부로 넘어가 GitHub.com 이 24시간 11분 동안 느려지고 오래된 데이터를 보여 줬다
    GitHub2018
  3. IL-0590 Rackspace ORD 재부팅 뒤 Mailgun 연결이 간헐적으로 실패하고 이벤트 유실과 이메일 중복 발송이 났다

하드웨어 고장1건

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