LabHub
学习 学习路径 课程

SLO — 定下能坏到什么程度

用燃烧率来挂告警

在 LabHub 中继续学习

一句话总结

使用 burn rate 设置告警后,该响时会响,该安静时也能保持安静。

概念图: 该响时会响,该安静时也能保持安静。 · 十倍 · 一次错误部署就可能全部耗尽 · 允许消耗的份额

99.9% 意味着每月 43 分钟

SLO 每月(30 天)允许时间
99% 7.2 小时
99.9% 43.2 分钟
99.95% 21.6 分钟
99.99% 4.32 分钟

99.9 和 99.99 在写法上只差一位,要求却相差十倍。在合同中写下 99.99% 之前必须先看这张表——每月只有 4 分钟,一次错误部署就可能全部耗尽

错误预算就是用来消耗的

如果目标是 99.9%,那么 0.1% 就是允许消耗的份额。完全不使用并不代表做得好——预算始终有剩余,说明目标太低,或部署过于保守。

这正是 SLO 的核心视角:不追求完美,而是约定最多允许出现多少故障

Burn rate

错误率是允许值的多少倍,称为 burn rate。

数字 14.4 的来源如下——它表示一小时内消耗一个月预算的 2%

0.02 × 30일 × 24시간 = 14.4

以这种速度消耗,就应该立刻叫醒值班人员。反之,如果只有 2 倍左右,创建工单就足够。

为什么当前告警毫无用处

看看一条常见规则。

5분 오류율 > 1%

SLO 为 99.9%,允许错误率是 0.1%,但这条规则并非由该目标推导而来。因此会同时发生两种问题。

告警疲劳并非因为告警数量多,而是因为无用告警太多

改用 burn rate 表达

오류율 > 14.4 × (1 - SLO)

SLO 为 99.9% 时,阈值是 0.0144(1.44%)。单看数字似乎很接近,但含义完全不同——它表示“正在以每小时消耗预算 2% 的速度燃烧”,因此也明确了应该采取什么行动

告警名称也要改变。不要叫 HighErrorRate,而要叫 ErrorBudgetBurnFast名称会决定响应方式。

只有一个窗口并不够

因此,要用 and 连接二者。只有短窗口与长窗口同时超过阈值,才触发告警。这样既能过滤瞬时尖峰,也能快速发现真实消耗。

还要区分严重程度。

Burn rate 窗口 响应
14.4 5 分钟 + 1 小时 立即呼叫
6 30 分钟 + 6 小时 立即呼叫
3 2 小时 + 1 天 工单
1 6 小时 + 3 天 工单

应该用什么衡量 SLI

计算 burn rate 只是算术。在此之前,如果没有定义什么才算成功,数字就毫无意义。这里需要作出三类选择。

在哪里测量。 在服务器日志中测量,看不到负载均衡器中断的请求;在负载均衡器测量,看不到客户端的 DNS 或 TLS 失败。测量点越接近用户体验越好,但也会混入更多我们无法控制的失败。生产环境中,常见的实用组合是以负载均衡器为基础,再用外部运行的合成监控作为补充

哪些情况算失败。 5xx 很明确,4xx 则比较模糊。400 通常是客户端错误,可以排除;429 是由我们主动阻断,因此应计入。如果排除 404,就可能错过路由损坏、所有请求都变成 404 的事故。定义必须写入文档;修改定义时,也要同时重新计算历史数据。

慢响应也算失败。 花费 30 秒才成功的响应,对用户而言就是失败。因此,延迟 SLI 不应使用平均值,而应采用在阈值时间内完成的请求比例。与其写“95% 的请求在 300ms 内完成”,不如写“300ms 内完成的请求比例为 99%”,这样就能像可用性一样计算预算。

sum(rate(http_request_duration_seconds_bucket{le="0.3",job="api"}[5m]))
/
sum(rate(http_request_duration_seconds_count{job="api"}[5m]))

不能把所有请求视为相同权重。 如果健康检查和机器人流量占分母的一半,用户经历的失败几乎不会体现在数字中。反过来,如果某个批处理 API 每秒发送数千个请求,一个客户端就会主导整个 SLI。答案是按用户旅程分别测量,但这样做有成本;至少应单独测量一条核心路径。

SLO 不是合同,而是决策工具。 必须先约定:预算有余量时可以进行风险较高的变更,耗尽后则集中精力稳定系统。如果没有这项共识,单纯测量数字,只会在事故后成为争论材料。

告警也必须测试

这是最常遗漏的部分。promtool 支持告警规则的单元测试

promtool test rules test.yml

输入模拟时间序列,并断言“此时这条告警应该触发”。如果没有测试,就可能部署一条事故发生时反而不响的告警——而且只能在事故中才发现。

还要测试不该触发时是否保持安静exp_alerts: [])。只测试应该响的情况,只完成了一半。

预算耗尽后怎么办

如果没有这个问题的答案,SLO 就只是装饰。

应提前约定:

相比确定数字,达成这项共识更困难;没有共识,数字就不会带来任何行动。

在实际工作中

引入这种方法时,最先遇到的不是技术问题,而是共识问题。写下 99.9% 很容易,但要提前确定预算只剩一半时应该停止什么,就必须与产品团队沟通,而这类对话通常并不轻松。

因此,初期最好先设置一段只观察、不触发告警的时期。观察一两个月的实际消耗曲线后,就能看出 99.9% 是否适合服务,还是即使只有 99.5% 也不会有人抱怨。如果设定无法实现的数字,预算每个月第一周就会耗尽,最终所有人都会停止关注它。

此外,使用什么衡量 SLI 是一个比想象中更重大的决定。在负载均衡器侧测量时,即使应用程序宕机也会记录为 5xx,但看不到客户端侧失败;在应用程序侧测量时则正好相反。只需在文档中写明测量位置,就能大幅减少日后围绕数字产生的争论。