absent_over_time, 이거 모르는 분 꽤 많더라
문제 상황
오늘 알게 된 건 아니고, 최근에 신규 팀원한테 알림 튜닝 인수인계하다가 "이 함수 처음 봐요"라는 말을 들었다. 생각해 보니 나도 예전에 absent()랑 헷갈려서 쓰다가 알람을 놓친 적이 있었다. 짧게 정리해 둔다.
Prometheus 알림 대부분은 "값이 얼마 이상이면 발동"이다. 근데 실제 사고는 오히려 "메트릭 자체가 안 오는" 순간에 터진다. exporter 프로세스가 죽었거나, 파드가 재시작되면서 라벨이 살짝 바뀌었거나, scrape job이 config reload 때 조용히 빠졌거나.
이럴 때 up == 0만 걸어두면 반쯤은 놓친다. up은 scrape target이 등록돼 있어야 값이 있는 거고, target이 아예 discovery에서 사라지면 up{job="X"} 시리즈 자체가 증발한다. 알람 규칙이 그 시리즈를 참조하고 있으면 그냥 조용해진다.
우리 팀에서는 이걸 몇 번 겪고 나서, 중요한 잡은 다 absent_over_time으로 이중 커버한다.
코드
# 예: node_exporter의 node_load1이 5분간 한 번도 안 들어오면 발동
absent_over_time(node_load1{job="node-exporter"}[5m])
absent()도 있지만, 얘는 딱 지금 이 순간만 본다. scrape 간격이 30초쯤이고 순간적으로 한두 번 튀는 걸 무시하려면 absent_over_time이 훨씬 안정적이다. [5m] 범위 안에서 시리즈가 한 번이라도 관측되면 벡터가 비어서 알람이 안 뜬다.
alert rule로 쓰면 이런 모양:
- alert: NodeExporterMissing
expr: absent_over_time(node_load1{job="node-exporter"}[10m]) == 1
for: 5m
labels:
severity: warning
annotations:
summary: "node-exporter metric 10분간 유실"
for: 5m을 붙이는 이유는 rollout이나 재시작 중에 잠깐 비는 걸 참는 용도. 10분 룩백 + 5분 pending이면 대략 15분 안에는 알림이 뜬다. 우리는 이 정도 지연은 감수한다.
주의
라벨 매칭이 살짝 함정이다. absent_over_time(node_load1[10m]) 이렇게 라벨 없이 쓰면 "어떤 인스턴스든 하나라도 있으면 OK"가 된다. 특정 인스턴스가 죽어도 다른 인스턴스가 살아 있으면 벡터가 안 비어서 안 잡힌다. 그래서 노드 단위로 잡고 싶으면 for by (instance) 같은 걸 못 쓰는 대신, 라벨을 명시적으로 걸거나 target별 규칙을 따로 만들어야 한다.
이거 최근에 Prometheus 3 쓰면서 UTF-8 라벨 이름 처리가 바뀐 뒤로도 그대로 동작하긴 하는데, 라벨 값에 특수문자 들어가는 경우엔 quoted matcher 문법으로 다시 써야 한다.
혹시 SLO 대시보드에 "메트릭 존재 여부" 자체를 시각화하고 싶은 팀이 있다면 이 함수 결과를 recording rule로 뽑아서 stat panel에 얹으면 꽤 유용하다.