【运维】凌晨三点被 PagerDuty 叫醒,却发现 CPU 才 40%:SLO 怎么救我的睡眠
那个「CPU 85% 告警」的夜晚
去年某次 on-call,PagerDuty 在凌晨 3:12 把我震醒。
打开 Grafana:CPU 85%,内存 70%,错误率 0.01%,P99 延迟比平时高了 40ms。
15 分钟后曲线自己回落,没有任何用户投诉,也没有任何 action item。
第二天 standup 的结论却是:「还好没出事。」
不对。真正出事的,是 我们对「什么叫出事」没有共同语言——告警阈值是拍脑袋的,SLO 是 PPT 里的,on-call 是真人当传感器。
2026 年,云原生工具链(K8s、Prometheus、OpenTelemetry、Grafana Cloud……)很多团队都有了,缺的不是 dashboard,而是 error budget 文化。
从 SLI 到 SLO:先量「用户感受到的」
| 概念 | 例子 |
|---|---|
| SLI(指标) | 成功请求占比、P99 延迟 < 500ms 的占比 |
| SLO(目标) | 30 天内可用性 ≥ 99.9% |
| Error Budget | 允许失败的那 0.1% = 约 43 分钟/月 |
关键转变:告警不应绑「CPU > 80%」,而应绑 「error budget burn rate 过快」。
Google SRE 经典做法:
- 快速 burn(1h 内烧完一月 budget)→ 立即 page
- 慢速 burn(6h 内)→ ticket,白天处理
CPU 高但 SLO 仍健康?不是 page 级事件,最多记一条 info。
云原生栈里怎么落地(不玄学版)
1. 指标:Prometheus + Recording Rules
# 简化:30 天可用性 SLI
sum(rate(http_requests_total{status!~"5.."}[30d]))
/
sum(rate(http_requests_total[30d]))
用 Recording Rule 预聚合,告警查 slo:availability:30d,别每次现算。
2. 追踪:OpenTelemetry 一条链路打穿
Ingress → Service → DB,一个 trace_id 串起来。
否则 P99 涨了,只能在三个 dashboard 之间猜。
2026 年 OTel 已是事实标准,新接入尽量 SDK 直出 OTLP,别再造 JSON log 解析轮子。
3. 日志:结构化 + 采样
全量 JSON 日志进 Loki/Elastic 很贵。
错误 100% 留,成功请求按 1% 采样,够排障,账单腰斩。
4. K8s:资源 request/limit 是 SLO 的隐形队友
CPU throttle 导致的 latency 抖动,在应用层看像「神秘毛刺」。
定期跑 vertical-rightsizing 报告,比盲目 HPA 扩容更有效。
GitOps:改集群不再 SSH
kubectl edit 适合救火,不适合日常。
Argo CD / Flux 把集群状态绑 Git 仓库:
- 谁改了什么 →
git log - 回滚 →
git revert - 漂移检测 → 自动 sync 或 alert
Platform 团队 2026 年的 KPI,往往是 「生产变更有 PR、有 review、可审计」,而不是「我能背 50 个 kubectl 命令」。
我们现在的 on-call 守则(精简版)
- Page 必须关联 SLO 或明确安全事件,禁止裸资源阈值 page
- 每个 page 必须有 runbook 链接,没有 runbook 的告警删掉
- 事后写 blameless postmortem,但 error budget Consumed 要进周报
- 非生产环境不许复制生产的告警规则——测试集群 CPU 90% 是常态
- On-call 轮值不超过 7 天, burnout 也是可用性风险
结语
云原生的终点不是「全上 K8s」,而是 变更可预测、故障可度量、值班有尊严。
当你下次想加一条「内存 > 75% 就打电话」的规则时,先问:这对应哪条 SLO?烧的是谁的 error budget?
如果答不上来,那条告警可能只是在训练人 ignore PagerDuty。
你们团队的 SLO 写在哪?Git 里还是 Confluence 吃灰?欢迎交流。