Incident Library
  • 원인
  • 구성 요소
  • 증상
  • 기여 요인
  • 사례

사례8건

8건 중 1~5번째

  1. 증상

    2026년 10월 6일 13시 30분 UTC부터 CircleCI 의 워크플로 조율 서비스가 느려져 일부 파이프라인과 잡이 이따금 조금씩 늦게 시작했다. 15시 30분부터는 지연이 계속 이어졌고 일부 잡이 실패하기 시작했다.

    촉발

    10월 6일 12시 40분쯤 데이터베이스의 가장 큰 테이블 몇 개에서 돌던 정기 유지 보수 작업인 anti-wraparound autovacuum 이 평소 작업량과 겹치면서, 데이터베이스가 트랜잭션 로그를 보관 처리하는 속도보다 빠르게 로그를 썼다.

    원인
    구성 요소
    기여 요인
    감지

    10시 2분부터 모니터링이 조율 서비스의 오류 알림을 짧게 여러 번 냈지만 매번 저절로 풀렸다. 13시 35분에 여러 다른 서비스의 관련 알림과 함께 다시 울렸고, 14시 30분쯤 알림이 다시 울리자 더 조사한 뒤 14시 54분에 장애를 선언했다. 트랜잭션 로그 볼륨이 얼마나 찼는지와 보관 처리가 얼마나 밀렸는지를 보는 알림은 없었다. 상태 페이지에는 15시 58분에 공지를 올렸고 16시 20분에 주요 장애로 올렸다.

    조치
    • anti-wraparound autovacuum 이 빨리 끝나도록 설정을 바꿨다. 이 작업은 취소하면 데이터베이스가 자동으로 다시 시작하기 때문이었다.
    • 트랜잭션 로그 볼륨이 거의 차자 데이터베이스가 읽기 전용이 되지 않도록 로그를 여유 공간이 많은 데이터베이스의 주 저장 볼륨으로 옮겼다. 옮기는 동안 데이터베이스가 50분 동안 내려갔다.
    • 유지 보수 작업이 더 시작되지 않도록 데이터베이스 파라미터 몇 가지를 조사해 바꿨다.
    • 18시 19분에 쓰기마다 저장소를 기다리는 시간을 줄이는 데이터베이스 설정을 바꿔 처리 속도를 되살렸다.
    • 밀린 작업을 빨리 처리하려고 잡을 실행 플릿에 넘기는 시스템에 데이터베이스와 서버 용량을 더했다.
    후속 조치
    • 트랜잭션 로그 볼륨이 얼마나 찼는지와 보관 처리가 얼마나 밀렸는지에 알림을 건다.
    • 이 두 상태를 일으키는 데이터베이스 유지 보수 작업에도 알림을 걸어 더 일찍 대응한다.
    • 시끄럽거나 지나치게 민감한 알림이 실제 문제를 가리지 않도록 모든 알림을 다시 살핀다.
    • 데이터베이스의 autovacuum 이 얼마나 자주, 얼마나 공격적으로 도는지를 조정한다.
    • 큰 테이블들의 크기를 시간에 따라 추적해 안전한 한계 안에 두게 한다.
    • 트랜잭션 로그 하나에 모든 쓰기가 몰리는 병목을 없앤다. 서비스를 각자 트랜잭션 로그를 가진 여러 데이터베이스 인스턴스로 나누는 방법과, 쓰기를 여러 노드에 나누는 분산 데이터베이스로 옮기는 방법을 검토한다.
    • 다른 시스템들이 재시도 끝에 포기하지 않고 조율 서비스가 회복할 때까지 기다리도록 동작을 바꾼다.
    • 긴 장애 동안 상태 페이지 공지가 구체적인 영향과 시각을 더 일찍 담도록 지침을 고친다.
    교훈

    CircleCI 는 여러 알림이 함께 울린 것을 더 일찍 알아챘어야 했다고 밝혔다. 모니터링은 느려진 것을 잡았지만 트랜잭션 로그 볼륨이 찬 정도와 보관 처리가 밀린 정도에는 알림이 없었다. 조율 서비스의 모든 쓰기가 데이터베이스 하나와 트랜잭션 로그 하나를 거치기 때문에, 그 로그가 밀리자 모든 파이프라인, 워크플로, 잡이 함께 느려졌다. 일부 잡은 다른 시스템들이 재시도 끝에 포기해서 실패했다. 고객들은 초기 상태 페이지 공지에 세부 내용이 부족했다고 알려 왔다.

  2. 증상

    13:30 UTC 에 ZooKeeperWait 지표가 갑자기 오른다는 알림이 왔다. 이 클러스터의 알림 기준은 낮은 쪽 10초, 높은 쪽 20초인데 값은 수천 초였다. 값은 대칭으로 이중화된 인스턴스 세 곳에서 똑같이 올랐다.

    촉발

    몇 달 동안 네트워크에서 떨어져 있던 클라이언트 머신 두 대가 다시 연결되면서, 그동안 쌓인 몇 달 치 헬스 체크 데이터를 아주 작은 배치로 빠르게 보냈다.

    원인
    구성 요소
    기여 요인
    감지

    13:30 UTC 에 팀은 ZooKeeperWait 지표가 갑자기 오른다는 알림을 받았다. 이 클러스터 크기에 맞춘 알림 기준은 낮은 쪽 10초, 높은 쪽 20초였다.

    조치
    • 쌓인 파트를 끝내 정리하지 못한 5분 단위 파티션 테이블을 장애 뒤 DROP-CREATE 로 다시 만들어 정상으로 되돌렸다.
    • 그 테이블의 파티션 단위를 분에서 시간으로 넓혔다.
    후속 조치
    • 루트 MaterializedView 테이블에서 범위를 벗어난 타임스탬프를 거부하도록 구현했다.
    • 두 번째 MaterializedView 가 거부된 데이터의 통계를 기록한다.
    • 거부 범위는 과거 데이터 백필을 위해 일부러 넓게 잡았고, 거부되는 데이터를 모아 가며 범위를 다듬는다.
    • 타임스탬프가 며칠이나 몇 달에 걸친 insert 쿼리 하나로 이번 상황을 재현하는 최소 시험 시나리오를 만들었다.
    • 관측 기능을 여러 가지 개선한다.
    교훈

    이 파이프라인은 주로 데이터 양을 다루지만, 어긋난 타임스탬프도 카디널리티 변화만큼 파이프라인을 흔들 수 있었다. 이상한 지표를 바로 설명하지 못했다고 치워 두면 안 된다. 이번에도 원인으로 이끈 것은 처음에 무시한 insert 크기 감소였다. 중앙값과 평균은 각자 쓸모가 있고, 이번에는 평균이 실마리였다. 파티션이 너무 적으면 파트가 커지고 mutation 이 느려지며 TTL 이 너무 비싸지거나 아예 동작하지 않는다. 반대로 너무 많으면 열 스캔과 집계 쿼리가 느려지고 Keeper 가 과부하된다. Keeper 작업은 파트 수에 따라 선형보다 훨씬 빠르게 늘었다.

  3. 증상

    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 테이블로 옮겼다. 엔지니어가 직접 정기적으로 상태를 알렸다.

  4. 증상

    RDS 인스턴스의 BurstBalance 가 갑자기 빠르게 줄기 시작해 끝내 바닥났고, 데이터베이스 성능이 크게 떨어졌다. 인스턴스는 MySQL 5.7.44, db.t3.medium, 범용 SSD gp2 30GiB 였다.

    촉발

    복잡한 SELECT 문이 어느 시점부터 갑자기 임시 테이블에 대량으로 쓰기 시작해 WriteIOPS 가 늘었다. 그렇게 바뀐 이유는 아직 조사 중이다.

    원인
    구성 요소
    기여 요인
    후속 조치
    • 문제 쿼리를 튜닝하는 것을 검토한다. 인덱스를 다시 보거나, 서브쿼리를 없애고 JOIN 을 최적화하는 식으로 쿼리를 다시 쓰는 방안이다.
    • gp2 볼륨을 성능 특성을 더 예측하기 쉬운 gp3 로 옮기거나, 스토리지를 늘려 기준 IOPS 를 높이는 것을 검토한다.
    • 임시 테이블의 크기 한도를 정하는 tmp_table_size 와 max_heap_table_size 파라미터를 조정하는 것을 검토한다.
    • 더 성능이 높은 인스턴스 타입으로 옮기는 것을 검토한다.
    • CloudWatch 알림 같은 수단으로 BurstBalance 를 감시하고, Pingdom 같은 외부 모니터링을 두는 것을 검토한다.
    교훈

    RDS 에서 BurstBalance 가 바닥나면 예상하지 못한 성능 저하가 올 수 있다. 복잡한 쿼리는 I/O 에 큰 영향을 주므로, 데이터베이스 설계와 쿼리 최적화를 계속 고쳐 나가고 성능을 정기적으로 감시해야 한다.

  5. 증상

    2024년 2월 22일 07:22 UTC 부터 Bitbucket Cloud 의 웹사이트와 API 가 느려졌다. 커넥션 풀이 포화되고 응답 시간이 늘었으며, 완전히 타임아웃 나는 요청이 점점 늘었다.

    원인
    구성 요소
    기여 요인
    조치
    • Bitbucket Pipelines 에 리소스를 더 넣어 쌓인 잡을 처리했고, 17:30 UTC 에 백로그가 모두 처리됐다.
    후속 조치
    • 쓰기가 많은 데이터베이스 테이블의 vacuum 임계값을 다시 설정한다.
    • 이런 동작을 더 일찍 잡아 영향을 줄이도록 알림 임계값을 조정한다.
    • Pipelines 서비스의 오토스케일링과 로드 셰딩 동작을 조정하고 빌드 러너 용량을 늘린다.
내 클러스터에도 있는지 확인하기

이 8건에서 가장 많이 나오는 구성 요소: 데이터베이스, PostgreSQL vacuum. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.

원인별1

용량 한계8건

  1. IL-0553 워크플로 조율 서비스의 데이터베이스에서 트랜잭션 로그 볼륨이 차서 CircleCI 파이프라인과 잡이 멈추고 몇 시간 동안 늦게 시작했다
  2. IL-0288 CDN77 의 ClickHouse 데이터 파이프라인에서 이중화된 인스턴스 세 곳의 ZooKeeperWait 가 수천 초로 치솟아 복제가 한 시간 넘게 느려졌다
    CDN772026
  3. IL-0390 PostHog US Cloud 의 Persons Postgres 데이터베이스 쓰기가 크게 느려져 이벤트와 persons 수집이 최대 2일 지연됐다
  4. IL-0447 RDS MySQL 인스턴스의 EBS BurstBalance 가 바닥나 IOPS 가 기준 성능으로 묶이고 데이터베이스 성능이 크게 떨어졌다
    every2024
  5. IL-0550 Bitbucket Cloud 의 웹사이트와 API 가 6시간 동안 느려지고 Pipelines 빌드가 밀렸다
  6. IL-0443 Aurora MySQL reader 가 이유 없이 재시작한 뒤 writer 의 insert latency 가 7배쯤 오르고 replication lag 가 하루 넘게 이어졌다
    Repro2019
  7. IL-0297 Mezmo 의 인증 캐시 Redis 서버가 OOM 으로 죽고 다시 뜨지 못해 로그인이 막히고 로그 색인이 늦어졌다
    Mezmo2019
  8. IL-0211 Mandrill 의 PostgreSQL 샤드 하나가 트랜잭션 ID 랩어라운드를 막으려고 쓰기를 멈춰 약 40시간 동안 메일 발송이 줄었다