무슨 일이 벌어지는가
absent_over_time(up{job="api"}[5m]) 같은 알람 표현식은 "지정한 메트릭이 5분 동안 한 번도 안 보이면 1을 반환"한다. 그래서 잡 다운 감지용으로 흔히 쓴다. 근데 함정이 있다.
Prometheus 프로세스가 막 기동했을 때, 아직 첫 스크레이프가 끝나지 않은 시점에서 이 표현식이 평가되면 어떻게 될까? 메트릭이 없으니까 그냥 1 이 나온다. 그리고 알람룰에 for 절이 없으면 그 즉시 firing.
# 이렇게 쓰면 Prometheus 재시작할 때마다 알람 옴
- alert: ApiDown
expr: absent_over_time(up{job="api"}[5m])
labels:
severity: critical
룰 평가 주기가 보통 30초~1분이라, Prometheus 부팅 후 첫 평가가 스크레이프보다 앞설 확률이 꽤 된다. 운영 환경에서 Prometheus 재시작 사유는 의외로 많다. 버전 업그레이드, 노드 교체, OOM, 설정 변경 후 reload가 안 먹어서 강제 재시작...
해결책
for 절을 붙인다. 끝.
- alert: ApiDown
expr: absent_over_time(up{job="api"}[5m])
for: 2m
labels:
severity: critical
for: 2m 이 의미하는 건 "2분 동안 계속 true여야 firing 으로 전환". 그 사이에 스크레이프가 한 번이라도 성공하면 메트릭이 들어오면서 표현식이 false 가 되고, pending 상태에서 자연 소멸한다. 거짓 양성을 깔끔하게 막아준다.
룰을 작성할 때 absent, absent_over_time 가 보이면 반사적으로 for 가 있는지 같이 확인하는 습관을 들이자. 이건 Prometheus 3.x 에서도 변하지 않았다. UTF-8 메트릭명 지원이 들어오면서 알람 룰에 따옴표 처리 관련 수정이 좀 있었는데, 함정 자체는 그대로다.
사이드 노트
for 값을 너무 크게 잡으면 진짜 장애 났을 때 알람이 늦게 온다. 보통 스크레이프 간격(15s)의 5~10배 정도가 무난하다. 1~2분이면 충분. 30분씩 잡아두는 곳도 봤는데, 그건 그냥 알람을 죽이는 거다.
다음에는 absent_over_time 으로 다중 잡을 한번에 감시하는 패턴(vector(0) or on() ... 트릭)도 정리해 보려고 한다.
'IT > 모니터링' 카테고리의 다른 글
| Grafana Alloy vs OpenTelemetry Collector, 결국 뭘로 갈까 (0) | 2026.06.12 |
|---|---|
| Tempo vs Jaeger v2, 결국 우리가 Tempo로 옮긴 이유 (0) | 2026.06.08 |
| Prometheus remote_write 큐가 막혀서 Thanos에 메트릭이 사라졌던 새벽 (0) | 2026.06.05 |
| OTel Collector에 memory_limiter 안 걸어서 OOM 무한루프 겪은 이야기 (0) | 2026.06.03 |
| Loki structured metadata, 이거 모르면 라벨 카디널리티로 계속 운다 (0) | 2026.06.02 |