监控告警总是吵个不停?我干脆把阈值全删了
先说说我的黑历史。三年前我负责一个K8s集群,线上有二十多个业务服务,当时我们用了很标准的Prometheus配置:CPU使用率超过80%告警,内存超过85%告警,磁盘超过90%告警,然后再挂上Alertmanager。结果呢?第一天晚上就收了300多条通知,大部分是某个大数据作业瞬间把节点CPU拉高到82%,三秒后又掉回30%。值班同事半夜爬起来看一眼,发现没事,爬回去睡觉。第二周,大家开始习惯性忽略所有告警,包括一个真正的磁盘IO故障。后来那个故障拖了四个小时,用户都开始骂了,我们才从工单里发现。那次事故之后,我干了一件事:把所有基于百分比阈值的告警规则全部删了。一个不留。
你可能会说,疯了吧?但我想明白了一个道理:监控和告警根本是两回事。监控是观察,告警是决策。传统做法是先设定一个僵硬的数字,比如CPU超过90%,然后就认为这是一个异常。但90%对某个批处理任务来说可能是常态,对另一个实时服务来说却可能意味着即将不可用。同样的阈值,放在白天和凌晨,意义完全不同。真正有价值的告警不是告诉你“哪个指标越界了”,而是告诉你“某个用户场景正在变糟,需要你动手处理”。比如“每天的订单导出任务失败了三次”比“Redis内存用了87.4%”有用得多。前者是一个明确的事件,后者只是一个难以推断后果的状态。所以我后来把所有告警都改成了基于事件、基于日志特征、基于错误率趋势的检测,全部删光了基于CPU和内存固定百分比的规则。
有人会问:那资源不足怎么办?不是还有红线吗?我的做法是,资源指标不做告警,只做展示和容量分析。真正的负责调度的人看的是Grafana图上的趋势线,而不是手机上一条“CPU Usage 92%”的垃圾通知。容量管理是一个需要观察时间跨度的活,把几秒钟的波动变成alert,等于把不稳定性送给值班的真人。真正需要人脑决策的,其实很少。我在那之后定了一条原则:一个系统如果每个小时产生超过两条由人类处理的告警,那这个系统设计就是失败的——要么自动化没有做到位,要么是告警规则本身模糊。比如我们现在对支付回调的监控,只设了一个规则:连续五分钟失败率超过正常值的五倍且总失败次数超过10次才触发。没有再多的指标了。一旦触发,消息里直接带上最近20笔失败请求的trace ID和日志片段。值班人员直接看图,不用再登录机器查一遍。自从这样搞,我们整个平台的告警量从每天平均150+变成每天不到15条,而且每一条几乎都值得打开看。
当然,这个方法需要付出的代价是,你不能再照着网上那堆现成的告警模板去抄了。每一个服务的健康边界都不同,你得自己重新去梳理它的行为模式。我花了很多时间去看历史出事故的时间窗口:那段时间前后日志里都出现了什么?错误码分布如何?哪个调用下游变慢了?把这些特征转成可检测的条件。这个过程很痛苦,但很有回报。而且说真的,现在很多所谓智能告警平台,用机器学习去过滤噪声,我试用过几个,仍然免不了要人去定义“什么是正常”。那还不如一开始就让告警规则回答一个更基本的问题:这条通知到达人类手里时,人要做的那一个决定是什么?如果回答不出,那这条告警就不该存在。用我同事的话说,别让告警系统用战术上的忙碌来掩盖战略上的懒惰。