
1. PromQL 기본 개념
PromQL(Prometheus Query Language)은 Prometheus의 시계열 데이터를 조회하고 분석하는 쿼리 언어입니다. Grafana 대시보드, 알림 규칙 모두 PromQL로 작성합니다.
4가지 데이터 타입
| 타입 | 설명 | 예시 |
|---|---|---|
| Instant Vector | 동일 타임스탬프의 시계열 집합 | http_requests_total |
| Range Vector | 시간 범위의 시계열 | http_requests_total[5m] |
| Scalar | 단일 숫자 값 | 3.14 |
| String | 문자열 (거의 안 씀) | "hello" |
메트릭 타입
Counter — 단조 증가 값 (리셋 시 0으로) : http_requests_total
Gauge — 올라갈 수도 내려갈 수도 : temperature, memory_usage
Histogram — 분포 측정 (bucket) : http_request_duration_seconds
Summary — 분위수 직접 계산 : go_gc_duration_seconds
2. 셀렉터와 매칭
# 기본 셀렉터
http_requests_total
# 라벨 매칭
http_requests_total{method="GET", status="200"}
# 정규식 매칭
http_requests_total{method=~"GET|POST"}
http_requests_total{status!~"2.."}
# 부정 매칭
http_requests_total{method!="DELETE"}
# __name__ 매칭 (메트릭 이름도 라벨)
{__name__=~"http_requests.*"}
3. 핵심 함수
rate() — Counter의 초당 변화율
# 지난 5분간 초당 요청 수
rate(http_requests_total[5m])
# job별 초당 요청 수
sum(rate(http_requests_total[5m])) by (job)
# method별 초당 요청 수 Top 5
topk(5, sum(rate(http_requests_total[5m])) by (method))
주의: rate()는 반드시 Counter 타입에만 사용하세요. Gauge에는 deriv()를 사용합니다.
increase() — 일정 시간 동안의 증가량
# 지난 1시간 동안의 총 요청 수
increase(http_requests_total[1h])
# 일일 에러 수
sum(increase(http_requests_total{status=~"5.."}[24h]))
histogram_quantile() — 퍼센타일 계산
# 95th 퍼센타일 응답 시간
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
)
# 서비스별 99th 퍼센타일
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service)
)
# 50th (중앙값) 응답 시간
histogram_quantile(0.5,
rate(http_request_duration_seconds_bucket[5m])
)
irate() — 순간 변화율
# 최근 2개 데이터 포인트 기준 순간 변화율
irate(http_requests_total[5m])
rate()는 전체 범위의 평균, irate()는 가장 최근 2개 포인트의 변화율입니다. 대시보드에서는 irate()가 더 반응적이고, 알림에는 rate()가 더 안정적입니다.
4. 집계 연산자
# sum — 합계
sum(rate(http_requests_total[5m])) by (instance)
# avg — 평균
avg(node_cpu_seconds_total{mode="idle"}) by (instance)
# max, min
max(container_memory_usage_bytes) by (pod)
# count — 시계열 개수
count(up == 1) by (job)
# quantile — 분위수
quantile(0.95, rate(http_requests_total[5m]))
# stddev — 표준편차
stddev(rate(http_requests_total[5m])) by (job)
# without — 특정 라벨 제외하고 집계
sum without (instance)(rate(http_requests_total[5m]))
5. 실전 쿼리 패턴
에러율 계산
# HTTP 5xx 에러율 (%)
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
* 100
# 서비스별 가용률
1 - (
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
)
리소스 사용률
# CPU 사용률 (%)
100 - (avg by (instance)(
irate(node_cpu_seconds_total{mode="idle"}[5m])
) * 100)
# 메모리 사용률 (%)
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
# 디스크 사용률
(1 - node_filesystem_avail_bytes{mountpoint="/"}
/ node_filesystem_size_bytes{mountpoint="/"}) * 100
Saturation (포화도)
# Pod CPU throttling
sum(rate(container_cpu_cfs_throttled_seconds_total[5m])) by (pod)
/
sum(rate(container_cpu_cfs_periods_total[5m])) by (pod)
# 큐 길이
avg_over_time(queue_length[5m])
6. 알림 규칙 작성
# prometheus-rules.yaml
groups:
- name: application
rules:
# 높은 에러율
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
> 0.05
for: 5m
labels:
severity: critical
annotations:
summary: 'High error rate on {{ $labels.service }}'
description: 'Error rate is {{ $value | humanizePercentage }}'
# 느린 응답 시간
- alert: SlowResponseTime
expr: |
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service)
) > 1.0
for: 10m
labels:
severity: warning
annotations:
summary: 'P95 latency > 1s on {{ $labels.service }}'
- name: infrastructure
rules:
# 높은 메모리 사용률
- alert: HighMemoryUsage
expr: |
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) > 0.9
for: 15m
labels:
severity: warning
# 디스크 부족 예측
- alert: DiskWillFillIn24h
expr: |
predict_linear(node_filesystem_avail_bytes{mountpoint="/"}[6h], 24*3600) < 0
for: 30m
labels:
severity: warning
annotations:
summary: 'Disk will fill in 24h on {{ $labels.instance }}'
# Pod CrashLooping
- alert: PodCrashLooping
expr: |
increase(kube_pod_container_status_restarts_total[1h]) > 5
for: 10m
labels:
severity: critical
7. Grafana 대시보드 쿼리
# RED Method 대시보드
# Rate (요청 수/초)
sum(rate(http_requests_total[5m])) by (service)
# Errors (에러 수/초)
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
# Duration (지연 시간 분포)
histogram_quantile(0.5, sum(rate(http_request_duration_seconds_bucket[$__rate_interval])) by (le))
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[$__rate_interval])) by (le))
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[$__rate_interval])) by (le))
8. 퀴즈
Q1: rate()와 irate()의 차이점과 각각 적합한 사용 상황은?
rate(): 전체 범위의 초당 평균 변화율을 계산합니다. 더 부드럽고 안정적이어서 알림 규칙에 적합합니다. irate(): 범위 내 가장 최근 2개 데이터 포인트의 순간 변화율입니다. 스파이크를 빠르게 감지하므로 대시보드 그래프에 적합합니다.
주의: 둘 다 Range Vector를 인자로 받지만 [5m]의 의미가 다릅니다. rate()는 5분 평균, irate()는 5분 내 최근 2포인트만 사용합니다.
Q2: predict_linear() 함수의 용도와 동작 원리는?
predict_linear(v range-vector, t scalar)는 시계열 데이터에 선형 회귀를 적용하여 t초 후의 값을 예측합니다.
예: predict_linear(node_filesystem_avail_bytes[6h], 24*3600) < 0
→ 지난 6시간의 디스크 여유 공간 추세를 분석하여 24시간 후 0 이하가 될지 예측합니다.
디스크 부족, 메모리 증가 등 자원 고갈을 미리 감지하는 용량 계획 알림에 핵심적으로 사용됩니다.
Q3: histogram_quantile에서 le 라벨의 역할과 주의사항은?
le는 "less than or equal"의 약자로, 히스토그램 버킷의 상한값을 나타냅니다. http_request_duration_seconds_bucket{le="0.5"}는 0.5초 이하인 요청 수입니다.
주의사항:
by (le)를 반드시 포함해야 합니다 — 빠뜨리면 le별 집계가 깨져서 잘못된 값이 나옵니다
버킷 경계가 적으면 보간(interpolation)이 부정확합니다
결과는 근사치입니다 — 정확한 퍼센타일이 필요하면 Summary 타입을 사용하세요