LabHub
学习 学习路径 课程

可观测性

有些告警很准,却有害

在 LabHub 中继续学习

一句话总结

告警的成功标准不是“是否检测到问题”,而是“现在是否需要人采取行动”。无法通过这一标准的告警,即使判断准确,也会造成伤害。

概念图: 哪里出了问题,并使用用户语言描述。 · 问题有多严重。 · 从何时开始。 · 发生在哪里。

为什么需要它

每次发生事故就增加一条规则,两年后规则会达到 300 条,Slack 每天堆积 400 条消息。值班人员夜里被叫醒三次,三次都什么也没做就重新睡下。每天 400 条告警中,只有 4 条最终引发实际行动,精确率只有 1%。

在这种状态下,人学到的最优策略是“先忽略,之后再看”。正因为这种策略很合理,情况才更加危险。增加一条告警无法解决问题。

它如何运作

原则只有一个:只针对用户实际感受到的症状进行呼叫。CPU 达到 90% 不是症状。如果 CPU 为 90%,响应时间却正常,那么什么事故都没有发生;如果 CPU 只有 40%,响应却每次耗时 5 秒,那就是严重事故。针对原因指标发出呼叫,会在这两种情况下都作出错误判断。

应该呼叫的指标:可用性、延迟(超过阈值的比例)、吞吐量骤降、新鲜度、正确性。不应呼叫的指标:CPU、内存、磁盘 IOPS、Pod 重启次数、线程池使用率、GC 时间、副本数量。只有两个例外:不可逆且需要提前处理的问题(磁盘剩余空间、证书过期、配额耗尽),以及观测系统自身故障(up == 0 or absent(up))。如果没有后一类告警,其余告警可能会悄无声息地全部失效。

阈值也必须能够解释。“错误率超过 5% 就告警”中的 5% 从何而来?大多数情况下,它没有任何依据。无法解释的阈值会在每次事故后被一点点调高。

for: 要求表达式持续为真达到指定时间后才触发;中间只要有一次变为假,计时器就会归零。因此,“误报太多,把 for 延长到 30 分钟”是一种反模式。检测会延迟 30 分钟,如果事故在 25 分钟内结束,告警甚至完全不会触发。正确顺序是:① 使用长窗口 rate 进行平滑;② 使用短窗口 AND 确认问题仍在持续;③ 最后只给 for 设置 2~5 分钟。

生产现场中的表现

路由只有三个等级:页面呼叫(现在必须醒来)、工单(工作时间处理)、监控面板(不创建告警)。不存在第四个等级。“先只发到 Slack 频道”是最糟糕的折中方案——没有人负责,也没有人会关闭它。

分组最常见的错误,是在 group_by 中加入 instance。这样会按 Pod 数量产生告警。如果 severity=page 却没有 runbook_url,CI 就应该让构建失败。凌晨 3 点被叫醒的人并不处于能够发挥创造力的状态。不过,只有链接、内容却为空的运行手册,比没有链接更糟。

目标应以数字明确规定:以 12 小时轮班为基准,平均页面呼叫不超过 2 次,页面呼叫转化为实际行动的比例至少达到 70%。一旦超过这两个数字,就不该继续增加告警,而应开始删除。连续 3 个月没有引发行动的页面呼叫应降级或删除;持续静默超过 30 天的告警也应删除。静默是“这条告警有问题”最诚实的信号。

一条告警中必须包含什么

凌晨 3 点被叫醒的人,首先看到的是屏幕上的一行告警标题。这一行和正文必须能引导下一步行动,因此告警中应包含固定项目。

还建议增加一项:提供一种方式记录**“该告警触发了,但无需采取任何行动”**。如果值班人员能当场点击一次留下记录,几周后就可以用数据判断哪些告警是噪声。这比复盘时依赖记忆争论,得出结论要快得多。

**创建告警时,必须同时确定删除它的条件。**增加规则时,如果同时写明“连续 3 个月没有引发行动就删除”,规则从一开始就不会增长到 300 条。规则容易增加,却很难删除,因此应在创建时就同时建立删除依据。

最后,还必须测试告警本身。编写规则后,要人为制造相应条件,确认它会真实触发;情况结束时,还要确认它会恢复。**无法恢复的告警,与无法触发的告警一样糟糕。**如果触发一次后永远保持红色,下次真正发生相同问题时,就不会有人察觉。

下一项实验要做什么

你将区分症状与原因,为告警规则填写必需字段,定义路由、抑制和分组,实际补全运行手册,最后亲自编写检查器,在 CI 中发现存在缺陷的规则。