사례4건
4건 중 1~4번째
- 증상
9월 27일 22:58 UTC 에 쿼리 큐 깊이 알림이 울렸다. Azure West Europe 리전 고객의 쿼리가 느려지고 타임아웃됐다. 쓰기는 계속 받았지만 일부 파티션에서는 새 데이터를 바로 조회할 수 없었다.
- 원인
- 구성 요소
- 기여 요인
- 감지
9월 27일 22:58 UTC 에 쿼리 큐 깊이 알림이 울려 장애 대응이 시작됐다.
- 조치
- 쿼리 계층 용량을 두 배로 늘렸다.
- 9월 28일 아침에 멈춘 스토리지 파드를 하나씩 재시작했다.
- 9월 29일 08:58 UTC 에 readiness 검사 타임아웃을 올려 전체에 배포했다.
- 재시작 뒤 복구 동시성을 두 배로 늘렸다.
- 9월 30일 00:25 UTC 에 정리 타임아웃을 24시간으로 올려 안전장치가 일으키던 강제 재시작을 멈췄다.
- 스토리지 파드마다 자원 요청을 올려 호스트에 올라가는 파드 수를 줄였고, 파드마다 페이지 캐시용 메모리와 디스크 처리량이 두 배가 됐다.
- 후속 조치
- 페이지 폴트 비율, 캐시 커버리지, 스토리지 볼륨의 디스크 읽기, 쿼리 중단 비율에 경고 알림을 더했다. 알림은 캐시 압박이 고객에게 보이기 전에 울리도록 만들었다.
- 런북에 major page fault 를 스토리지 성능 저하의 선행 지표로 적고, 조정할 수 있는 완화 설정을 자세히 적었다.
- 스토리지 엔진의 참조 누수를 계속 추적한다.
- 디스크 검사를 상태 검사 경로에서 뺀다.
- 교훈
캐시가 모자란 상태는 메모리 지표에 드러나지 않았다. 스토리지 프로세스가 메모리를 적게 쓰고 나머지를 페이지 캐시가 차지하기 때문이다. InfluxData 는 major page fault 를 스토리지 성능 저하의 선행 지표로 본다. InfluxData 는 스토리지 엔진의 참조 누수와 상태 검사 경로의 디스크 검사가 이런 장애를 일으키는 위험 요인은 아니며, 진단과 복구 중에 눈에 띄어 조사할 만한 현상이라고 밝혔다.
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 가 없는 문제를 보지 못했다. 시기로는 추수감사절과 블랙 프라이데이 전에 끝내려 했지만, 미국 지원팀 일부가 이미 휴가 중인 민감한 때였으므로 그다음 주로 미뤘어야 했다고 밝혔다.
IL-0443Aurora MySQL reader 가 이유 없이 재시작한 뒤 writer 의 insert latency 가 7배쯤 오르고 replication lag 가 하루 넘게 이어졌다Repro2019- 증상
Aurora MySQL 의 reader 가 이유를 알 수 없이 재시작했다. 그 직후부터 writer 의 insert latency 가 7배쯤 오르는 등 writer 성능이 크게 떨어진 상태가 오래 이어졌다. 같은 일이 2019년 11월 두 주 사이에 두 번 일어났다.
- 촉발
reader 에서 오래 도는 쿼리 때문에 롤백 세그먼트가 계속 커진 끝에 reader 가 재시작했다. 글쓴이는 그 쿼리가 Redash 에서 reader 로 보낸 것이었다고 기억한다.
- 원인
- 구성 요소
- 기여 요인
- 조치
- 팀은 writer 성능이 원래대로 돌아올 때까지 지켜보기만 했다.
- 후속 조치
- 롤백 세그먼트 길이를 Datadog 의 mysql.innodb.history_list_length 로 감시하는 모니터를 더했다.
- reader 가 재시작할 만큼 오래 도는 쿼리를 찾으면 바로 kill 하게 했다.
- 모니터 알림이 거의 매주 울리게 되자 사내에 알린 뒤 max_execution_time 을 설정해, 일정 시간이 지난 쿼리를 강제로 끝내게 했다.
- 교훈
롤백 세그먼트가 커지지 않도록 트랜잭션을 작게 해야 한다. 롤백 세그먼트는 클러스터 전체가 함께 쓰므로, 한번 커지면 인스턴스를 바꿔도 해제가 끝나기를 기다리는 수밖에 없다. 롤백 세그먼트 길이는 show engine innodb status 의 "History list length" 값으로 볼 수 있다.
- 증상
WORKER_JOB_ERROR 오류가 늘었다는 신고가 들어왔다. 이 오류는 파일을 받아 Assembly 를 조율하는 Uploader 와 인코딩을 실행하는 Drone 사이의 통신에 문제가 있다는 뜻이다.
- 촉발
HLS 트래픽이 가파르게 늘었고, 같은 양을 더 빨리 처리하려고 Drone 을 더 많이 띄울 수 있게 되면서 중앙 노드가 바빠졌다. 이를 설명할 코드나 인프라 변경은 찾지 못했고, 이 두 변화가 겹쳐 Redis 병목이 드러났다.
- 원인
- 구성 요소
- 기여 요인
- 감지
WORKER_JOB_ERROR 오류가 늘었다는 신고가 들어와 문제를 알았다. 모니터링은 Redis 명령 수, 연결 수, 스왑 사용량을 보고 있었지만 대역폭은 보지 않아 포화를 잡지 못했다.
- 조치
- 잃은 메시지를 다시 넣고 하트비트 감시를 느슨하게 하는 임시 조치를 했다. 증상만 막는 조치였고 Assembly 실행 시간이 늘었다.
- 놓친 Redis 패치가 있는지 확인하고 Redis 를 최신 안정 버전으로 올렸다.
- 대역폭 제한에 걸린 것을 알고 Redis 클러스터를 두 배인 여섯 대로 늘렸다. 곧 다시 포화되자 세 대를 더 붙였지만 상황은 더 나빠졌다.
- 읽기 replica 를 하나로 줄였다. 트래픽과 실패율이 바로 떨어졌고 Assembly 가 다시 빨라졌다.
- 리전마다 Drone 확장에 상한을 두었다. 큰 배치 가져오기는 시간이 더 걸릴 수 있지만 시스템은 안정을 유지한다고 밝혔다.
- 후속 조치
- 포화 수준에 다시 가까워지면 알 수 있도록 로그와 알림을 더 둔다.
- Redis 노드와 Drone, Uploader 사이의 트래픽을 한곳에 몰리지 않게 나눌 방법을 찾는다.
- 이미 하고 있는 리전별 샤딩에 더해 Uploader 별 샤딩을 추가한다.
- 교훈
Redis 노드를 늘린 것은 잘못된 판단이었다. 모든 쓰기를 리더 한 대가 받는 구조에서는 노드가 늘수록 리더가 복제로 내보낼 트래픽이 늘어, 더 많은 트래픽을 감당하려면 노드를 오히려 줄여야 했다. 잃은 데이터를 다시 넣을 수 있으므로 팀은 복제가 꼭 필요한지 다시 따져 봤다. 지표는 이미 많이 지켜보고 있었지만 알림을 제대로 걸 수 있는 지표는 몇 개뿐이어서, 고른 지표가 모자랐을 수 있다. 대역폭도 빠져 있었다. 쓰기를 받는 Redis 노드가 하나뿐이면 replica 를 줄이거나 노드를 키워도 시간을 조금 벌 뿐이고, 성장을 버티려면 트래픽을 나눠야 한다.
이 4건에서 가장 많이 나오는 구성 요소: 데이터베이스 복제, 데이터베이스. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.