그래프
사례3건
3건 중 1~3번째
IL-0308RevenueCat 이 Aurora PostgreSQL 10 에서 14 새 클러스터로 넘어간 직후 쿼리가 극도로 느려져 대시보드와 SDK 엔드포인트가 세 시간 넘게 실패했다RevenueCat2022- 증상
2022년 11월 23일 9:39 UTC 에 트래픽 전부가 새 Aurora PostgreSQL 14.x 클러스터로 넘어갔고, 지연이 나빠져 인프라 팀이 조사를 시작했다. 9:54 UTC 에는 쿼리가 평소보다 훨씬 오래 걸리면서 데이터베이스 연결을 모두 차지하고 있었다.
- 촉발
복제를 이용해 Aurora PostgreSQL 10.x 클러스터에서 새 14.x 클러스터로 트래픽을 넘겼다. 그런데 가장 큰 테이블 하나의 vacuum 이 전환 전에 끝나지 않아, 새 클러스터의 가장 큰 테이블들에 ANALYZE 가 돌지 않은 상태였다.
- 원인
- 구성 요소
- 기여 요인
- 감지
9:39 UTC 에 트래픽 전부가 새 클러스터로 넘어갔을 때 지연이 나빠 보였고, 인프라 팀이 바로 조사를 시작했다.
- 조치
- 9:54 UTC 에 쿼리가 데이터베이스 연결을 너무 오래 잡지 않도록 데이터베이스 사용자에 statement timeout 을 걸었다.
- 9:58 UTC 에 로드 밸런서에서 트래픽의 90% 에 503 을 보내 부하를 덜고 시스템이 회복할 여유를 만들었다.
- 10:00 UTC 무렵부터 오래 걸리는 쿼리에 EXPLAIN 을 돌려 보고, 해만 끼치고 필요 없는 인덱스를 지우기 시작했다.
- 트래픽을 100% 로 되돌리는 동안 Apple 웹훅을 잠시 받지 않았다.
- New Relic 이 느린 쿼리마다 돌리는 EXPLAIN 쿼리를 없애려고 New Relic 을 끈 새 릴리스를 냈다.
- 12:00 UTC 무렵부터 가장 큰 테이블들에 손으로 ANALYZE 를 돌렸다.
- 미리 준비해 둔 스크립트로 영향받은 시퀀스 값을 자동으로 올려 기본 키 중복을 풀었다.
- 전환 몇 분 뒤 통합 이벤트 발송 작업이 이벤트 테이블을 갱신하지 못하는 것을 잡고 발송 작업을 손으로 멈췄다.
- 발송되었지만 데이터베이스에 기록되지 않은 웹훅을 만일에 대비해 다시 보냈다.
- 13:33 UTC 에 통합 이벤트 발송, ETL, 웹 서버 밖의 작업을 모두 되살렸다.
- 후속 조치
- 사업에 중요한 시기에는 변경 동결을 두는 것을 검토한다.
- 백엔드 장애 때 SDK 가 얼마나 믿을 만하게 동작하는지 더 잘 알린다.
- 개발자 대시보드와 기술 담당자에게 보내는 직접 이메일을 써서 유지보수와 장애를 고객에게 더 잘 알린다.
- 사전 연습에서 트래픽 일부를 재생해 전환 당일과 더 비슷한 조건을 만든다. 이번 연습은 쓰기 트래픽을 재생하지 않았다.
- API 를 빠르고 안정적으로 유지하려고 비용이 큰 작업을 최대한 비동기로 옮기는 데 더 투자한다.
- 테이블 인덱스를 다시 검토한다. 쓰이지 않는 인덱스가 있고, 데이터베이스가 쿼리에 그 인덱스를 고르면 성능이 떨어질 수 있다.
- 데이터베이스 대시보드에서 엔드포인트와 시스템별 부하를 더 잘 보여 줘 부하가 어디서 오는지 빨리 찾게 한다. 이번에는 Apple 웹훅 부하가 복구를 막는다는 것을 아는 데 너무 오래 걸렸다.
- 장애 중에 고객 지원과 고객 커뮤니케이션 담당을 불러 소통을 맡긴다.
- 교훈
RevenueCat 은 처음부터 롤백했으면 더 나았다고 돌아봤다. 사전 연습에서는 데이터 일관성과 쿼리 성능만 보고 쓰기 트래픽을 재생하지 않았다. 쓰기는 인덱스가 얽히지 않아 읽기보다 단순하다고 여겼기 때문이다. 복제를 멈추고 평소처럼 쓰기를 해 봤다면 문제를 찾을 수 있었다. 시퀀스 상태가 복제되지 않는다는 한계를 놓치고 상태도 함께 복제된다고 가정했다. 사전 연습 때는 새 클러스터가 오래 떠 있어 vacuum 과 통계가 이미 끝나 있었기 때문에 ANALYZE 가 없는 문제를 보지 못했다. 시기로는 추수감사절과 블랙 프라이데이 전에 끝내려 했지만, 미국 지원팀 일부가 이미 휴가 중인 민감한 때였으므로 그다음 주로 미뤘어야 했다고 밝혔다.
- 증상
2022-03-27 3:23 UTC 에 계정, 서버, 플레이어 정보를 담는 주 PostgreSQL 데이터베이스가 쓰기를 받지 않았다. 처음 보인 증상은 사용자가 웹사이트를 불러오지 못하는 것이었다.
- 촉발
플레이어 식별자 테이블의 인덱스가 알 수 없는 이유로 손상돼 vacuum 작업이 모두 오류로 끝났다. 로그로 보아 손상은 약 한 달 전인 2022-02-26 에 생긴 것으로 추정했고, 그동안 트랜잭션 ID 가 계속 쌓여 2022-03-27 에 wraparound 보호가 작동했다.
- 원인
- 구성 요소
- 기여 요인
- 감지
처음 들어온 것은 웹사이트를 불러오지 못한다는 사용자 신고였다. 팀은 30분쯤 전에 작동한 DDoS 방어 탓으로 보았다가, RCON 업데이트와 쿼리가 실패하는 것을 보고 더 살펴본 끝에 주 데이터베이스가 쓰기를 받지 않는 것을 찾았다.
- 조치
- 데이터베이스를 내리고 single-user mode 로 들어가 손상된 인덱스를 지운 뒤 데이터베이스를 다시 올렸다.
- vacuum 을 다시 돌렸고, 이번에는 성공해 데이터베이스가 다시 쓰기를 받았다.
- 지운 플레이어 식별자 인덱스를 약 두 시간에 걸쳐 다시 만들었다.
- 데이터베이스가 돌아온 뒤 쿼리 워커를 모두 멈추고 RCON 업데이트를 우선했다.
- 인덱스가 돌아오자 서비스가 새 Postgres primary 를 가리키게 했다.
- replica 를 더 부트스트랩해 하나 올라올 때마다 primary 부하를 덜었고, 16:30 UTC 에 RCON 업데이트를 따라잡았다.
- RCON 업데이트가 늦어지지 않게 쿼리를 제한해서 다시 돌렸고, 쿼리의 우선순위는 서버의 현재 접속 인원과 순위로 매겼다.
- 후속 조치
- Postgres 로그의 오류를 모니터링한다.
- 트랜잭션 ID 를 모니터링하고 알림을 건다.
- 물리 복제에 더해 논리 replica 를 둔다.
- 장애에서 더 빨리 복구하도록 더 빠른 네트워크를 갖춘다.
- 교훈
BattleMetrics 는 Postgres 의 트랜잭션 ID 크기를 확인하는 헬스 체크를 두지 않은 것을 결정적인 실수로 보았다. 인덱스 손상은 사이트 성능에 영향이 없어 한 달 동안 드러나지 않았고, 그동안 vacuum 이 계속 실패하며 데이터베이스가 wraparound 에 다가갔다. 손상은 replica 에도 복제돼 있어 장애 조치가 소용없었고, 백업 서버와 내려받기용 백업도 같은 손상을 안고 있었다. 오류 문구와 달리 wraparound 보호에 들어간 서버에서도 single-user mode 없이 전체 vacuum 을 돌릴 수 있었다.
IL-0334RDS MySQL 의 bookmarks 테이블이 2TB 파일 크기 한도에 닿아 INSERT 가 실패하고 Instapaper 가 31시간 동안 멈췄다Instapaper2017- 증상
2월 9일 수요일 12:30PM PT 부터 Instapaper 사용자가 저장한 글을 담는 MySQL 의 bookmarks 테이블에 새 항목을 넣으면 오류가 나기 시작했다. Instapaper 서비스는 2월 10일 목요일 7:30pm PT 까지 멈췄다.
- 촉발
2월 9일 수요일 12:30PM PT 에 bookmarks 테이블이 2TB 파일 크기 한도를 넘었다.
- 원인
- 구성 요소
- 기여 요인
- 조치
- Pinterest SRE 팀의 안내로 Instapaper 운영 데이터베이스를 i2.8xlarge 인스턴스의 5.5TB RAID-0 디스크에 덤프했다. 첫 시도는 24시간, 병렬로 돌린 두 번째 시도는 10시간이 걸렸다.
- 덤프가 너무 오래 걸리자 아카이브 접근을 제한한 채 동작하는 인스턴스를 약 6시간 만에 만들어, 31시간의 다운타임 끝에 운영에 올렸다.
- 옛 데이터베이스의 Aurora 읽기 복제본을 만들었다. Aurora 는 Instapaper 코드로 충분히 시험해 보지 않아 위험하다고 봤지만 만들기는 쉬웠다. 약 24시간 만에 끝났다.
- 새 MySQL RDS 인스턴스를 만들어 보조 인덱스 없이 데이터를 모두 넣었다. 8시간이 걸렸다. 그 뒤 보조 인덱스 세 개를 하나에 약 16시간씩 만들었다.
- Amazon 엔지니어가 실패한 운영 데이터베이스에 ext4 파일 시스템을 마운트하고 ext3 파일 시스템에서 ext4 파일 시스템으로 rsync 를 약 8시간 돌려, 데이터와 인덱스가 모두 있는 ext4 데이터베이스 인스턴스를 만들었다.
- RDS 엔지니어들이 임시 운영 데이터베이스의 바이너리 로그로 새 ext4 데이터베이스에 행 기반 복제를 걸어 목요일부터 월요일까지의 변경을 맞췄다. 약 3시간이 걸렸다.
- 새 데이터베이스를 마스터로 승격하고 애플리케이션 코드가 새 데이터베이스를 가리키도록 배포했다.
- 후속 조치
- Instapaper 전체 장애가 나면 Pinterest 의 SRE 팀에 바로 에스컬레이션하는 절차를 만든다.
- MySQL 백업 시험 주기를 석 달에 한 번에서 한 달에 한 번으로 늘린다.
- Pinterest 의 SRE 팀과 함께 이런 장애가 다시 나면 복구할 수 있는 절차를 마련한다.
- 교훈
팀이 알지 못했고 볼 수도 없었던 파일 시스템 한도 때문에 운영 데이터베이스뿐 아니라 모든 백업까지 쓸 수 없게 됐다. 호스팅된 인스턴스에는 MySQL 로만 접근할 수 있어서 rsync 같은 파일 시스템 수준의 해결책은 Amazon 엔지니어의 도움 없이는 쓸 수 없었다. 완벽하게 대응했어도 진단부터 데이터베이스 재구축까지 다운타임은 최소 10시간이었을 것이다. 이 문제는 미리 내다보고 막기 어려웠지만, 이런 장애를 위한 재해 복구 계획이 없어 다운타임과 복구 시간이 필요 이상으로 길어졌다. 데이터베이스를 다시 만드는 데 며칠이 걸린다는 것을 알았다면 곧바로 제한된 서비스 복구로 들어가 첫날의 다운타임을 크게 줄일 수 있었다. Pinterest 안에서, 그리고 AWS 팀과 더 잘 소통했다면 쓸 수 있는 자원을 더 잘 활용했을 것이다. 글쓴이는 다른 회사가 호스팅하는 기술이라도 매일 운영에 쓰는 기술의 한도를 이해하는 것이 자신의 책임이라고 밝혔다.
이 3건에서 가장 많이 나오는 구성 요소: 데이터베이스, 데이터베이스 복제. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.