사례3건
3건 중 1~3번째
- 증상
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월 7일 목요일, Kickstarter 트래픽 대부분을 받는 MySQL 복제본들이 갱신을 멈췄다. 복제본 하나만 멈췄다면 그 복제본을 갈아 끼우면 됐지만, 모든 복제본이 같은 상태였다.
- 촉발
데이터가 이미 어긋나 있는 상태에서, 나중에 실행된 unsafe 쿼리가 MIXED 모드 복제를 row 기반 복제로 바꿨다. 복제본이 그 행의 새 값을 그대로 쓰려다 고유 키가 겹쳐 복제가 멈췄다.
- 원인
- 구성 요소
- 기여 요인
- –
- 감지
트래픽 대부분을 받는 복제본들이 모두 갱신을 멈춘 것을 보고 알았고, SHOW SLAVE STATUS\G 에서 중복 키 복제 오류를 확인했다.
- 교훈
데이터베이스는 복잡하다. Rails 커뮤니티에서는 데이터베이스를 ActiveRecord 와 ActiveRelation 뒤에 숨은 단순한 데이터 저장소로 여기기도 하지만, 데이터베이스가 요청받은 일을 어떻게 처리하는지 더 깊이 알아야 한다.
- 증상
2012년 9월 10일 월요일, 스키마 마이그레이션이 데이터베이스에 높은 부하를 걸자 Percona Replication Manager 의 헬스 체크가 마스터에서 실패했다. Percona Replication Manager 는 'active' 역할을 다른 노드로 옮겼고, 새 노드가 느려지면서 GitHub.com 이 멈췄다.
- 촉발
무중단 MySQL 스키마 마이그레이션이 이전의 같은 종류 마이그레이션보다 높은 부하를 데이터베이스에 걸었고, 그 부하로 Percona Replication Manager 의 헬스 체크가 마스터에서 실패했다.
- 원인
- 구성 요소
- 기여 요인
- 감지
9월 11일 아침 한 개발자가 'standby' 역할을 맡은 노드에서 잘못된 쿼리 결과가 나온다고 운영팀에 알렸다. 그 뒤 운영팀은 혼자 마스터로 뽑힌 'c' 노드가 앞서 데이터가 뒤처졌다고 판단한 노드라는 것을 알아챘다.
- 조치
- 9월 10일 Pacemaker 의 maintenance-mode 를 켜서 모든 헬스 체크와 자동 페일오버 동작을 멈췄다.
- 9월 11일 8:26 AM 에 데이터가 뒤처진 'c' 노드의 전원을 꺼서 갈라진 클러스터 상태를 끝내고 데이터가 더 어긋나지 않게 했다.
- 클러스터 상태를 깨끗하게 되살리려고 'a' 와 'b' 두 노드에서 Pacemaker 와 Heartbeat 프로세스를 모두 멈춘 뒤 'a' 노드에서 다시 띄웠다.
- 'a' 노드에서 MySQL 을 띄워 'active' 역할을 맡게 했다.
- 다른 사용자의 대시보드에 새어 나간 이벤트를 모두 지우고, 그 시간에 경로가 잘못 잡힌 저장소를 모두 점검했다.
- 협업자가 아닌 사람에게 열려 있던 비공개 저장소 16개의 소유자에게 모두 직접 연락했다.
- 후속 조치
- Pacemaker 설정을 바꿔 'active' 데이터베이스 역할의 페일오버는 운영팀 사람이 시작할 때만 일어나게 한다.
- 비상시나 정기 유지보수 때 페일오버를 해도 성능이 떨어지지 않도록, 복제본 데이터베이스의 InnoDB 버퍼 풀을 미리 데우는 여러 방법을 조사하고 시험한다.
- 화요일에 segfault 를 일으킨 코드 경로를 중심으로 Pacemaker 와 Heartbeat 스택 전체를 점검한다.
- 만일에 대비해 segfault 가 난 서버에서 강도 높은 하드웨어 시험을 한다.
- 교훈
GitHub 은 이번 장애에 세 가지가 겹쳤다고 밝혔다. 일어나지 말았어야 할 'active' 역할 페일오버가 여러 번 일어났고, 클러스터 상태가 갈라져 클러스터 관리 소프트웨어가 잘못된 동작을 했으며, 그 페일오버들이 필요 이상으로 성능과 가용성을 해쳤다. 두 장애는 모두 자동 페일오버에서 시작했는데, 그 페일오버를 해야 하느냐고 운영팀 누구에게 물었어도 하지 말아야 한다고 답했을 것이다. GitHub 은 자동 페일오버가 서비스 가용성을 지키는 좋은 방법인 경우가 많지만, 주 운영 데이터베이스는 그런 경우가 아니라고 결론 내렸다.
이 3건에서 가장 많이 나오는 구성 요소: 데이터베이스, 데이터베이스 복제. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.