把错误预算算成数字
目标
在真实的 Prometheus 中观察最近的错误速度,并用另外提供的合成 30 天汇总制作功能发布判定程序。区分消耗速度与周期使用量、冻结与数据不足。
为什么重要
把 12 小时错误率除以允许错误率得到的值,是 12 小时 burn rate。仅凭这一个值,不能断定 30 天预算已经用完。在没有观测的时候用 0 来代替,也不是安全的判断。要先确认真实数据的单位和范围,再把明确的策略用代码执行出来。
预计需要 75 分钟。在默认的 60 分钟会话结束之前,用+时间延长(最长 180 分钟)。会话结束时 /root/obs 中的文件会消失,所以请另外保存需要的代码。Python 条件语句、字典和 JSON 输入输出是前置知识。
步骤
- 把以 5xx 为唯一失败的合成服务的成功比率 SLI 写入 /root/obs/slo-01-sli.promql。汇总最近 1 小时的 rate,求出成功请求/全部请求。不要把这个定义推广到其他服务的 4xx。
- 计算基于时间的 99.9% SLO 在 30 天内的允许不可用时间(以分钟为单位),只把数字写入 /root/obs/slo-02-budget.txt。不要换算成请求错误次数。
- 把最近 12 小时错误率除以 0.001 得到的 burn rate 查询写入 /root/obs/slo-03-consumed.promql。文件名是为了兼容以前的实验而保留的,但其值并不是月度使用量。
- 把最近 1 小时 burn rate 的查询写入 /root/obs/slo-04-burn1h.promql。它的窗口长度与第 3 步不同,两者都是速度指标。
- 用 and 连接“1 小时和 5 分钟的 burn rate 各自超过 14.4”的条件,写入 /root/obs/slo-05-multi.promql。不要忽略已经恢复的短窗口。
- 在 /etc/prometheus/rules/slo.yml 中编写名为 ErrorBudgetBurnFast 的多窗口告警规则。包含 alert、expr、for、labels.severity、annotations.summary,并用 promtool check rules 检查。告警的传递与功能发布的允许策略是两回事。
- 重新加载 Prometheus 之后,通过规则 API 确认告警已经登记。仅凭已登记这一事实,并不能证明它真正触发过,也不能证明生产环境中的响应已经得到验证。
- 阅读 /opt/lab/slo_release/contract.md,并完成 /root/obs/slo-gate.py。根据 stdin 中的一个合成观测 JSON,计算周期预算使用比例和两个窗口的 burn rate。数据不充分为 hold,预算使用比例达到 1 以上为 freeze,除此之外两个窗口都超过 14.4 也为 freeze,其余为 allow。输出是 decision、reason、budget_used、burn_hour、burn_five_minutes 五个字段,退出码为 allow=0、freeze=2、hold=3。数据检查的顺序和详细的 reason,遵循执行契约。
参考
- 起始文件:/opt/lab/slo_release/starter.py。如果没有,就在 mkdir -p /root/obs 之后复制为 slo-gate.py。
- 查看输入:python3 /opt/lab/slo_release/evaluate.py sample healthy
- 完整验证:python3 /opt/lab/slo_release/evaluate.py check /root/obs/slo-gate.py
- 第 5、6 步的时间序列检查说明:/opt/lab/slo_release/promql.md。假条件必须返回空向量,而不是值为 0 的元素,告警才会熄灭。
- Prometheus 中约 12 小时的合成历史,与程序输入的 30 天合成汇总,是不同的数据。它们不是真实的生产记录。
- 没有数据时,数字是 null 而不是 0。月度比例 20% 是 0.2,而不是 20。
- 程序不会连接外部服务,也不会执行真正的发布或回滚。allow 只是通过了这套合成策略,并不是对生产安全的保证。
用查询定义 SLI
成功比率 SLI → /root/obs/slo-01-sli.promql
这个合成服务只把观测到的 5xx 算作失败。用成功请求的 rate 之和除以全部 rate 之和。不要把其他服务的 4xx 无条件归类为成功。
把 30 天错误预算换算成分钟
基于时间的 30 天预算(分钟)→ /root/obs/slo-02-budget.txt
这是基于时间的 99.9% SLO。用 30 天的分钟数乘以允许不可用比例,写到小数点后一位。不要与请求次数预算混淆。
观察 12 小时的消耗速度
观察 12 小时消耗速度 → /root/obs/slo-03-consumed.promql
用 12 小时错误率除以允许错误比例 0.001。超过 1 表示该窗口的速度比允许的速度更快,并不表示 30 天预算已经全部用完。
观察 1 小时的消耗速度
观察 1 小时消耗速度 → /root/obs/slo-04-burn1h.promql
用同样的错误定义,把窗口换成 1h。长窗口和短窗口都是 burn rate,要与预算使用量区分开来。
多窗口条件
多窗口条件 → /root/obs/slo-05-multi.promql
用 and 连接“1 小时和 5 分钟各自超过 14.4”的条件。必须去掉为假的元素。bool 比较得到的 0 也可能让告警亮起。请用 /opt/lab/slo_release/promql.md 中的时间序列检查来确认恢复和缺失。
编写告警规则
ErrorBudgetBurnFast 多窗口告警规则 → /etc/prometheus/rules/slo.yml
请包含 alert、expr、for、labels.severity、annotations.summary。for: 0s 表示不额外等待持续时间,直接评估两个窗口的条件。过长的 for 可能连严重故障的告警也一并延迟。
确认规则已登记
确认 ErrorBudgetBurnFast 规则已在 Prometheus 中登记
配置检查之后重新加载,并在 rules API 中确认名称。即使是 inactive,登记确认也能通过,但它并不能代替真实触发和告警传递的测试。
用代码验证发布判定
判定程序 → /root/obs/slo-gate.py
请先实现执行契约中的数据检查。把月度预算超支、最近两个窗口的故障、未确认的数据,分别以不同的原因和退出码留下来。