Prometheus 告警规则写错的 9 种方式:从误报到漏报
监控系统的价值不在于采集了多少指标,而在于告警是否可信。一条天天误报的规则会让人关掉通知,然后真正的事故就漏了。这篇把 PromQL 告警规则里最常见的 9 类错误逐条拆开,每条给出错误写法、失效原因和修正版。
1. 用 rate() 却不配 for
只要有一个 5xx 就触发,然后立刻恢复,告警风暴。for 表示"持续满足条件多久才真正告警"。所有基于 rate/increase 的规则都应该配 for。
2. rate 窗口小于抓取间隔
rate() 至少需要 2 个样本才能算,窗口小于 2 倍抓取间隔时会返回空。规则:[窗口] ≥ 4 × scrape_interval。抓取 15s → 窗口至少 60s。
3. 用 rate() 统计绝对值
rate() 返回的是每秒速率,不是总数。想看 5 分钟总请求数应该用 increase()。
4. 计数器用了 gauge 的聚合方式
http_requests_total 是 Counter(单调递增),对它求 avg 没有意义。Counter 必须先 rate() 再聚合。
5. 分母没有保护,除零导致 NaN
没有流量时分母为 0,结果是 NaN,比较运算返回 false,告警不触发——恰恰在最该报警的时候静默。必须加最低流量门槛。
6. absent() 用错位置
absent() 判断的是标签组合不存在,up == 1 已经过滤了不存在的序列。正确写法是 absent(up{job="api"}) 或 up{job="api"} == 0。前者是抓取不到,后者是健康检查失败,生产环境两个都要有。
7. 聚合丢掉了关键标签
告警触发后不知道是哪台机器。用 sum by (instance) 保留定位维度。告警信息里必须包含"去哪里看"的标签。
8. 用 > 判断应该用 < 的指标
所有"剩余/可用/健康"类指标都是低于阈值告警,"使用/错误/延迟"类才是高于阈值。
9. 多个条件用 and 但没处理空向量
and 要求两侧标签集完全匹配才能保留。如果两侧标签维度不同,结果为空。用 on(instance) 显式指定匹配维度。
一条规则的自检清单
| 检查项 | 问法 |
|---|---|
| 触发条件 | 正常状态下会返回什么?空?0?NaN? |
| 持续时间 | 有没有配 for?瞬时抖动会触发吗? |
| 窗口大小 | [窗口] ≥ 4 × scrape_interval? |
| 指标类型 | Counter 用了 rate/increase?Gauge 用了直接比较? |
| 分母保护 | 除法的分母可能为 0 吗? |
| 定位信息 | 告警内容里有 instance/pod 这类可定位标签吗? |
分级策略
不是所有告警都值得半夜叫醒人。P1 服务不可用立即电话(for 1m),P2 用户体验受损工作时间处理(for 10m),P3 趋势性问题周报里看(for 1h)。
predict_linear 很实用:它做线性回归预测,能在磁盘真满之前 4 天就告警,而不是等 95% 才报。
小结
9 类错误的共同点:表达式在语法上合法,在语义上错误。PromQL 不会因为逻辑错就报错,它只会返回一个看起来正常但没意义的结果。
真正有效的做法不是记住这 9 条,而是每写一条规则就问一遍"它在正常状态下返回什么"。如果答案是"空"或"NaN",这条规则大概率不会按预期工作。
- 点赞
- 收藏
- 关注作者
评论(0)