クエリは回してみないと分からない
한국어 원문으로 표시합니다.
한 줄 요약
PromQL 은 틀려도 오류를 내지 않고 빈 결과를 냅니다. 그래서 쿼리가 맞는지는 진짜 지표 위에서 돌려 봐야만 알 수 있습니다.
왜 진짜 Prometheus 여야 하나
앞 모듈들에서 PromQL 을 여러 개 썼습니다. 그런데 그 실습들이 도는 곳에는 Prometheus 자체가 없어서, 쿼리가 원하는 답을 주는지 확인할 방법이 없었습니다.
PromQL 은 문법이 맞아도 조용히 빈 결과를 내는 경우가 많습니다. 오류가 아니라 빈 결과라서 알아채기 어렵습니다.
- 범위 선택자가 수집 주기보다 짧으면
rate()가 계산할 점이 부족합니다 - 라벨 이름을 하나 틀리면 매칭되는 시계열이 없습니다
- 레코딩 룰은 등록된 뒤부터 계산하므로 과거 구간이 비어 있습니다
up == 0 이 잡지 못하는 것
가장 값진 함정입니다. up == 0 은 대상이 있으면서 응답하지 않을 때만 참입니다.
파드가 통째로 사라지면 서비스디스커버리에서 대상이 빠지고 up 시계열 자체가 없어집니다. 없는 것은 0 이 아니므로 알림이 걸리지 않습니다.
"다 죽었는데 아무 알림도 안 왔다" 가 여기서 나옵니다.
up == 0 대상이 있는데 응답이 없다
absent(up{job="x"}) 그 job 의 대상이 아예 없다
count(up{job="x"}) < 3 예상보다 적다 ← 실무에서 가장 쓸모 있다
설정이 반영되지 않는 자리
ConfigMap 볼륨은 kubelet 이 주기적으로 동기화합니다(약 60초). 전파 전에 reload 를 치면 옛 설정을 다시 읽는데, reload 는 200 을 돌려줍니다. 그래서 설정이 틀렸다고 믿고 엉뚱한 곳을 고치게 됩니다.
그리고 subPath 로 마운트하면 갱신이 아예 전파되지 않습니다.
알림을 쓸모 있게 만드는 규칙
경보가 많아지면 사람이 보지 않게 되고, 그러면 없는 것과 같아집니다. 네 가지를 지키면 대부분 걸러집니다.
증상으로 겁니다, 원인이 아니라. "CPU 80% 초과" 는 사람을 깨울 이유가 아닙니다. "결제 오류율 5% 초과" 는 이유입니다. 원인 지표는 대시보드에 두고, 경보는 사용자가 겪는 것에만 겁니다.
for 를 반드시 붙입니다. 순간의 스파이크로 깨우면 신뢰를 잃습니다.
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m])) > 0.05
for: 10m # 10분 동안 계속 참일 때만
labels: {severity: page}
annotations:
summary: "5xx 비율 {{ $value | humanizePercentage }}"
runbook: "https://…/runbooks/high-error-rate"
runbook 링크를 답니다. 새벽 3시에 깬 사람이 무엇을 볼지 적혀 있지 않은 경보는 불안만 만듭니다.
소진율(burn rate)로 겁니다. SLO 가 99.9% 라면 한 달 오류 예산이 43분입니다. "지금 속도로 가면 예산을 언제 다 쓰는가" 로 걸면, 짧고 심한 것과 길고 약한 것을 한 규칙으로 잡습니다.
빠른 소진: 1시간 창에서 예산의 2% 이상 → 즉시 호출
느린 소진: 6시간 창에서 예산의 5% 이상 → 티켓
지표 카디널리티가 Prometheus 를 죽인다
라벨 값 하나가 시계열 하나입니다. user_id 를 라벨로 넣으면 사용자 수만큼 시계열이
생기고, 메모리가 그만큼 필요합니다.
# 지금 무엇이 시계열을 많이 쓰나
topk(10, count by (__name__)({__name__=~".+"}))
# 특정 지표의 라벨별 카디널리티
count(count by (route) (http_request_duration_seconds_count))
Prometheus 의 /status/tsdb 화면에도 상위 지표와 라벨이 나옵니다. 시계열 100만
개를 넘어가면 메모리가 수 GB 단위로 늘고, 재시작 시 WAL 재생이 길어져 몇 분간
지표가 비어 보입니다.
값이 무한히 늘 수 있는 것(요청 ID, 이메일, 전체 URL)은 지표가 아니라 로그나 트레이스에 넣습니다. 이 구분이 관측 설계의 절반입니다.
실무에서 진짜 중요한 것
알림은 up == 0 이 아니라 count(...) < N 으로 겁니다. 사라진 대상은 0 이 아니라 없는 것이라, up == 0 은 가장 큰 사고에서 침묵합니다. 기대 개수를 아는 job 마다 개수 알림을 하나씩 두는 것이 값이 큽니다.
설정을 고친 뒤에는 reload 의 200 을 믿지 말고 반영된 값을 되읽습니다. ConfigMap 전파는 최대 60초 걸리고 subPath 마운트는 아예 갱신되지 않습니다. /api/v1/status/config 로 지금 떠 있는 설정을 확인하는 것이 유일하게 확실한 방법입니다.
레코딩 룰은 등록된 시점부터 계산합니다. 대시보드를 룰 기반으로 옮기면 과거 구간이 비어 보입니다. 이관할 때는 두 표현식을 한동안 나란히 두고 겹치는 구간을 대조해야 합니다.
다음 실습에서 이것들을 진짜 Prometheus 위에서 직접 확인합니다.