生产环境的监控与排障 — OpenTelemetry、Prometheus、告警与 Runbook¶
这一章把第 12 章的演示栈升级成生产回路。 第 12 章答"怎么看"; 本章答三个更硬的问题:埋点怎么标准化(OTel)、什么时候该吵醒人 (告警哲学 + 规则)、吵醒之后怎么办(runbook)。主线例子:orders-service 与 payments-service 两个服务,从埋点到告警到 runbook 全链路。
1. 可见性从埋点开始:OpenTelemetry¶
书里的立场很硬:如果服务发不出有意义的遥测数据,什么 dashboard 和告警 都讲不出真实故事1。早期微服务时代各用各的库(OpenTracing 管追踪、 OpenCensus 管指标),如今合并成 OpenTelemetry(OTel)——开源、厂商中立的 埋点标准,统一收 traces、metrics、logs。三个积木1:
| 积木 | 干什么 |
|---|---|
| Instrumentation 库 | 嵌进应用代码,自动抓 spans、时延、指标(常见框架开箱即用) |
| OpenTelemetry Collector | 接收、处理、导出遥测到各后端(Jaeger、Prometheus、云服务) |
| Exporters | 定义数据发给谁、怎么发 |
三段拼成一条管道:采集与存储/可视化解耦——换后端不用改应用1。
Trace 的概念正式化: 一次请求穿过分布式系统全程是一个 trace, 其中每个服务执行的一段是一个 span;trace 就是 span 的树, 带上时延和上下文传播。请求慢了,你能精确定位是哪个服务、哪个调用拖的2。
2. 采集与可视化:Prometheus + Grafana 上 K8s¶
指标的采集可视化仍是 Prometheus + Grafana 这对搭档(第 12 章单机版在
K8s 上以 observability 命名空间里的工作负载形式部署:Prometheus 抓指标、
Grafana 出 dashboard,还有现成的预定义 dashboard 可导入)3。
埋点侧的最佳实践(书里的专节)是五条:尽早埋点(开发初期就上,别等出问题)、
服务命名标准化(一致的命名才有可拼的 dashboard 和 trace)、记录业务上下文
(技术指标之外带上用户/交易标识)、指标与追踪关联(时延尖峰能跳到具体 span)、
优先 OTLP 导出(互操作性最好)4。落到代码上,时延用 histogram 记录
(orders_request_seconds / payments_request_seconds),后面 p95 告警的
histogram_quantile 就靠它的 bucket5。选指标的思路我们再补一条书外的:
RED 方法(速率/错误/时延)是微服务指标的常用最小集(补充,不在书里)。
3. 告警的哲学:先立规矩,再写规则¶
书里的告警观值得整段接住6:
告警只在该行动时吸引人注意。不是每个偏离基线的事都值得一条呼叫或 Slack 消息。最好的告警是预测性的,而不是反应性的——它预警的是"即将 影响用户的趋势",而不是"已经影响的既成事实"。
告警疲劳比漏掉一个事件更糟:太多噪音导致麻木,太少又留盲区。目标是平衡: 对真实用户痛点的症状告警,诊断交给 dashboard 和日志6。
三条准则6:
- 对症状告警,不对原因——用户在乎的是响应慢,不是哪个容器 CPU 满了;
- 明确归属——每条告警都要有负责处理的团队或个人;
- 带上上下文——好的告警消息直接附 dashboard 或 runbook 链接。
机制层面:告警就是定期求值的 PromQL 表达式,条件持续成立一段时间,
Prometheus 就触发告警。例子口径:error rate > 5% 持续 2 分钟、
p95 时延超过 1 秒6。
4. 告警规则与路由¶
规则写成 YAML,四条字段各司其职7:
groups:
- name: service_alerts
interval: 30s
rules:
- alert: HighErrorRate
expr: rate(orders_errors_total[2m]) / rate(orders_requests_total[2m]) > 0.05
for: 1m # 持续 1 分钟才触发(防抖动)
labels: { severity: warning, service: orders-service } # 路由用
annotations: # 给人看
summary: "High error rate in orders-service"
description: "Error rate above 5% for more than 1 minute."
- alert: HighLatency
expr: histogram_quantile(0.95, sum(rate(orders_request_seconds_bucket[2m])) by (le)) > 1
for: 1m
labels: { severity: critical, service: orders-service }
- alert: PaymentsLatency
expr: histogram_quantile(0.95, ...) > 0.8 # payments 阈值 800ms
expr求值的 PromQL;for条件要持续多久才算数(滤掉毛刺);labels(severity/service)给 Alertmanager 做路由;annotations是通知里给人读的话;- 规则文件经 ConfigMap 挂载进 Prometheus,
rule_files自动加载目录下 所有*.yml——规则可以和 Prometheus 二进制独立版本化、独立发布; 应用后访问 Prometheus 的/rules确认加载与求值状态7。
触发之后由 Alertmanager 接手路由:按 label 决定发给哪个团队、走邮件还是 Slack、要不要聚合与静默8。
5. Runbook:把信号变成操作¶
告警本身只是信号;让它有运营价值的是上下文——"接下来该做什么"的知识。 Runbook 就是那份文档:简洁、结构化,告诉值班的人(老手或新人)怎么排查、 怎么处置。 runbook 弥合"检出"与"解决"之间的缝9。
六要素(照单接住)9:
- 摘要(这条告警/问题是什么)
- 影响(对用户或系统意味着什么)
- 立即检查(确认或排除的第一步动作)
- 可能原因(这条告警常见的触发原因)
- 修复步骤(缓解与根治)
- 参考(dashboard、trace、相关文档链接)
书里给了两个完整样例。其一"orders-service 错误率高":影响=用户结账/支付失败; 立即检查=确认告警→打开 Orders & Payments dashboard 看量/时延/错误率面板→ 查 payments-service 是否也在报错;可能原因=两服务间网络问题、最近的部署 引入 bug、数据库或外部 API 超时;修复=查日志找堆栈→是部署引入的就回滚→ 偶发则重启 Pod→缓解后在 dashboard 验证恢复;参考=Grafana dashboard + Jaeger trace10。
6. 两系告警的分工与运营纪律¶
Prometheus 告警 vs Grafana 告警的对照(书里表 18.1 的要点)11:
| 维度 | Prometheus + Alertmanager | Grafana Unified Alerting |
|---|---|---|
| 定义 | YAML 规则文件 | 可视化/声明式(界面里) |
| 范围 | 全部指标,全局 | 通常按 dashboard 或团队 |
| 路由 | Alertmanager 集中路由 | Grafana 内联系点 |
| 场景 | 生产级告警 | dashboard 级/实验性告警 |
实践上很多团队两者并用:关键告警走 Prometheus(要版本化),辅助性、 提升态势感知的走 Grafana11。
收尾的运营纪律(书末,态度鲜明)12:
好的可观测性设置不是永远不变的,而是被定期审查、测试和打磨的。 把告警和 runbook 当作应用的活组件对待,而不是静态文档。
具体两条习惯:每次事故复盘都问"检出够不够早、告警里上下文够不够"; 定期故意触发测试告警、做受控故障演练——让告警通道和 runbook 在真出事前 就被验证过12。
7. 作者的判断与证据¶
- "对症状不对原因"是 Google SRE 系的核心告警哲学,书里与"告警疲劳" 的权衡一起给出,论证完整6。
for字段防抖动、labels路由、annotations给人看——字段级分工 是实操细节,可信7。- Runbook 六要素 + 两个成例是本章最可直接搬用的部分,结构本身就是 检查表910。
- Prometheus 管关键告警、Grafana 管辅助告警的分工建议符合行业常见实践, 但属于经验之谈,非定论11。
判断(我们的,不是书里的): 本章其实讲的是"自动化的最后一里": 编排器(14–17 章)解决了"系统自己恢复",本章解决"恢复不了时人怎么接管"。 而 runbook 文化的深层含义是把个人排障经验组织化—— 没有 runbook 的团队,告警只是叫醒一个人;有了 runbook,叫醒的是一套 被验证过的集体记忆。AI 运维(第 19 章)接的正是这个位置的下一站。 如果错,会错在: runbook 在AI agent 能自动排障的未来可能贬值为 "训练材料";但"症状告警 + 明确归属 + 上下文"的告警设计原则, 对人和 AI 接收者同样成立——那一层不会过时。
8. 边界与局限¶
- 本章示例的 Prometheus/Grafana 部署在 K8s 上,但对告警哲学与 runbook 的讨论平台无关——这是好事。
- 没有覆盖:SLO/错误预算的定量框架(只出现 p95 等概念)、on-call 轮值 制度、事故指挥体系(incident command)。
- 通知渠道(邮件/Slack/PagerDuty 的具体配置)一带而过,以 Alertmanager 路由概念为主。
- PromQL 的具体函数(rate/histogram_quantile)只到示例级,系统学习要查 Prometheus 官方文档。
9. 可带走的¶
- 可见性从埋点开始;OTel 三积木:库、Collector、exporters——采集与后端解耦1。
- trace = span 的树;慢请求定位到具体服务/调用2。
- 时延用 histogram 记,p95 告警靠 bucket5。
- 对症状告警不对原因;告警疲劳比漏报更糟6。
- 规则四字段:
expr/for(防抖动)/labels(路由)/annotations(给人)7。 - 规则走 ConfigMap +
rule_files,与 Prometheus 独立版本化7。 - runbook 六要素:摘要/影响/立即检查/可能原因/修复/参考9。
- 关键告警 Prometheus、辅助告警 Grafana,两者并用11。
- 告警和 runbook 是活组件:事故后复盘、定期演练12。
10. 原文地图¶
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 埋点是起点 | Technical requirements | text/198-fm-technical-requirements.txt:36(搜「Instrumenting」) · text/198-fm-technical-requirements.txt:40(搜「real story」) |
| OTel 三积木 | Technical requirements | text/198-fm-technical-requirements.txt:43(搜「OpenTracing」) · text/198-fm-technical-requirements.txt:46(搜「three key building blocks」) · text/198-fm-technical-requirements.txt:51(搜「Collector」) · text/198-fm-technical-requirements.txt:55(搜「Exporters」) |
| trace/span 定义 | Technical requirements | text/198-fm-technical-requirements.txt:59(搜「distributed tracing」) · text/198-fm-technical-requirements.txt:63(搜「tree of spans」) |
| 指标采集可视化节 | Collecting and visualizing metrics with Prometheus and Grafana | text/199-fm-collecting-and-visualizing-metrics-with-promethe.txt:29(搜「Collecting and visualizing」) · text/199-fm-collecting-and-visualizing-metrics-with-promethe.txt:9(搜「Best practices」) |
| 告警哲学三准则 | Defining alerts and runbooks | text/200-fm-defining-alerts-and-runbooks.txt:45(搜「purpose of alerts」) · text/200-fm-defining-alerts-and-runbooks.txt:49(搜「predictive」) · text/200-fm-defining-alerts-and-runbooks.txt:55(搜「alert fatigue」) · text/200-fm-defining-alerts-and-runbooks.txt:60(搜「symptoms」) · text/200-fm-defining-alerts-and-runbooks.txt:61(搜「ownership」) · text/200-fm-defining-alerts-and-runbooks.txt:62(搜「context」) |
| 规则四字段与三例 | Defining alerts and runbooks | text/200-fm-defining-alerts-and-runbooks.txt:86(搜「HighErrorRate」) · text/200-fm-defining-alerts-and-runbooks.txt:100(搜「histogram_quantile」) · text/200-fm-defining-alerts-and-runbooks.txt:137(搜「expr」) · text/200-fm-defining-alerts-and-runbooks.txt:163(搜「rule_files」) |
| Alertmanager 路由 | Defining alerts and runbooks | text/200-fm-defining-alerts-and-runbooks.txt:180(搜「Connecting Prometheus to Alertmanager」) |
| runbook 六要素 | Defining alerts and runbooks | text/200-fm-defining-alerts-and-runbooks.txt:305(搜「practical runbooks」) · text/200-fm-defining-alerts-and-runbooks.txt:317(搜「Summary」) · text/200-fm-defining-alerts-and-runbooks.txt:326(搜「error rate」) · text/200-fm-defining-alerts-and-runbooks.txt:342(搜「roll back」) |
| 两系告警对照 | Defining alerts and runbooks | text/200-fm-defining-alerts-and-runbooks.txt:464(搜「versus」) · text/200-fm-defining-alerts-and-runbooks.txt:470(搜「YAML rule files」) · text/200-fm-defining-alerts-and-runbooks.txt:480(搜「use both」) |
| 运营纪律 | Defining alerts and runbooks | text/200-fm-defining-alerts-and-runbooks.txt:487(搜「Operational readiness」) · text/200-fm-defining-alerts-and-runbooks.txt:495(搜「living components」) · text/201-fm-summary.txt:4(搜「Review alerts」) · text/201-fm-summary.txt:7(搜「Simulate failures」) |
-
出处:「Technical requirements」的埋点节(
text/198-fm-technical-requirements.txt:37,搜「visibility starts」;:40,搜「real story」;:43,搜「OpenTracing」;:45,搜「OpenTelemetry」;:46,搜「three key building blocks」)。 ↩↩↩↩ -
出处:「Technical requirements」的追踪节(
text/198-fm-technical-requirements.txt:60,搜「single request」;:63,搜「tree of spans」;:71,搜「contributes to the latency」)。 ↩↩ -
出处:「Collecting and visualizing metrics with Prometheus and Grafana」的章节开头(
text/199-fm-collecting-and-visualizing-metrics-with-promethe.txt:29,搜「Collecting and visualizing」)与预定义 dashboard 段(text/199-fm-collecting-and-visualizing-metrics-with-promethe.txt:529,搜「pre-defined」)。 ↩ -
出处:「Collecting and visualizing metrics with Prometheus and Grafana」的埋点最佳实践小节(
text/199-fm-collecting-and-visualizing-metrics-with-promethe.txt:9,搜「Best practices for instrumentation」;:14,搜「Instrument early」)。原文:五条建议——尽早埋点;服务命名标准化;记录业务上下文;指标与追踪关联;优先 OTLP 导出。 ↩ -
出处:「Collecting and visualizing metrics with Prometheus and Grafana」的埋点代码(
text/199-fm-collecting-and-visualizing-metrics-with-promethe.txt:146,搜「orders_request_seconds」;:222,搜「histogram (orders_request_seconds)」)与告警规则(text/200-fm-defining-alerts-and-runbooks.txt:100,搜「histogram_quantile」)。原文:orders/payments 各用 Histogram 记录请求时延;p95 告警用 histogram_quantile 按 bucket 聚合。 ↩↩ -
出处:「Defining alerts and runbooks」第 45–66 段(
text/200-fm-defining-alerts-and-runbooks.txt:46,搜「requires action」;:49,搜「predictive」;:54,搜「more than 2 minutes」;:55,搜「alert fatigue」;:60,搜「symptoms」;:61,搜「ownership」;:62,搜「context」)。 ↩↩↩↩↩↩ -
出处:「Defining alerts and runbooks」第 68–178 段(
text/200-fm-defining-alerts-and-runbooks.txt:86,搜「HighErrorRate」;:100,搜「histogram_quantile」;:113,搜「PaymentsLatency」;:130,搜「exceeds 5%」;:137,搜「expr」;:146,搜「ConfigMap」;:163,搜「rule_files」;:168,搜「9090/rules」)。 ↩↩↩↩↩ -
出处:「Defining alerts and runbooks」的 Alertmanager 节(
text/200-fm-defining-alerts-and-runbooks.txt:180,搜「Connecting Prometheus to Alertmanager」;:178,搜「right team」)。 ↩ -
出处:「Defining alerts and runbooks」第 305–323 段(
text/200-fm-defining-alerts-and-runbooks.txt:309,搜「runbook is」;:312,搜「close the gap」;:316,搜「contains the following」)。 ↩↩↩↩ -
出处:「Defining alerts and runbooks」第 324–364 段(
text/200-fm-defining-alerts-and-runbooks.txt:326,搜「exceeded 5%」;:342,搜「roll back」;:346,搜「Grafana dashboard」)。 ↩↩ -
出处:「Defining alerts and runbooks」第 464–485 段(
text/200-fm-defining-alerts-and-runbooks.txt:468,搜「Aspect」;:470,搜「YAML rule files」;:476,搜「Production-grade」;:480,搜「use both」)。 ↩↩↩↩ -
出处:「Defining alerts and runbooks」第 487–495 段与「Summary」(
text/200-fm-defining-alerts-and-runbooks.txt:495,搜「living components」;text/201-fm-summary.txt:4,搜「Review alerts」;:3,搜「Simulate failures」)。 ↩↩↩