Ken
ClickHouse Cloud의 매트릭과 비용을 주기적으로 수집하여 데이터화 하고, 이를 토대로 비용 추적 및 Alert를 구현하고 있는 개인 프로젝트입니다. v0.1은 자기 서비스에서만 수집이 가능하며, 다수의 서비스에 적용가능한 버전을 추가로 개발 중에 있습니다. (
- 들어가며
- CostKeeper의 핵심 특징
- 시스템 아키텍처
- 전체 구조
- 데이터 흐름 타이밍
- 핵심 설계 원칙
- 왜 15분 단위 수집인가?
- APPEND vs REPLACE 모드
- RMV 실행 타이밍 설계
- 테이블 구조
- Layer 1: Raw Data
- Layer 2: Aggregation
- Layer 3: Analysis
- Layer 4: Alerting
- Views
- 주요 계산 로직
- 효율성 계산
- lagInFrame 비교
- Alert 임계값
- 빠른 시작
- 설치 (3분)
- 대화형 입력 항목
- 확인
- 문제 해결
- metrics_15min 데이터 손실
- hourly_metrics가 비어있음
- Alert 미발생
- 참고 자료
들어가며
이전 글에서는 ClickHouse Cloud의 세 가지 데이터 소스(Cloud API, Prometheus API, System Tables)와 각각의 특징을 살펴보았습니다. 이번 글에서는 이러한 데이터 소스를 실제로 활용하여 비용과 리소스를 통합 분석하는 모니터링 시스템을 구축하는 방법을 다룹니다.
CostKeeper의 핵심 특징
100% ClickHouse Cloud 네이티브: 외부 스케줄러나 cronjob 없이 Refreshable Materialized View (RMV)만으로 완전 자동화됩니다.
15분 단위 메트릭 수집: CHC의 system.asynchronous_metric_log는 약 33분만 보관되므로, 15분 주기 수집으로 데이터 손실을 방지합니다.
동적 리소스 조회: CGroupMaxCPU, CGroupMemoryTotal 메트릭에서 할당량을 직접 조회하여 Auto-scaling 환경에서도 정확한 효율성을 계산합니다.
자동 Alert 시스템: INFO(20%), WARNING(30%), CRITICAL(50%) 3단계 심각도로 즉시 감지합니다.
시스템 아키텍처
전체 구조
데이터 흐름 타이밍
핵심 설계 원칙
왜 15분 단위 수집인가?
CHC의 system.asynchronous_metric_log는 약 33분만 보관됩니다. 1시간 주기로 수집하면 데이터가 이미 삭제된 후 수집을 시도하게 됩니다.
APPEND vs REPLACE 모드
RMV | 모드 | 테이블 엔진 | 이유 |
rmv_daily_billing | APPEND | ReplacingMergeTree | 7일 데이터 반복 수집 → 중복 자동 제거 |
rmv_metrics_15min | APPEND | SharedMergeTree | 매번 새 타임스탬프 → 중복 없음 |
rmv_hourly_metrics | APPEND | SharedMergeTree | 매번 새 타임스탬프 → 중복 없음 |
rmv_hourly_analysis | APPEND | SharedMergeTree | 매번 새 타임스탬프 → 중복 없음 |
핵심: 시계열 데이터는 APPEND + SharedMergeTree, 중복 가능 데이터는 APPEND + ReplacingMergeTree
RMV 실행 타이밍 설계
RMV | 실행 시각 | OFFSET 이유 |
rmv_metrics_15min | 00, 15, 30, 45분 | 즉시 실행 |
rmv_hourly_metrics | 매시 +2분 | 마지막 15분 데이터 대기 |
rmv_hourly_analysis | 매시 +5분 | hourly_metrics 완료 대기 |
mv_alerts | 실시간 | INSERT 트리거 |
테이블 구조
Layer 1: Raw Data
daily_billing - CHC API에서 수집한 일별 비용 (TTL: 365일)
컬럼 | 타입 | 설명 |
date | Date | 청구 날짜 |
service_id | String | CHC 서비스 UUID |
service_name | String | 서비스 표시 이름 |
total_chc | Float64 | 총 비용 (CHC) |
compute_chc | Float64 | 컴퓨팅 비용 |
storage_chc | Float64 | 스토리지 비용 |
network_chc | Float64 | 네트워크 비용 |
api_fetched_at | DateTime64(3) | API 조회 시각 (버전 컬럼) |
metrics_15min - 15분 단위 시스템 메트릭 (TTL: 365일)
컬럼 | 타입 | 소스 메트릭 |
collected_at | DateTime | 수집 시각 (15분 단위) |
allocated_cpu | Float64 | CGroupMaxCPU |
allocated_memory_gb | Float64 | CGroupMemoryTotal |
cpu_usage_avg/p50/p90/p99/max | Float64 | CGroupUserTime + CGroupSystemTime |
memory_used_avg/p99/max_gb | Float64 | CGroupMemoryUsed |
memory_usage_pct_avg/p99/max | Float64 | Used / Total × 100 |
disk_read/write_bytes | Float64 | BlockReadBytes, BlockWriteBytes |
network_rx/tx_bytes | Float64 | NetworkReceiveBytes/SendBytes |
load_avg_1m/5m | Float64 | LoadAverage1/5 |
Layer 2: Aggregation
hourly_metrics - 4개 15분 데이터의 시간별 집계 (TTL: 365일)
집계 방식 | 적용 메트릭 |
avg() | CPU, Memory 사용률, allocated_cpu/memory |
max() | cpu_usage_max, memory_used_max_gb |
sum() | disk_read/write_bytes, network_rx/tx_bytes |
Layer 3: Analysis
hourly_analysis - 비용 분석 및 Alert 플래그 (TTL: 365일)
카테고리 | 컬럼 | 설명 |
비용 (일별) | daily_total/compute/storage/network_chc | Billing API 원본 |
비용 (시간별) | estimated_hourly_total/compute/storage/network_chc | daily / 24 |
단가 | cost_per_cpu_core_hour | hourly_compute / allocated_cpu |
리소스 | allocated_cpu, allocated_memory_gb | 할당량 |
사용량 | cpu_usage_avg/p99/max, memory_usage_pct_avg/p99 | 실제 사용 |
효율성 | cpu_efficiency_pct | (usage / allocated) × 100 |
효율성 | memory_efficiency_pct | memory_usage_pct_avg |
효율성 | overall_efficiency_pct | (cpu_eff + mem_eff) / 2 |
비교값 | prev_1h/3h/24h_cpu_usage | lagInFrame 결과 |
비교값 | prev_1h/3h/24h_hourly_cost | lagInFrame 결과 |
변화율 | pct_change_1h/3h/24h_cpu | CPU 변화율 (%) |
변화율 | pct_change_1h/3h/24h_cost | 비용 변화율 (%) |
Alert | alert_cpu_spike_1h/3h/24h | CPU Alert 플래그 (0/1) |
Alert | alert_cost_spike_1h/3h/24h | Cost Alert 플래그 (0/1) |
Alert | alert_any | 종합 Alert 플래그 (0/1) |
Layer 4: Alerting
alerts - 생성된 Alert 저장 (TTL: 90일)
컬럼 | 타입 | 설명 |
alert_id | UUID | 고유 식별자 |
alert_time | DateTime64(3) | Alert 생성 시각 |
hour | DateTime | Alert 대상 시간 |
alert_type | LowCardinality(String) | cpu / cost |
comparison_period | LowCardinality(String) | 1h / 3h / 24h |
severity | LowCardinality(String) | info / warning / critical |
current_value | Float64 | 현재 값 |
comparison_value | Float64 | 비교 대상 값 |
pct_change | Float64 | 변화율 (%) |
estimated_hourly_chc | Float64 | 예상 시간당 비용 |
potential_daily_impact_chc | Float64 | 예상 일일 영향 |
message | String | Alert 상세 메시지 |
acknowledged | UInt8 | 확인 여부 (0/1) |
Views
v_dashboard - 실시간 대시보드 (최근 100시간)
컬럼 | 설명 |
daily_chc, hourly_chc | 비용 정보 |
cpu_cores, cpu_eff_pct, mem_eff_pct | 리소스 효율성 |
chg_1h/3h/24h_pct | 변화율 |
alert_any, alert_source | Alert 현황 |
v_alerts - 미확인 Alert 조회 (최근 50개)
주요 계산 로직
효율성 계산
CPU 효율성 = (cpu_usage_avg / allocated_cpu) × 100
Memory 효율성 = memory_usage_pct_avg
전체 효율성 = (cpu_efficiency + memory_efficiency) / 2
lagInFrame 비교
lagInFrame 윈도우 함수로 Self JOIN 없이 이전 데이터를 비교합니다:
prev_1h_cpu = lagInFrame(cpu_usage_avg, 1) OVER (ORDER BY hour)
prev_24h_cpu = lagInFrame(cpu_usage_avg, 24) OVER (ORDER BY hour)
pct_change_1h_cpu = ((current - prev_1h) / prev_1h) × 100
Alert 임계값
Severity | 변화율 임계값 |
INFO | ≥ 20% |
WARNING | ≥ 30% |
CRITICAL | ≥ 50% |
빠른 시작
설치 (3분)
./setup-costkeeper.sh
대화형 입력 항목
- CHC 연결: 호스트, 비밀번호
- API 설정: Organization ID, API Key
- 서비스 선택: 모니터링할 서비스 선택
- 임계값: Alert 발생 기준 (기본: 20/30/50%)
확인
-- Dashboard 확인
SELECT * FROM costkeeper.v_dashboard LIMIT 10;
-- Alert 확인
SELECT * FROM costkeeper.v_alerts;
-- RMV 상태
SELECT view, status, next_refresh_time
FROM system.view_refreshes
WHERE database = 'costkeeper';
문제 해결
metrics_15min 데이터 손실
증상: 15분 데이터가 누적되지 않음
원인: RMV가 APPEND 모드가 아님
해결: SHOW CREATE TABLE rmv_metrics_15min으로 APPEND 키워드 확인
hourly_metrics가 비어있음
증상: 시간별 집계 데이터 없음
원인: 4개의 15분 데이터가 준비되지 않음
확인: metrics_15min에서 해당 시간의 row 수 확인 (4개 필요)
Alert 미발생
증상: 변화율이 높은데 Alert가 없음
확인: hourly_analysis에서 alert_any 플래그 값 확인
참고 자료
코드 저장소:
clickhouse-hols/chc/tool/costkeeper at main · litkhai/clickhouse-hols
ClickHouse Hands-on Labs . Contribute to litkhai/clickhouse-hols development by creating an account on GitHub.
github.com
공식 문서:
- ClickHouse Cloud API
- Refreshable Materialized Views
- Window Functions