刚接手运维工作那会儿,我犯过一个极其"经典"的错误:觉得监控覆盖率越高越好,于是把网上抄来的Prometheus规则一股脑全配上了。
结果就是,我的手机成了24小时震动的按摩棒。凌晨3点被"CPU使用率超过80%“的告警惊醒,爬起来一看,只是个定时备份任务在跑,两分钟后就自动恢复了。这种"狼来了"的故事发生几次后,我和团队对告警彻底麻木了,直到真正发生线上故障时,那条关键的报错信息淹没在了几百条无效告警里,导致我们晚了半小时才介入处理。
那时候我才明白:写告警规则不是填空题,而是一门关于"信噪比"的艺术。
很多兄弟在落地Prometheus时,往往只关注"能不能抓到指标”,却忽略了"这玩意儿到底该不该报"。今天咱们不聊虚的,我想结合这几年踩过的坑,聊聊怎么写出既精准又"不扰民"的高质量Prometheus规则。
一、 别让"抖动"骗了你:引入时间窗口与趋势预测
新手写规则最喜欢"直来直去"。比如监控磁盘,看到剩下10%就马上报警。这听起来没毛病,但在实际生产环境里,这种瞬时值的判断非常容易误报。
真实案例:
我们有个日志处理服务,每隔几小时会有一次短暂的数据写入洪峰,磁盘I/O和使用率会瞬间飙高,但很快就会被清理脚本释放。刚开始我们设置了node_filesystem_free_bytes < 10%就告警,结果运维群每天都要炸几次锅,大家查了一圈发现"没事啊",久而久之就没人看了。
避坑方法论: 告警的本质是呼叫人工介入。如果它能自己恢复,就不应该半夜叫醒你。我们需要引入持续时间(Duration)和趋势预测(Prediction)。
- 加个"for"缓冲: 只有当问题持续一段时间(比如5分钟)还没恢复,才算真问题。
- 看未来趋势: 与其盯着现在的剩余空间,不如算算"按照当前写入速度,多久之后会写满"。
优化后的规则示例:
groups:
- name: disk_alerts
rules:
# 只有当磁盘将在4小时内填满,且当前剩余空间确实小于10%时,才告警
# predict_linear 是个神技,利用过去1小时的数据预测未来
- alert: DiskWillFillIn4Hours
expr: predict_linear(node_filesystem_free_bytes[1h], 4 * 3600) < 0 and node_filesystem_free_bytes / node_filesystem_size_bytes < 0.1
for: 10m # 持续10分钟满足条件才触发
labels:
severity: warning
annotations:
summary: "磁盘将在4小时内耗尽"
description: " 的磁盘写入过快,预计4小时后写满,请检查日志量。"
自从换了这个规则,那个日志服务的无效告警直接归零。只有当清理脚本挂了,或者业务量暴增导致真要写满时,我们才会收到通知。这时候,每个人都知道:这条告警必须处理,不能滑过去。
二、 告别"资源焦虑":从RED方法论切入业务视角
很多团队的Prometheus规则里,90%都是CPU、内存、磁盘这些基础资源监控。
但我问你一个扎心的问题:如果CPU跑到了95%,但用户访问完全正常,这算故障吗? 反过来说,如果CPU只有10%,但用户下单全报500错误,这算故障吗?
显然后者才是我们要死磕的。过分关注底层资源,很容易陷入"资源焦虑"。作为开发和运维人员,我们的关注点应该从"机器活得好不好"转移到"服务干得行不行"。
真实案例: 有次大促,我们盯着仪表盘看CPU负载,一切平稳。结果客服炸了,说用户反馈无法支付。查了半天才发现,是下游支付网关的一个连接池配置错了,导致请求大量超时。因为等待超时不消耗CPU,所以资源监控全是绿的,但业务其实已经挂了。
落地框架:RED方法论 Weaveworks 提出的 RED 方法论非常适合微服务监控。我们在写规则时,优先覆盖这三个维度:
- R (Rate):请求速率(每秒多少请求?)
- E (Errors):错误率(有多少失败了?)
- D (Duration):响应时间(处理要多久?)
实操代码:
比起盯着CPU,我强烈建议你先配好这条关于"错误率"的黄金规则:
groups:
- name: service_level_alerts
rules:
# 5分钟内,如果错误率超过1%,立马告警
# sum(rate(...)) 是处理微服务聚合的标准姿势
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m])) > 0.01
for: 2m
labels:
severity: critical
annotations:
summary: "服务 错误率飙升"
description: "当前错误率已超过1%,请立即检查日志!"
这不仅能让你在业务受损的第一时间感知,还能帮你过滤掉那些"虽然CPU高但服务很健康"的无效焦虑。我现在的习惯是:凡是不能直接映射到用户体验的资源告警,等级全部设为 Warning,只有 RED 指标异常才设为 Critical 并触发电话通知。
三、 巧用"中间层":Recording Rules 拯救你的Prometheus
随着规则越写越多,你可能会发现Prometheus的查询变慢了,甚至有时候评估规则本身就让Prometheus OOM(内存溢出)了。
这通常是因为你在Alert规则里写了太多复杂的实时计算。比如,你要算全公司几千个实例过去7天的SLA(服务等级协议),如果在告警规则里直接跑这个查询,Prometheus大概率会原地去世。
踩坑经历: 我们曾试图在一个规则里计算"过去24小时API的P99响应时间",结果每到整点评估规则时,Prometheus就出现短暂的卡顿,数据断点频发。
解决方法:预计算(Recording Rules) 这就像编程里的"缓存"或者是数据库里的"物化视图"。先把复杂的查询算好,存成一个新的指标,告警的时候直接查这个新指标。
优化步骤:
- 定义中间指标: 先把复杂的聚合算出来。
groups:
- name: recording_rules
rules:
# 每分钟预计算一次,存成 job:http_inprogress_requests:sum
- record: job:http_inprogress_requests:sum
expr: sum by (job) (http_inprogress_requests)
- 基于中间指标告警:
- alert: HighRequestLoad
# 告警查询瞬间完成,不再消耗大量算力
expr: job:http_inprogress_requests:sum > 1000
for: 1m
我个人的经验是,只要你的PromQL里出现了3层以上的聚合操作(sum套rate再套predict),就应该考虑把它拆解成Recording Rules。 这不仅能救你的Prometheus一命,还能让你的告警规则看起来清爽得多,后期维护也容易。
结尾与行动建议
做监控这么多年,我最大的感悟是:最好的告警,是你收到它时,手心会出汗,而不是翻个白眼把它划掉。
自定义Prometheus规则不仅仅是写几行YAML配置,它倒逼着我们去理解业务的真实形态、理解系统的瓶颈所在。
如果你觉得现在的告警太吵,不妨在这个周五下午(我通常选这个时间做复盘),试着做这3个动作:
- 做一次"告警大扫除": 导出过去一周触发次数最多的Top 3告警,问问自己:这几条告警如果没发,系统会挂吗?如果不会,删了它或者调低等级。
- 落地一条RED规则: 挑一个核心服务,给它加上基于错误率(Errors)的告警,替代掉单纯的CPU告警。
- 加上
for参数: 检查所有现有的规则,凡是没有加for持续时间的,全部加上至少1分钟的缓冲。
你在配置Prometheus规则时,遇到过最离谱的误报是什么?或者你有什么独门的"降噪"技巧? 欢迎在评论区聊聊,咱们一起把监控做得更"丝滑"。