准确的告警堆多了就变成不准确的告警
一句话总结
告警的质量不是用准确度来衡量,而是用可操作性来衡量。每次响起都没有人可做的事的告警,即使每一条都准确,整体上也是在说谎。
为什么需要它
增加告警是件容易的事。每次出事故,都会冒出一个“要是早知道这个就好了”的指标,给这个指标设上阈值,下次会议就有话可说了。这样过了一年,规则文件里就积累了 80 条告警。
问题在于之后。夜班值班人员的手机夜里响了二十次,其中十九次到早上一看什么事也没有。人是会学习的——从此以后,看到通知也不会马上起床。而第二十一次,真正的故障,以同样的声音到来。
这就是告警疲劳。无论怎样提高单条告警的准确度,都解决不了,因为问题在于呼叫的总量。Google SRE Book 就此写道:“监控系统的输出必须是人能够承受的。”能否承受,不是由每条规则决定,而是由总和决定。
工作原理
解决办法的骨架有两点。
第一,按症状告警,按原因调查。 用户遭遇的事情——请求失败、缓慢、结果错误——只有几种。而产生这些症状的原因却有几十种。如果为每个原因都设告警,就会产生几十个呼叫,而给症状设告警,则会减少到几个。原因指标不是要取消,而是要下放到仪表板和调查工具中。人被叫醒之后去看的东西,和把人叫醒的东西,是不同的位置。
第二,给告警加上持续时间。 如果条件一旦为真就立刻响起,瞬间跳动的值就会直接变成呼叫。把 for 设为 5 分钟,就只有保持了 5 分钟以上的才会响起。光靠这一个旋钮,呼叫数量就常常下降到个位数——不过检测也会相应变慢,而能慢到什么程度,由错误预算来回答。
选择告警时要问的问题可以归结为一个:收到这条通知的人,现在有没有能做的事? 如果没有,那它就不是呼叫,而是工单或仪表板面板。
| 性质 | 发送到 | 示例 |
|---|---|---|
| 现在就需要人介入 | 呼叫(page) | 用户请求的错误比例正在超过目标 |
| 本周之内处理即可 | 工单 | 6 小时后磁盘会满 |
| 调查时查看 | 仪表板 | p99 延迟、队列深度、各实例的 CPU |
还有些地方,光靠持续时间是不够的。如果等条件保持 5 分钟,小事故会被漏掉,大事故会知道得太晚。所以基于 SLO 的告警,不使用持续时间,而是使用消耗速度——同时用短窗口和长窗口来看,按当前速度消耗预算有多快,只有两者同时超过时才会响起。结构是:短窗口负责快速检测,长窗口负责去除噪声。
最好为告警设置预算。比如承诺“一个人一周收到的呼叫不超过两次”。有了预算,每次增加新告警时,都会一并问一句“要去掉什么”,这个问题会减慢规则文件增长的速度。超出预算时,答案往往不是修改规则,而是修复系统——经常响起的告警,通常是在如实告知经常发生的故障。
并且要对每条告警强制两件事。一是运行手册链接。在凌晨三点收到从没见过的告警的人,必须能通过这一个链接知道该确认什么、该回退什么。另一件是所有者。没有人负责的告警,没有人能删除,所以会永远留着。每个季度召开一次告警复盘,把“过去 90 天内一次都没有响起,或者响了却没有采取任何措施的告警”列成清单并删除,这样的团队能让规则文件保持精简。
在现场相遇的样子
某个团队的规则文件里有一条“请求数比平时少”的告警。本意是好的——流量中断可能就是故障。但凌晨本来流量就少。那条告警在 12 小时中有 609 分钟为真,也就是接近一半的时间,值班人员已经建了过滤器,自动忽略这条通知。它不只是可有可无,更有害的是培养了建过滤器的习惯。
还有相反方向的案例。p99 延迟超过 0.5 秒就响起的告警,因为没有持续时间,12 小时内响了六十五次。加上 for: 5m 后变成八次,for: 15m 时变成一次。规则的条件一个字符都没有改变。改变的只是团队对“要持续多久才值得把人叫醒”的共识。
下一项实验要做什么
把四条基于原因的告警写成规则文件,并制作一个工具,针对已回填的 12 小时数据,亲手统计每条各会响起多少次。把持续时间分别改成 0 分钟、5 分钟、15 分钟,测量呼叫数量如何减少,并与一条基于症状的告警比较。然后统计原因告警响起的时间中,用户没有遭遇任何事情的时间有多少分钟,以这个数字为依据,用表格决定哪些保留为呼叫、哪些下放,最后单独制作只含呼叫规则的文件并通过检查。