IL-0288 CDN77 · 2026-03-09databaseobservability
CDN77 의 ClickHouse 데이터 파이프라인에서 이중화된 인스턴스 세 곳의 ZooKeeperWait 가 수천 초로 치솟아 복제가 한 시간 넘게 느려졌다
2026년 3월 9일 13:30 UTC 에 CDN77 의 큰 ClickHouse 데이터 파이프라인에서 ZooKeeperWait 지표가 이중화된 인스턴스 세 곳에서 동시에 수천 초로 치솟았다. 팀은 먼저 그때 시작된 매일 도는 data diff 작업의 무거운 읽기를 의심했지만, diff 쿼리가 다시 가벼워진 뒤에도 값이 높고 CPU, RAM, 쿼리 수가 정상이어서 가설을 버렸다. system.zookeeper_log 를 기본값대로 꺼 두어 Keeper 트래픽을 직접 볼 수 없었다. 그 뒤 insert 쿼리의 평균 크기가 줄고 TTL 병합이 크게 늘어난 것을 찾았다. Grafana 패널이 중앙값이 아닌 평균을 보여 준 덕에 무언가가 쓰기 크기를 끌어내리고 있음을 알 수 있었다.
서로 다른 곳에서 대응하던 엔지니어 두 명이 각자 같은 결론에 닿았다. 13:15 UTC 부터 일부 insert 가 아주 긴 시간 범위에 걸쳐 있었고, 시간 단위로 나뉜 MergeTree 파티션 키 때문에 지나치게 많은 파트로 잘렸다. 원인은 평균을 거의 반으로 끌어내린 클라이언트 머신 두 대였다. 이 머신들은 몇 달 동안 네트워크에서 떨어져 있었지만 전송기 프로세스는 계속 돌았다. 머신 자체의 헬스 체크 데이터는 네트워크 없이도 일정한 간격으로 쌓였고, 전송기는 보낼 때가 아니라 기록할 때 배치를 만들었으므로 작은 배치들이 큐를 채웠다. 네트워크가 돌아오자 몇 달 치 데이터가 빠르게 들어왔다. Buffer 테이블은 이 배치를 다른 트래픽과 합쳤지만 합친 데이터가 긴 기간에 걸쳐 파티션마다 쪼개졌다. 5분 단위로 나뉜 테이블은 과거 하루마다 복제 파트 288개를 만들었다. 기본값 2 인 max_number_of_merges_with_ttl_in_pool 때문에 파트가 빨리 정리되지 않았다. 파트가 들어오고 복제되고 바로 삭제 예약되면서 Keeper 트래픽이 몇 배로 늘었고, 복제가 느려졌다. 지연 모니터링 테이블은 남아 있던 필터 때문에 CDN layer 0 머신의 데이터만 기록했고, 그보다 높은 layer 에 있던 이 두 머신의 지연은 잡지 못했다.
대부분의 테이블은 결국 쌓인 파트를 정리했지만 5분 단위로 파티션을 나눈 테이블 하나는 그러지 못했다. 장애 뒤 이 테이블을 DROP-CREATE 로 다시 만들고 파티션 단위를 분에서 시간으로 넓혔다. 내부 사용자, 고객, 파트너에게 보이는 영향은 없었다.
- 심각도
- –
- 영향 범위
- One large ClickHouse data pipeline was degraded for over an hour, with ZooKeeper traffic multiplied and replication slowed on three redundant instances; no observable impact on internal users, customers or partners
- 영향 사용자
- none observed
- 지역
- –
- 감지까지
- 15m
- 복구까지
- –
증상
13:30 UTC 에 ZooKeeperWait 지표가 갑자기 오른다는 알림이 왔다. 이 클러스터의 알림 기준은 낮은 쪽 10초, 높은 쪽 20초인데 값은 수천 초였다. 값은 대칭으로 이중화된 인스턴스 세 곳에서 똑같이 올랐다.
팀은 처음에 무거운 읽기 쿼리가 쓰기를 막는다고 의심했다. ZooKeeperWaitMicroseconds 가 오르기 시작한 때와 거의 같은 때 매일 도는 data diff 작업이 시작됐기 때문이다. 몇 분 뒤 diff 쿼리가 가벼워졌는데도 ZooKeeperWait 는 높게 남았고, CPU, RAM, 실행 중인 쿼리 수도 정상이어서 이 가설을 버렸다.
Keeper 트래픽을 직접 볼 수 있는 system.zookeeper_log 는 ClickHouse 기본값대로 꺼 두었기 때문에 팀은 Keeper 부하를 간접 증거로 짐작해야 했다. 세 인스턴스는 서로 다른 데이터센터에 있어 한꺼번에 문제가 생길 것 같지 않았다.
장애가 시작되고 약 20분 뒤, system.query_log 에서 본 insert 쿼리의 평균 크기가 줄고 있었다. 로그 전송기는 평소대로 중앙값 약 70,000 행/초를 보내는데 ClickHouse 는 40,000 행/초 대의 평균을 보고했다. 팀은 이를 바로 설명하지 못해 Keeper 부하의 부수 효과로 치워 두었다.
system.part_log 에서는 병합 이유가 TTLDeleteMerge 인 TTL 병합이 크게 늘었고, ClickHouse 오류 로그에는 "Not executing log entry because 2 merges with TTL already executing." 이 되풀이됐다. 팀은 대부분의 테이블에 켜 둔 ttl_only_drop_parts 가 어떤 이유로 꺼진 것은 아닌지 의심했다.
system.part_log 에서 만들어진 파트 수는 크게 늘었는데 전체 행 수는 거의 그대로였고, 파티션 이름에는 넉 달 전 타임스탬프까지 보였다. 흔히 겪는 "too many parts" 오류는 나지 않았다. 설정한 한도에 닿지 않았기 때문이다.
원인
- 촉발
- 몇 달 동안 네트워크에서 떨어져 있던 클라이언트 머신 두 대가 다시 연결되면서, 그동안 쌓인 몇 달 치 헬스 체크 데이터를 아주 작은 배치로 빠르게 보냈다.
감지
13:30 UTC 에 팀은 ZooKeeperWait 지표가 갑자기 오른다는 알림을 받았다. 이 클러스터 크기에 맞춘 알림 기준은 낮은 쪽 10초, 높은 쪽 20초였다.
조치
- 쌓인 파트를 끝내 정리하지 못한 5분 단위 파티션 테이블을 장애 뒤 DROP-CREATE 로 다시 만들어 정상으로 되돌렸다.
- 그 테이블의 파티션 단위를 분에서 시간으로 넓혔다.
후속 조치
- 루트 MaterializedView 테이블에서 범위를 벗어난 타임스탬프를 거부하도록 구현했다.
- 두 번째 MaterializedView 가 거부된 데이터의 통계를 기록한다.
- 거부 범위는 과거 데이터 백필을 위해 일부러 넓게 잡았고, 거부되는 데이터를 모아 가며 범위를 다듬는다.
- 타임스탬프가 며칠이나 몇 달에 걸친 insert 쿼리 하나로 이번 상황을 재현하는 최소 시험 시나리오를 만들었다.
- 관측 기능을 여러 가지 개선한다.
교훈
이 파이프라인은 주로 데이터 양을 다루지만, 어긋난 타임스탬프도 카디널리티 변화만큼 파이프라인을 흔들 수 있었다. 이상한 지표를 바로 설명하지 못했다고 치워 두면 안 된다. 이번에도 원인으로 이끈 것은 처음에 무시한 insert 크기 감소였다. 중앙값과 평균은 각자 쓸모가 있고, 이번에는 평균이 실마리였다. 파티션이 너무 적으면 파트가 커지고 mutation 이 느려지며 TTL 이 너무 비싸지거나 아예 동작하지 않는다. 반대로 너무 많으면 열 스캔과 집계 쿼리가 느려지고 Keeper 가 과부하된다. Keeper 작업은 파트 수에 따라 선형보다 훨씬 빠르게 늘었다.
출처
참고 문서
관련 사례
같은 원인 · 공통 데이터베이스, 데이터베이스 복제
IL-0305Intercom 의 PlanetScale 샤드 하나에서 복제본이 CPU 100% 로 주 데이터베이스를 따라가지 못해 받은편지함에 최대 2.2시간 전의 데이터가 보였다Intercom · 2026같은 원인 · 공통 데이터베이스, 데이터베이스 복제
IL-0110Grafana Agent 파드가 메모리를 많이 쓰던 노드에 Hangfire 파드가 함께 올라가 시스템 OOM 으로 CrashLoopBackOff 를 반복했고, 노드가 응답을 멈추고 NotReady 가 됐다.DFDS · 2024같은 원인 · 공통 데이터베이스, 텔레메트리 에이전트
IL-0443Aurora MySQL reader 가 이유 없이 재시작한 뒤 writer 의 insert latency 가 7배쯤 오르고 replication lag 가 하루 넘게 이어졌다Repro · 2019같은 원인 · 공통 데이터베이스, 데이터베이스 복제
IL-0334RDS MySQL 의 bookmarks 테이블이 2TB 파일 크기 한도에 닿아 INSERT 가 실패하고 Instapaper 가 31시간 동안 멈췄다Instapaper · 2017같은 원인 · 공통 데이터베이스, 데이터베이스 복제
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0390PostHog US Cloud 의 Persons Postgres 데이터베이스 쓰기가 크게 느려져 이벤트와 persons 수집이 최대 2일 지연됐다PostHog · 2025같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0287Atlas 와 Cloud Manager 의 모니터링을 받치는 내부 데이터베이스 클러스터의 샤드 하나가 과부하되어 지표 수집과 클러스터 작업이 늦어졌다MongoDB · 2025같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0298Wikimedia sessionstore 의 Cassandra 노드가 디스크가 가득 차 잇따라 죽고 쿼럼을 잃어 편집이 실패했다Wikimedia Foundation · 2025같은 원인 · 공통 데이터베이스
IL-0312max_connections 를 올리려고 재시작한 주 PostgreSQL 데이터베이스가 다시 올라오지 않아 Gadget 의 모든 앱 요청이 멈췄다Gadget · 2024같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0042OpenSearch 디스크가 가득 찬 동안 fluent-bit 가 로그를 처리하지 못해 Elasticsearch 와 OpenSearch 에 애플리케이션 로그가 들어오지 않았다.UK Ministry of Justice · 2024같은 원인 · 공통 텔레메트리 에이전트
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0202갑자기 몰린 쿼리와 데이터베이스 쓰기로 Honeycomb 수집 호스트가 메모리 부족으로 죽었고, 쿠버네티스 CrashLoopBackOff 가 용량 회복을 막아 US1 이벤트 수집이 한 시간 넘게 불안정했다Honeycomb · 2023 · sev1같은 원인 · 공통 데이터베이스
IL-0386Google Cloud 로 옮긴 뒤 GKE 노드에서 Postgres 연결 타임아웃과 memcached i/o timeout 이 간헐적으로 튀었다incident.io · 2023같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 텔레메트리 에이전트
같은 원인 · 공통 데이터베이스
IL-0194kube-apiserver 재시작 뒤 Vector DaemonSet 의 파드 list 요청이 한꺼번에 몰려 etcd 메모리가 세 배 가까이 늘고 마스터 노드가 연쇄적으로 재시작했다.Palark · 2023같은 원인 · 공통 텔레메트리 에이전트
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0206GKE 파드 안의 Consul 에이전트가 메모리 급증으로 거듭 OOM kill 되어 Rails 파드가 데이터베이스 복제본을 찾지 못했고, 모든 쿼리가 primary 로 몰려 GitLab.com 이 느려졌다.GitLab · 2022같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0384US-EAST-1 의 Amazon Kinesis Data Streams 에서 레코드 읽기와 쓰기가 하루 대부분 실패했다Amazon Web Services · 2020같은 원인 · 공통 텔레메트리 에이전트
IL-0496전역 복제 Cassandra 클러스터에서 모든 리전의 인스턴스 CPU 가 100% 로 치솟아 쿼리가 타임아웃됐고, 같은 부하가 이틀 저녁 더 찾아왔다Ably · 2020같은 원인 · 공통 데이터베이스
IL-0026메모리 제한이 없는 fluentd-sumologic 파드가 메모리를 다 써서 운영 쿠버네티스 노드 두 대에 이틀 연속 SystemOOM 이 났다Blue Matador · 2019같은 원인 · 공통 텔레메트리 에이전트
IL-0037imagePullPolicy가 Always인 DaemonSet이 크래시 루프를 돌며 이미지를 계속 받아, NAT 세 대를 같이 쓰던 리전 전체가 이미지 레지스트리에서 429로 막혔다Datadog · 2019같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0211Mandrill 의 PostgreSQL 샤드 하나가 트랜잭션 ID 랩어라운드를 막으려고 쓰기를 멈춰 약 40시간 동안 메일 발송이 줄었다Mailchimp · 2019같은 원인 · 공통 데이터베이스
IL-0064CPU 를 많이 쓰는 파드가 Google Cloud 노드 하나에 몰려 노드가 커널 패닉으로 죽었고, 다시 배치된 파드가 다음 노드를 또 죽이며 웹사이트와 API 가 멈췄다.Moonlight · 2019같은 원인 · 공통 데이터베이스
IL-0075클러스터가 EC2 인스턴스 약 290대로 커지자 노드마다 도는 Datadog 에이전트가 쿠버네티스 API 를 폴링하면서 API 서버가 CPU 와 메모리를 다 써 쿠버네티스 컨트롤 플레인을 쓸 수 없게 됐다.Civis Analytics · 2019같은 원인 · 공통 텔레메트리 에이전트
같은 원인 · 공통 데이터베이스
IL-0333사양을 낮춘 RDS PostgreSQL 인스턴스가 피크 부하를 못 버텨 헬스 체크가 실패하고 Buildkite 대시보드가 몇 시간 동안 내려갔다Buildkite · 2016같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스 복제
IL-0282US-East 리전의 DynamoDB 스토리지 서버들이 멤버십 정보를 받지 못해 스스로 요청 처리에서 빠지면서 고객 요청의 약 55% 가 실패했다Amazon Web Services · 2015같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0288
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0288/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.