그래프
사례4건
4건 중 1~4번째
IL-0572Merpay 회계 이벤트 처리 시스템에서 Cloud Pub/Sub 메시지 1000만 건이 밀려 새 회계 데이터가 하루 넘게 Cloud Spanner에 들어가지 못했다Mercari2026- 증상
월말 마지막 영업일 아침 6시쯤부터 Cloud Pub/Sub 메시지가 밀리기 시작했고, Cloud Spanner에 새 회계 데이터를 등록하지 못하는 상태가 간헐적으로 이어졌다. 밀린 메시지는 1000만 건 규모에 이르렀다. 복구와 재발을 거듭하며 수습하기까지 하루가 넘게 걸렸다.
- 촉발
장애 한 달여 전 Cloud Functions를 1st gen에서 Cloud Run 기반 2nd gen으로 옮기면서 --max-instances 를 지정하지 않아, 스케일 상한이 1st gen 기본값인 사실상 무제한에서 2nd gen 기본값인 100으로 내려갔다. 월말 아침 부하가 쉬는 구간 없이 약 40분 이어지자 이 상한에 걸렸다.
- 원인
- 구성 요소
- 기여 요인
- 조치
- 별도 pull 구독으로 Dataflow가 Cloud Storage에 저장해 둔 데이터를 다시 넣어 데이터 손실을 피했다.
- 후속 조치
- max-instances 를 비롯한 스케일 관련 파라미터를 배포 정의에 모두 명시해 세대나 기본값이 바뀌어도 영향을 받지 않게 했다. max-instances 는 Spanner 부하를 생각해 100에서 1000까지 단계적으로 올렸다.
- 콜드 스타트를 피하려고 min-instances 를 1로 두고, 핸들러의 공유 상태가 안전한지 확인한 뒤 concurrency 를 1에서 10으로 올렸다. 이에 맞춰 cpu는 1, memory는 512MB에서 1Gi로 늘렸다.
- mercari/spanner-autoscaler를 관리하는 SRE 팀이 High priority CPU와 Total CPU를 OR 조건으로 보는 dual CPU scaling mode를 구현했다. 팀은 이 기능이 담긴 v0.8.0을 도입해 Total CPU 임계값 70%를 새로 뒀다.
- 스케일업이 더 빨리 시작되도록 High priority CPU 임계값을 60%에서 55%로 내렸다.
- 월말 피크가 시작될 때 확보한 PU가 줄지 않도록 아침 5시부터 7시까지 Spanner 스케일다운을 막는다.
- 월말 아침이나 대규모 리컨사일이 도는 달처럼 부하를 예상할 수 있는 기간에는 일정에 따라 PU를 미리 확보한다.
- Datadog에 Cloud Run 인스턴스 수가 상한의 40%와 60%에 이르면 각각 경고 단계와 심각 단계로 알리는 모니터를 더했다.
- Datadog에 Pub/Sub의 전달되지 않은 메시지 수가 임계값을 넘으면 알리는 모니터를 더했다. 오탐을 피하려고 보수적인 임계값에서 시작해 평소 상태를 알아 가며 단계적으로 낮춘다.
- 교훈
관리형 서비스의 세대를 옮길 때는 직접 바꾸지 않은 기본값이 부하가 걸릴 때 문제로 드러난다. 스케일 상한, 동시 처리 수, 타임아웃처럼 평소에는 효과가 보이지 않는 파라미터는 옮길 때마다 명시해야 한다. 장애 원인은 하나가 아닐 수 있으므로 촉발, 증폭, 실제 피해로 이어진 요인을 각각 봐야 한다. 설정 최적화와 그 한계에 가까워지는 것을 알아채는 모니터링은 늘 함께 갖춰야 하고, 물려받아 운영하는 시스템일수록 설정과 전제를 정기적으로 다시 살펴야 한다.
- 증상
글로벌 게임의 이벤트 당일, 인스턴스마다 1000 rps 가까운 부하가 걸린 가운데 master 인스턴스 한 대가 호스트 고장으로 멈췄다. MHA가 평소대로 자동 Failover를 해 서비스는 이어졌지만, 원래 있던 slave 3대 중 1대가 레플리케이션 에러를 내며 최신 데이터를 따라가지 못했다.
- 촉발
부하가 높은 이벤트 당일 master 인스턴스 한 대가 호스트 고장으로 멈췄고, MHA가 Failover 중 slave의 데이터를 최신화하면서 mysqlbinlog로 relaylog를 적용했다.
- 원인
- 구성 요소
- 기여 요인
- 조치
- 최신 데이터를 받지 못한 slave 인스턴스를 서비스에서 빼 운영 환경에 미치는 영향을 줄였다.
- 교훈
MySQL을 대규모로 쓰면 MySQL 5.7.9의 mysqlbinlog 변경을 MHA가 따라가지 못한 것처럼 드문 조건에서만 드러나는 문제도 만난다. 이번에도 운영 환경의 데이터 불일치에서 시작해 MHA와 MySQL의 소스코드, binlog 사양까지 거슬러 올라가서야 원인을 찾았다.
- 증상
2023-02-07 9:47 AM 동부 시간에 평소 부하에서 데이터베이스 성능 문제 알림이 울렸다. 알림 내용은 주말에 업그레이드한 데이터베이스의 락 경합이 높다는 것이었고, 이 때문에 통화 서버인 SFU 가 문제를 겪었다.
- 촉발
Daily 는 주말에 데이터베이스 서버를 업그레이드했고, 이 작업으로 데이터베이스가 MySQL 포인트 릴리스의 저수준 동작 변경이 들어간 버전으로 올라갔다. 월요일까지 정상이던 데이터베이스가 2월 7일 평소 부하에서 대량의 교착을 일으켰다.
- 원인
- 구성 요소
- 기여 요인
- 감지
9:47 AM 동부 시간에 평소 부하에서 데이터베이스 성능 문제 알림이 울렸고, 알림은 새로 업그레이드한 데이터베이스의 높은 락 경합을 가리켰다.
- 조치
- 10:13 에 옛 데이터베이스를 최신으로 맞추던 MySQL binlog 복제를 끄고 데이터베이스를 재시작해 부하를 줄였다. 나아졌지만 SFU 가 교착을 일으키던 쿼리를 재시도해 문제가 이어졌다.
- 10:47 에 데이터베이스가 갑자기 스스로 재시작했다. 이 재시작 덕분에 SFU 는 재시작하지 않고 오래된 meeting 업데이트를 버릴 수 있었고, 플랫폼이 정상으로 돌아왔다.
- 예방 조치로 방을 만드는 REST API 엔드포인트에 요청 제한을 걸었다. POST /rooms 의 한도를 DELETE /rooms/:name 과 같은 초당 약 2회, 30초에 50회로 맞췄다.
- MySQL 동작 변경을 피하려고 영향받은 테이블 하나의 인덱스를 고쳤다. 그 주 동안 계획을 만들어 시험했고 토요일 저녁에 사용자 영향 없이 운영 데이터베이스에 적용했다.
- 후속 조치
- 운영 환경의 Aurora MySQL 2.11.0 에서 본 교착 문제를 문서로 남기고 원인을 밝혀 다음 릴리스에서 고치도록 AWS 와 계속 협력한다.
- 시험 부하에 API 요청 패턴을 더했다.
- 더 세밀한 데이터베이스 지표를 보는 운영 모니터링 알람을 더했다.
- 교훈
Daily 는 모든 인프라 변경을 운영과 비슷한 부하로 시험하려 하지만, 이번에는 이 교착을 일으킬 만한 형태의 합성 부하로 시험하지 못했다. MySQL 5.7 에서 교착 처리가 더 보수적으로 바뀐 것은 알려진 변경이었어도, 실제로 겪은 교착의 심각도는 Daily 와 AWS Aurora 팀 모두에게 뜻밖이었다.
- 증상
2021-05-21 13:00 UTC 에 CircleCI 엔지니어가 작업 시작이 지나치게 늦어진다는 첫 호출을 받았다. Docker, Machine executor, remote Docker 작업이 늦어지거나 막혔고, 시스템이 GCP 의 CPU 쿼터에 걸려 VM 을 띄우지 못하고 있었다.
- 촉발
2021-05-20 08:37 UTC 에 RabbitMQ 를 3.8.9 에서 3.8.16 으로 올렸다. 3.8.15 에서 들어온 변경으로, 메시지를 받고 ack 하지 않는 컨슈머에 기본 15분 ack 타임아웃이 걸렸다. 변경 기록에는 quorum queue 에만 해당한다고 적혀 있었지만 실제로는 모든 큐 종류에 적용됐다.
- 원인
- 구성 요소
- 기여 요인
- 감지
02:31 UTC 에 VM destroyer 서비스 대기열 하나에 컨슈머가 없다는 알림이 왔고, 파드를 재시작해 정상으로 돌렸다. 그 뒤 03:10 에 다시 컨슈머가 빠지기 시작한 것은 알아채지 못했다. 10:11 에 VM 을 지우는 대기열이 쌓인다는 알림이 울렸다. 이 알림은 임계값에 닿을 때 한 번만 알리게 잘못 설정돼 있었고 온콜을 호출하지 않았다. 엔지니어들은 13:00 에 작업 시작 지연 호출을 받고서야 본격적으로 조사를 시작했다.
- 조치
- 14:13 에 Linux machine 작업이 작업 대기열에 아예 들어오지 못하게 손으로 막았다.
- 13:26 에 Google Cloud 에 쿼터 증설 티켓을 열었고 14:37 에 GCP 가 쿼터를 늘렸다. 시스템은 그 뒤에도 스스로 회복하지 못했다.
- 오래된 VM 을 손으로 지우는 계획을 세우고 지우기 시작했다.
- 17:22 에 자원을 비우고 멈춘 플랫폼을 다시 움직이려고 일부 워크플로를 취소했다.
- 16:25 에 VM 을 지우는 대기열에 컨슈머가 없음을 확인하고 대기열과의 연결을 되살리려고 VM 서비스 배포를 리셋했다. 대기열이 빠지기 시작했다.
- Burst Balance 가 바닥난 RDS 데이터베이스를 재부팅해도 효과가 없자 18:20 에 인스턴스를 키워 메모리와 CPU, burst balance 를 늘렸다. 데이터베이스가 돌아오는 동안 VM 프로비저닝 서비스를 줄여 연결이 몰리지 않게 했고, 19:15 에 한 번 더 키웠다.
- VM 프로비저닝 서비스를 줄이고, vm-create 대기열을 키우던 remote-docker 작업이 실행되지 않게 막아 부하를 덜었다.
- 21:00 에 새 VM 을 만들고 오래된 VM 을 지우는 파드를 모두 줄여 VM 을 만들고 지우지 못하는 순환을 끊었다.
- 21:57 에 remote-docker 작업을 프로비저닝 대기열에 넣지 않는 새 분배 백엔드를 배포했고, 22:21 에 프로비저닝 시스템을 줄여 대기열이 빠질 여유를 만들었다.
- 22:36 부터 두 시간 동안 프로비저닝과 분배 시스템의 구성 요소를 하나씩 안정성을 확인하며 다시 올렸고, 00:39 에 모두 돌아오자 완화용 코드 변경을 되돌렸다.
- 후속 조치
- VM 프로비저닝이 부하 변화에 더 잘 버티고 thundering herd 에서 회복하도록 고친다.
- VM 프로비저닝을 분리해 그 실패가 Docker 작업에 영향을 주지 않게 한다.
- RabbitMQ 와 운영 대기열들의 관측성을 점검하고 보강한다.
- 요청을 묶어 보내 GCP API 요청 한도에 걸리지 않게 한다.
- 오래 이어지는 장애에 맞게 장애 대응 방식을 보강한다.
이 4건에서 가장 많이 나오는 구성 요소: 데이터베이스, 메시지 브로커. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.
원인별1
업그레이드로 깨진 호환성4건
IL-0572Merpay 회계 이벤트 처리 시스템에서 Cloud Pub/Sub 메시지 1000만 건이 밀려 새 회계 데이터가 하루 넘게 Cloud Spanner에 들어가지 못했다Mercari2026IL-0569MySQL master 장애 때 MHA 자동 Failover 뒤 slave 한 대가 relaylog를 적용하지 못해 레플리케이션이 멈췄다DeNA2026IL-0314주말에 업그레이드한 Aurora MySQL 데이터베이스에서 교착이 쌓여 통화 서버가 재시작되고 통화가 다른 서버로 옮겨졌다Daily2023IL-0294CircleCI 의 VM 정리 대기열에서 컨슈머가 사라져 Docker 와 machine 작업이 12시간 가까이 늦어지거나 막혔다CircleCI2021