PCA — 프로메테우스 인증 어소시에이트 · PromQL · 이론
rate 는 왜 정수를 주지 않고, le 는 왜 버리면 안 되나
한 줄 요약
PromQL 에서 가장 많이 틀리는 두 가지는 rate 를 sum 뒤에 쓰는 것과 분위수 계산에서 le 를 버리는 것입니다. 둘 다 에러를 내지 않고 그럴듯한 숫자를 돌려주기 때문에 대시보드에 몇 달씩 살아남습니다.
왜 이게 필요했나
카운터는 그대로 그리면 우상향 직선이고 아무 정보가 없습니다. 그래서 rate 로 초당 증가율을 봅니다. 그런데 rate 는 단순한 나눗셈이 아니라 외삽(extrapolation) 을 합니다. 범위 안 첫 샘플과 마지막 샘플의 차이를 구한 뒤, 샘플이 범위 경계에 딱 붙어 있지 않은 만큼을 비례로 늘려 잡습니다. 그래서 increase 가 3.4 같은 값을 돌려줍니다. 에러가 정확히 3건이었어도 그렇습니다. 이것은 버그가 아니라 정의이고, "정확히 N건"이 필요한 계산에는 쓰지 않습니다.
어떻게 동작하나
rate 의 세 가지 함정
첫째, 윈도가 스크레이프 간격에 비해 좁으면 안 됩니다. rate 는 윈도 안에 샘플이 최소 두 개 있어야 값을 냅니다. 스크레이프가 15초인데 윈도가 20초면 샘플이 하나뿐인 순간이 생겨 결과가 비어 버리고, 그래프에는 구멍으로, 알림에서는 "조건 불성립"으로 나타납니다. 경험칙은 윈도 ≥ 스크레이프 간격 × 4 이고 알림에는 5분 이상을 씁니다.
둘째, 순서입니다.
# 틀림 — 카운터를 먼저 더하면 파드 재시작(리셋)이 감지되지 않는다rate(sum(http_requests_total) by (route)[5m:])# 맞음 — rate 를 먼저, 집계는 그다음sum(rate(http_requests_total[5m])) by (route)카운터 리셋 보정은 개별 시계열 단위로만 정확합니다. 파드 하나가 재시작해 0 으로 떨어져도, 이미 합산된 뒤에는 "전체가 조금 줄었다"로만 보여 리셋으로 인식되지 않습니다. 결과는 실제보다 낮은 요청률이고, 배포할 때마다 트래픽이 줄어든 것처럼 보입니다.
셋째, irate 는 마지막 두 샘플만 봅니다. 대시보드에서 순간 반응을 볼 때는 쓸 만하지만 알림에는 절대 쓰지 않습니다. 노이즈 한 번에 발화합니다.
lookback delta 와 staleness
즉시 벡터 셀렉터는 평가 시점 T 에서 과거로 최대 5분(기본 lookback delta)까지 훑어 가장 최근 샘플을 씁니다. 정확히 T 시점에 샘플이 없어도 되는 이유가 이것입니다. 다만 그 사이에 stale marker 가 있으면 시계열은 결과에서 빠집니다.
histogram_quantile 의 선형 보간
le="1" 누적 9812le="2.5" 누적 9993목표 = 0.99 × 10000 = 9900추정 = 1.0 + (9900 - 9812) / (9993 - 9812) × (2.5 - 1.0) = 1.729초1.729초라는 정밀해 보이는 숫자가 나오지만, 이 버킷 안의 181건이 실제로 어디 있는지는 아무도 모릅니다. 전부 1.05초일 수도, 전부 2.4초일 수도 있습니다. 여기서 실무 규칙 세 개가 나옵니다. SLO 임계값과 정확히 같은 버킷 경계를 넣을 것, 관심 구간을 촘촘히 둘 것, 최상단 유한 버킷을 실제 타임아웃보다 크게 잡을 것. p99 가 마지막 유한 경계를 넘으면 함수는 그 경계값에 붙어 버려서 얼마나 나쁜지 알 수 없게 됩니다.
그리고 집계할 때 le 를 반드시 남깁니다.
# 틀림 — le 를 버리면 버킷이 뭉개져 의미 없는 숫자가 나온다histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (route))# 맞음histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, route))같은 이유로 avg(histogram_quantile(...)) 도 틀립니다. 분위수를 평균 내는 대신 버킷 카운터를 먼저 합치고 그 위에서 분위수를 구합니다.
시험이 좋아하는 나머지들
| 요소 | 핵심 |
| --- | --- |
| offset / @ | 상대 이동 / 절대 에포크 시점 지정 |
| bool | 비교 결과를 필터링 대신 0·1 값으로 |
| on / ignoring | 이항 연산의 매칭 레이블 지정 |
| group_left / group_right | 다대일·일대다 매칭 허용 |
| unless | 오른쪽과 매칭되는 시계열을 왼쪽에서 제거 |
| 서브쿼리 | expr[30m:1m] — 범위:해상도 |
| predict_linear | 게이지의 선형 회귀 외삽, 용량 알림용 |
| absent | 시계열이 없을 때 1 을 반환 |
현장에서 만나는 모습
홈랩 대시보드에서 가장 오래 살아 있던 버그가 by (le 누락이었습니다. 값이 나오고, 그래프도 그려지고, 심지어 그럴듯하게 움직입니다. 잡아내는 방법은 하나뿐입니다 — histogram_quantile 이 들어간 쿼리를 전부 검색해서 le 가 집계 절에 있는지 눈으로 확인하는 것입니다. 대부분의 팀에서 하나쯤은 빠져 있습니다.
카디널리티 사고는 대체로 배포 직후에 계단식으로 나타납니다. prometheus_tsdb_head_series 를 그래프로 띄워 두고 배포 시각과 겹쳐 보면 원인 커밋이 바로 나옵니다. 어떤 메트릭이 범인인지는 topk(10, count by (__name__)({__name__=~".+"})) 한 줄이면 끝납니다.
다음 실습에서 할 것
/root/pca-promql/ 아래에 쿼리 여덟 개를 파일로 씁니다. 라우트별 요청률과 에러율, le 를 지킨 p99, 카디널리티 진단, predict_linear 디스크 예측, 저트래픽에서 유령 알림을 막는 AND 게이트, up 과 absent 를 묶은 스크레이프 건강 확인, 그리고 마지막으로 두 창을 AND 로 묶은 번 레이트 표현식까지. 채점은 문자열 매칭이므로 지시한 메트릭 이름과 윈도를 정확히 쓰세요.