모니터링 (system 테이블, Prometheus 엔드포인트, 대시보드, 경보)
현재 값과 누적 카운터와 주기 측정값을 담는 system 테이블 세 가지, Prometheus 엔드포인트 설정, 내장 대시보드와 Grafana, 그리고 운영에서 실제로 걸어 두는 경보 목록을 정리합니다.
지표는 세 테이블에서 나옵니다
ClickHouse 는 자기 상태를 전부 system 테이블로 보여 줍니다. 세 테이블의 성격이 달라서 같이 봐야 합니다.
| 테이블 | 성격 | 예 |
|---|---|---|
system.metrics | 지금 이 순간의 값 (게이지) | Query(실행 중 쿼리 수), MemoryTracking, ReadonlyReplica, BackgroundMergesAndMutationsPoolTask |
system.events | 서버 시작 뒤 누적 카운터 | Query, InsertedRows, SelectedRows, RejectedInserts, DelayedInserts, FailedQuery, MergedRows |
system.asynchronous_metrics | 주기적으로(기본 1초) 다시 계산하는 값 | MaxPartCountForPartition, ReplicasMaxAbsoluteDelay, MemoryResident, Uptime, NumberOfTables, 디스크와 CPU 지표 |
세 테이블의 값은 system.metric_log 에 초 단위 이력으로 쌓입니다. "그때 무슨 일이 있었나" 를 되짚을 때는 이 테이블입니다.
SELECT toStartOfMinute(event_time) AS m,
max(CurrentMetric_Query) AS running_q,
max(CurrentMetric_MemoryTracking) / 1e9 AS mem_gb,
sum(ProfileEvent_Query) AS queries,
sum(ProfileEvent_FailedQuery) AS failed,
sum(ProfileEvent_RejectedInserts) AS rejected
FROM system.metric_log
WHERE event_time > now() - INTERVAL 6 HOUR
GROUP BY m ORDER BY m;로그 성격의 테이블도 함께 씁니다.
| 테이블 | 담는 것 | 어디에 쓰나 |
|---|---|---|
system.query_log | 쿼리마다 시간, 읽은 양, 메모리, 설정, 예외 | 느린 쿼리 진단 |
system.part_log | 파트 생성, 머지, 뮤테이션, 삭제, 다운로드 | INSERT 패턴, 머지 속도 (Too many parts) |
system.text_log | 서버 로그 자체 | 에러 메시지 검색 |
system.error_log | 에러 코드별 발생 수 이력 (최근 버전) | 에러 추세 |
system.errors | 에러 코드별 누적 수와 마지막 메시지 | 지금 서버에서 무엇이 터지고 있나 |
system.crash_log | 서버 크래시 스택 | 재시작 원인 |
system.trace_log | 프로파일러 샘플 | CPU 병목 |
system.opentelemetry_span_log | 쿼리 처리 단계 스팬 | 분산 쿼리 추적 |
SELECT name, code, value, last_error_time, last_error_message
FROM system.errors
WHERE last_error_time > now() - INTERVAL 1 HOUR
ORDER BY value DESC;팁 system 로그 테이블은 기본으로 무한히 자랍니다.
config.d에서 각 로그 테이블에<ttl>event_date + INTERVAL 30 DAY</ttl>을 주고,metric_log처럼 큰 것은collect_interval_milliseconds를 늘려 줍니다. 로그 테이블 자체가 디스크를 채운 사고가 드물지 않습니다.
Prometheus 엔드포인트
설정 한 조각으로 서버가 Prometheus 형식 지표를 내보냅니다.
<clickhouse>
<prometheus>
<endpoint>/metrics</endpoint>
<port>9363</port>
<metrics>true</metrics>
<events>true</events>
<asynchronous_metrics>true</asynchronous_metrics>
<errors>true</errors>
</prometheus>
</clickhouse>curl -s http://localhost:9363/metrics \
| grep -E 'ClickHouseMetrics_Query |ClickHouseAsyncMetrics_MaxPartCountForPartition'지표 이름은 ClickHouseMetrics_, ClickHouseProfileEvents_, ClickHouseAsyncMetrics_, ClickHouseErrorMetric_ 접두어가 붙습니다. 복제본 수십 대를 긁는 쪽이 Prometheus 이고, 서버는 요청받을 때 값을 만들어 줍니다. Keeper 도 같은 방식의 <prometheus> 설정이 있습니다.
Cloud 는 조직 단위 Prometheus 엔드포인트(API 키로 인증)를 제공해 Grafana 나 Datadog 에 붙일 수 있습니다. 서비스 콘솔의 고급 대시보드로도 같은 지표를 봅니다 (ClickHouse Cloud 개요).
대시보드
- 내장 대시보드: 서버 HTTP 포트의
/dashboard경로(http://host:8123/dashboard)에 쿼리 기반 차트가 들어 있습니다. 차트 정의는system.dashboards테이블에 있고 직접 추가할 수 있습니다. 설치 직후 바로 쓸 수 있어 급할 때 좋습니다. - Grafana: 공식 ClickHouse 데이터 소스 플러그인(
grafana-clickhouse-datasource)으로 system 테이블을 직접 쿼리하거나 Prometheus 를 거쳐 봅니다. 공개된 대시보드 템플릿이 여럿 있습니다. - 자기 관측: ClickStack(HyperDX)으로 ClickHouse 자신의 로그와 트레이스를 ClickHouse 에 넣어 보는 구성도 가능합니다 (ClickStack과 chDB).
대시보드 첫 화면에 두는 패널은 보통 다음과 같습니다. 왼쪽 위에서부터 중요 순서입니다.
- 실행 중 쿼리 수와 초당 쿼리 수, 실패 수
- 쿼리 p50 과 p95 (query_log 기준)
- 메모리:
MemoryResident와 서버 한도,MemoryTracking - INSERT: 초당 행 수,
RejectedInserts,DelayedInserts - 파트:
MaxPartCountForPartition, 머지 풀 사용량 - 복제:
ReplicasMaxAbsoluteDelay,ReplicasMaxQueueSize,ReadonlyReplica - 디스크 여유 (
system.disks), CPU, 네트워크
경보 목록
실제로 걸어 두고 밤에 깨울 가치가 있는 것만 모았습니다. 수치는 출발점입니다.
| 경보 | 지표 | 조건 | 왜 |
|---|---|---|---|
| 서버 죽음 | Uptime, /ping 응답 | 1 분 응답 없음 | 당연 |
| readonly 복제본 | ReadonlyReplica (metrics) | 0 보다 큼 5 분 | 쓰기 불가 (복제 지연) |
| 복제 지연 | ReplicasMaxAbsoluteDelay | 300 초 이상 | 읽기 결과 불일치 |
| 파트 폭증 | MaxPartCountForPartition | 300 이상 | INSERT 거절 임박 |
| INSERT 거절 | RejectedInserts 증가율 | 5 분에 1 건 이상 | 데이터 유실 가능 |
| 메모리 | MemoryResident / OSMemoryTotal | 90% 이상 | 서버 한도 임박 (메모리 초과) |
| 디스크 | system.disks.free_space | 15% 이하 | 머지와 INSERT 실패 |
| 쿼리 실패율 | FailedQuery / Query | 5% 이상 | 장애 또는 배포 문제 |
| 느린 쿼리 | query_log p95 | 평소의 3 배 | 성능 회귀 |
| 머지 적체 | BackgroundMergesAndMutationsPoolTask 가 풀 크기와 같음 | 30 분 지속 | 머지가 따라가지 못함 |
| Keeper | zk_outstanding_requests, zk_avg_latency | 요청 적체, 지연 50 ms 이상 | 복제 전체 영향 |
| 백업 실패 | system.backups.status = 'BACKUP_FAILED' | 1 건 | 복원 불가 (백업과 복원) |
| 뮤테이션 적체 | system.mutations 의 is_done = 0 수 | 10 개 이상 1 시간 | 머지 막힘 |
경보를 SQL 로 만들려면 Grafana 의 ClickHouse 데이터 소스에서 아래 같은 쿼리를 주기적으로 돌립니다.
SELECT
(SELECT value FROM system.asynchronous_metrics
WHERE metric = 'MaxPartCountForPartition') AS max_parts,
(SELECT value FROM system.asynchronous_metrics
WHERE metric = 'ReplicasMaxAbsoluteDelay') AS max_delay,
(SELECT value FROM system.metrics WHERE metric = 'ReadonlyReplica') AS readonly_replicas,
(SELECT count() FROM system.mutations WHERE NOT is_done) AS pending_mutations;상태 확인 엔드포인트
curl -s http://localhost:8123/ping # Ok.
curl -s http://localhost:8123/replicas_status # Ok. 또는 뒤처진 복제본 목록 (503)
curl -s 'http://localhost:8123/?query=SELECT%201'로드 밸런서 헬스 체크에는 /replicas_status 를 쓰면 뒤처진 복제본을 자동으로 빼 줍니다. 허용 지연은 max_replica_delay_for_distributed_queries 를 따릅니다.
운영 루틴
- 매일 아침: 전날
system.errors상위, 실패 쿼리 수, 백업 상태, 디스크 추세를 한 화면에서 봅니다. - 매주:
query_logp95 상위 20 개 쿼리 모양을 뽑아 성능 회귀를 찾습니다 (느린 쿼리 진단). - 매달:
system.settings_changes와 릴리스 노트로 다음 업그레이드를 준비하고, 로그 테이블 크기와 TTL 을 확인합니다. - 배포 뒤: 배포 전후 30 분의
metric_log를 비교해 메모리와 쿼리 수의 변화를 봅니다.