그래프
사례5건
5건 중 1~5번째
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의 전달되지 않은 메시지 수가 임계값을 넘으면 알리는 모니터를 더했다. 오탐을 피하려고 보수적인 임계값에서 시작해 평소 상태를 알아 가며 단계적으로 낮춘다.
- 교훈
관리형 서비스의 세대를 옮길 때는 직접 바꾸지 않은 기본값이 부하가 걸릴 때 문제로 드러난다. 스케일 상한, 동시 처리 수, 타임아웃처럼 평소에는 효과가 보이지 않는 파라미터는 옮길 때마다 명시해야 한다. 장애 원인은 하나가 아닐 수 있으므로 촉발, 증폭, 실제 피해로 이어진 요인을 각각 봐야 한다. 설정 최적화와 그 한계에 가까워지는 것을 알아채는 모니터링은 늘 함께 갖춰야 하고, 물려받아 운영하는 시스템일수록 설정과 전제를 정기적으로 다시 살펴야 한다.
IL-0390PostHog US Cloud 의 Persons Postgres 데이터베이스 쓰기가 크게 느려져 이벤트와 persons 수집이 최대 2일 지연됐다PostHog2025- 증상
2025년 11월 11일 16:02 UTC 부터 PostHog 수집 처리 파이프라인의 성능이 크게 떨어져, US 리전 모든 고객의 이벤트 처리가 지연되기 시작했다. 고객이 최근에 보낸 이벤트가 PostHog 에 보이지 않았다.
- 촉발
Persons 테이블의 properties 열은 자주 2KB 를 넘어 TOAST 테이블에 따로 저장되는데, 이 값마다 할당하는 32비트 OID 공간이 거의 다 찼다. 그러자 쓰기 한 건마다 비어 있는 OID 를 찾느라 이미 쓴 OID 를 길게 훑어야 했다.
- 원인
- 구성 요소
- 기여 요인
- 조치
- 새 TOAST 테이블과 새 OID 공간을 갖는 파티션 Persons 테이블 구조를 새로 만들었다.
- 실시간 쓰기가 옛 테이블과 새 테이블에 함께 맞춰지도록 데이터베이스 트리거를 넣었다.
- 백필 스크립트로 기존 Person 데이터를 옛 테이블에서 새 테이블로 복사했다.
- 새 쓰기는 모두 새 테이블로 가고, 옮기는 동안 읽기는 새 테이블을 먼저 본 뒤 옛 테이블로 넘어가도록 수집과 애플리케이션 로직을 바꿨다.
- 장애 중 새 문제를 만들 위험이 있어, 웹 앱은 완전 자동 롤아웃 대신 사람이 통제하는 배포로 운영에 내보냈다. 엔지니어 여럿이 주말 내내 교대로 Feature flags API, Error tracking 수집, Django 웹 애플리케이션을 고쳤다.
- 새 Persons 테이블에서 수집 성능이 돌아온 뒤, 파티션별 지연, 처리량, 자원 사용률을 지켜보며 수집 워커를 늘려 밀린 이벤트를 처리했다.
- MSK 로컬 디스크 사용률이 약 85% 에 닿자 수집을 잠시 멈췄다.
- 해당 Kafka 토픽의 로컬 보존 기간을 줄여, S3 로 넘기기 전에 디스크에 두는 데이터를 줄였다.
- 디스크 여유가 충분한 것을 확인한 뒤 수집을 다시 시작했다.
- 오래 걸리는 백필 작업을 더 잘 지켜보고 안정적으로 돌리려고 백필 과정을 Dagster 로 옮겼고, 남은 백필과 정리 작업을 주말 동안 Dagster 로 끝냈다.
- 후속 조치
- 쓰기마다 디스크 읽기가 크게 늘어나는 현상에 지표와 알림을 더한다.
- TOAST 테이블 통계에 지표와 알림을 더한다.
- 큰 규모에서 문제가 될 수 있는 다른 Postgres 엔진 한계에도 지표와 알림을 더한다.
- 비슷한 Postgres 엔진 수준 문제의 증상과 진단 방법을 런북으로 정리하고, 옮길지 제자리에서 고칠지 정하는 의사 결정 트리를 분명하게 넣는다.
- 고객에게 언제 어떻게 알릴지, 누구에게 에스컬레이션할지, 누가 대신 맡을지를 분명히 정한 고객 소통 런북을 새로 만든다.
- persons 데이터베이스에 다른 데이터 저장소를 쓰는 방안을 계속 검토한다.
- 새 테이블로 통합하는 작업을 마무리한다.
- 백필 도구와 Kafka tiered storage 의 안전장치를 개선한다.
- Person 과 비슷한 테이블을 처음부터 비슷한 한계에 닿지 않게 설계하고 운영한다.
- 교훈
Persons 테이블 하나에 analytics, feature flag, replay 필터, CDP 같은 핵심 기능 다수가 기대고 있어, 이 테이블이 느려지자 제품의 넓은 부분이 영향을 받았다. TOAST 증가, OID 사용량, 쓰기당 디스크 읽기 증폭을 보는 모니터링이 없어 OID 고갈을 원인으로 확정하는 데 하루 반쯤 걸렸다. 처음의 백필 방식은 길고 큰 마이그레이션에 필요한 가시성과 견고함이 모자라 장애 중에 Dagster 로 옮겨야 했다. MSK 디스크가 차오른 일로 tiered storage 설정과 알림이 큰 백로그 상황에 맞춰져 있지 않았다는 것이 드러났다. 평소 고객 소통을 맡는 팀원이 장애 내내 모두 자리에 없어 대신할 사람을 급히 찾아야 했다. PostHog 는 잘된 점으로 네 가지를 꼽았다. 데이터를 잃지 않았다. 여러 팀과 외부 컨설턴트, AWS 엔지니어가 함께 드문 엔진 수준 문제를 진단했다. 시스템을 살려 둔 채 트리거와 백필로 새 Persons 테이블로 옮겼다. 엔지니어가 직접 정기적으로 상태를 알렸다.
- 증상
2025년 8월 28일 03:53 UTC 에 PagerDuty 의 Kafka 에서 장애가 시작됐다. 처음 온 알림은 Kafka 브로커 하나의 고장을 가리켰지만, 곧 다른 브로커들도 메모리가 바닥났다. 미국 서비스 리전의 일부 고객은 새 이벤트가 처리되지 않거나 늦게 처리됐다.
- 촉발
API 키 사용 내역을 Kafka 토픽에 남기는 새 기능의 논리 오류로 API 요청마다 새 Kafka 프로듀서가 만들어졌다. 이 기능은 8월 21일 1% 에서 시작해 27일 5%, 같은 날 저녁 25%, 28일 75% 로 롤아웃됐다.
- 원인
- 구성 요소
- 기여 요인
- 감지
03:53 UTC 에 장애가 시작되자 처음 온 알림은 Kafka 브로커 하나의 고장을 가리켰다. 두 번째 장애는 16:38 UTC 에 Kafka 성능이 다시 떨어지며 울린 알림으로 알았다. 핵심 API 오류를 알리는 중요한 알림은 웹훅 호출에 묻혔다.
- 조치
- 처음 알림이 브로커 하나의 고장을 가리켜 하드웨어 문제를 의심했고, 클러스터를 늘리고 그 브로커를 뺐다.
- 원인을 조사할 여유를 얻으려고 Kafka 힙 크기를 두 배로 늘렸고, 이를 적용하려고 클러스터 전체를 롤링 재시작해 Kafka 를 안정시켰다.
- 상태 페이지 자동 게시가 되지 않자 엔지니어링 팀을 더 부르고 백업 절차를 시작해 상태 페이지에 손으로 공지를 올렸다.
- Kafka 가 돌아온 뒤 여러 애플리케이션을 손으로 복구했고, ksqlDB 스트림 관리 중 생긴 데이터 손실은 스크립트로 백필했다.
- 두 번째 장애 때 당번 대응자가 힙 크기를 다시 두 배로 늘리고 롤링 재시작했다.
- API 사용 기능의 롤아웃과 힙 증가 사이의 강한 상관관계를 찾아, 이 기능이 Kafka 메시지를 더는 보내지 않게 하는 풀 리퀘스트로 기능을 되돌렸다.
- 후속 조치
- 상태 페이지 자동 게시를 막은 의존을 없앴고, 손으로 공지하는 런북을 단순하게 고쳐 다시 냈다.
- 플랫폼 일부가 망가져도 상태 공지가 빨리 나가도록 실전 연습을 평소 업무에 더 꾸준히 넣는다.
- 힙, 가비지 컬렉션, 프로듀서와 컨슈머 상태 같은 JVM 과 Kafka 수준의 모니터링을 넓혀 가용성에 영향이 가기 전에 부하 신호를 드러낸다.
- 서비스 의존 관계 지도를 보강해 대응 중에 연쇄 장애를 더 쉽게 따라가게 한다.
- 고객 영향 지표 수집을 인시던트 작업 흐름에 자동으로 넣어 대응자가 영향 범위를 늘 볼 수 있게 한다.
- 큰 롤아웃에 준비 점검표와 더 느린 증가 기간 같은 변경 관리 장치를 더 엄격하게 두고, 큰 장애 직후에는 특히 그렇게 한다.
- 스트리밍 시스템의 복구 방법을 고쳐 장애가 길어질 가능성을 줄인다.
- 상태 페이지 공지, 내부와 외부 동기화, 알림 같은 소통 작업을 자동화해 혼선을 줄이고 이해관계자가 같은 정보를 보게 한다.
- 상태 페이지 장애 조치와 PD-on-PD 절차 같은 큰 장애 대응 흐름을 카오스 엔지니어링으로 매달 시험해 자동화에 덜 기댄다.
- 인시던트 심각도 등급과 전담 소통 담당을 포함한 역할 정의를 더 분명히 해 혼란을 줄이고 대응을 빠르게 한다.
- 교훈
PagerDuty 는 연쇄 장애가 본래 예측하기 어렵고, 한 서비스의 작은 문제가 시스템 도표로는 보이지 않는 길로 다른 서비스에 번진다고 봤다. 관측성의 빈틈 때문에 대응자는 하위 시스템 여러 개가 망가질 때까지 처음 무너진 것을 보지 못했다. 사람은 의존 관계를 직선으로 생각하지만 운영 시스템은 그렇게 움직이지 않는다. 통화에 참여한 누구도 시스템 전체를 머릿속에 담고 있지 않아 의존 관계를 잇는 데 시간이 걸렸다. 새 기능은 안전하게 내려고 별도 배포 대신 설정으로 조금씩 켰는데, 이 때문에 장애와 변경을 바로 잇기 어려웠다. 이 기능은 잘 쓰지 않는 프레임워크와 라이브러리로 만들어서, 요청마다 프로듀서를 새로 만든다는 것이 코드에 드러나지 않았다. 여기에 Kafka 알림이 적었던 것이 겹쳐 점진적 롤아웃 절차가 있어도 장애를 막지 못했다. 중요한 알림이 우선순위 낮은 웹훅 알림에 묻혔고, 백업 절차로 상태 페이지에 공지하는 일처럼 일부 운영 절차는 더 자주 연습해야 했다. 미리 만들어 둔 백필 스크립트와, 처리를 일시 정지했다가 재개하는 런북은 완벽하지 않았지만 대응자에게 출발점을 줬다.
IL-0280New Relic US 리전의 여러 NRDB 셀에서 Kafka 브로커가 디스크 부족으로 잇따라 멈춰 고객이 몇 시간 동안 데이터 수집과 알림을 쓸 수 없었다New Relic2021- 증상
한 셀의 Kafka 브로커가 응답하지 않았다. 몇 시간 뒤 여러 셀의 Kafka 브로커 디스크가 차면서 브로커가 하나둘 멈췄고, US 리전의 많은 고객이 데이터 수집과 알림을 쓸 수 없었다.
- 촉발
엔지니어가 응답하지 않는 Kafka 브로커를 수동으로 재시작했는데, 같은 시각 자동 복구도 돌아 클러스터가 오래 성능 저하 상태에 머물렀다. 엔지니어는 밀린 데이터를 지키려고 장애 대응 도구로 Kafka 데이터 보존 기간을 크게 늘렸고, 이 변경이 문제가 난 셀뿐 아니라 모든 셀에 적용됐다.
- 원인
- 구성 요소
- 기여 요인
- 감지
7월 29일 아침 엔지니어링 팀이 한 셀의 Kafka 브로커가 응답하지 않는 것을 봤다. 나중에 디스크 여유 공간이 줄어들 때 모니터링 시스템이 알림을 보냈지만, 같은 시각 다른 여러 시스템이 관계없는 경고를 내고 있어 엔지니어들은 이 알림을 놓쳤다.
- 조치
- 엔지니어링 팀이 응답하지 않는 Kafka 브로커를 수동으로 재시작했다. 같은 시각 자동 복구도 돌았고, 두 작업 모두 결국 무사히 끝났다.
- 브로커의 디스크 공간 문제를 해결했다. 그 뒤에도 Kafka 문제가 여러 셀에 넓게 퍼져 있어 서비스 복구에 시간이 걸렸다.
- 교훈
셀 격리는 넓은 장애를 막는 가장 강한 보호 수단이다. 평소 운영뿐 아니라 긴급 도구도 이 격리를 지켜야 한다. 긴급 대응 도구는 혼란스러운 상황에서도 안전하게 쓸 수 있어야 하고, 그러면서도 필요한 기능은 빠짐없이 갖춰야 한다. 사람의 주의력은 한정되어 있으므로 장애 대응 절차와 알림을 계속 다시 따져 엔지니어의 주의가 가장 급한 신호로 가게 해야 한다.
- 증상
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 요청 한도에 걸리지 않게 한다.
- 오래 이어지는 장애에 맞게 장애 대응 방식을 보강한다.
이 5건에서 가장 많이 나오는 구성 요소: 메시지 브로커, 데이터베이스. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.