读书笔记 · 约 17,641 字 · 预计推送 2 部分

Prometheus/Grafana 监控实践:指标命名、告警规则、SLO 与成本控制 —— 主题精读 未开始

目录

题记与说明


一、主题概览

监控实践常被当成"装好 Prometheus + 套个 Grafana 面板"就完事,但这次精读的 5 个来源指向同一个判断:监控体系的难点不在工具部署,而在三个纪律性设计——

  1. 指标怎么命名:决定了一年后的 PromQL 还能不能读、能不能告警、会不会撞名(Prometheus 官方 naming 实践)。
  2. 告警怎么定义:决定值班的信噪比。核心是"对症状告警而非原因"+"按错误预算消耗速度(burn rate)告警",而非静态阈值(Prometheus alerting 实践 + Google SRE Workbook)。
  3. 成本怎么控:Prometheus 的成本几乎完全由基数(cardinality,指标名 × label 值组合 = 时间序列数)和抓取频率决定,是可以工程化治理的(Grafana cardinality 文章)。
  4. SLO 是粘合剂:SLO 把 1、2、3 串起来——SLI 决定测什么,错误预算决定何时告警,SLO 决定哪些指标/桶值得花钱保留(Grafana SLO 指南)。

二、逐源精读

来源 1:Prometheus 官方《Metric and label naming》

出处:https://prometheus.io/docs/practices/naming/ (Prometheus Authors,最佳实践文档)

文档定位:开头即声明这些约定不是使用 Prometheus 的强制要求,而是风格指南与最佳实践合集,组织可以自行调整:"The metric and label conventions presented in this document are not required for using Prometheus, but can serve as both a style-guide and a collection of best practices."

指标名的 MUST/SHOULD 规则(RFC 2119 语气):

为什么坚持在名字里带单位和类型后缀(对 OpenTelemetry 风格的反驳,这一节很有价值):

"It's critical, especially during monitoring/SRE incident practices to look on PromQL expressions in plain YAML and understand the underlying metric type and unit you work with."
"With growing adoption and metric changes over time, there are cases where lack of unit and type information in the metric name will cause certain series to collide (e.g. process_cpu for seconds and milliseconds)."

即:Prometheus 生态大量消费场景是纯 YAML(告警、record rule、自动扩缩容配置),没 UI 补全帮你解释单位;且缺单位会随时间造成指标撞名。

Label 规则:label 用于区分被测物的特征(api_http_requests_total 用 operation="create|update|delete" 区分请求类型),不要把 label 名塞进指标名(冗余且 label 被聚合掉后名字变误导)。紧随其后的 CAUTION 是全文最重要的一段:

"Remember that every unique combination of key-value label pairs represents a new time series, which can dramatically increase the amount of data stored. Do not use labels to store dimensions with high cardinality (many different label values), such as user IDs, email addresses, or other unbounded sets of values."

基准单位表(部分):时间=seconds;字节=bytes(bits 一律换算成 bytes);百分比=ratio(0–1);功率不直接导出,而是导出 joules 计数器再 rate(joules[5m]) 得 Watts;质量用 grams 避免 kilo 前缀问题。

来源 2:Prometheus 官方《Alerting best practices》

出处:https://prometheus.io/docs/practices/alerting/ (官方实践页,引用 Rob Ewaschuk 的 *My Philosophy on Alerting*,基于其在 Google 的观察)

核心哲学:保持告警简单、对症状告警而不是原因、维护好控制台用于定位原因、以及——

"avoid having pages where there is nothing to do."(避免发出"收到后无事可做"的 page。)

具体规则:

来源 3:Google SRE Workbook 第 5 章《Alerting on SLOs》

出处:https://sre.google/workbook/alerting-on-slos/ (Google,Chris Jones 等著,该章是 SLO 告警的事实标准参考)

章旨:"having good SLOs that measure the reliability of your platform, as experienced by your customers, provides the highest-quality indication for when an on-call engineer should respond."——把 SLO 转成可执行告警规则,在错误预算烧穿前响应。

评估告警策略的 4 个属性(后续 6 种方案的评判轴):

属性含义
Precision触发的告警中"重大事件"的比例
Recall重大事件中被检出的比例
Detection time各种条件下发出通知的耗时
Reset time问题解决后告警继续 firing 的时长

6 种方案演进(前 3 种不可行/有缺陷,方案 6 最推荐):

  1. 短窗口错误率 ≥ SLO(10m 窗口 ≥0.1%):完全宕机 0.6 秒检出、recall 好,但 precision 极差——10 分钟 0.1% 错误率只消耗月度预算 0.02% 就 page;极端推演"每天收 144 条告警、一条都不处理、SLO 照样达标"。
  2. 放大窗口到 36h(对应 5% 月预算):precision 变好(完全宕机 2 分 10 秒检出),但 reset time 灾难性变差——错误早已停止,36 小时平均仍超阈值,告警继续 firing 36 小时;且长窗口 rate 计算内存/IO 代价高。
  3. 短窗口 + for: 1h duration 参数:官方明确否定——"For the reasons listed in Table 5-3, we do not recommend using durations as part of your SLO-based alerting criteria." 理由:(a) duration 不随事故严重度缩放,100% 宕机与 0.2% 事故同样 1 小时才报(那一小时已烧掉 30 天预算的 140%);(b) duration 计时器在指标短暂回落到 SLO 内时会重置——每 10 分钟持续 5 分钟的 100% 错误尖峰永远不触发告警,却烧掉 35% 预算(每个尖峰约 12%)。
  4. 单烧率 + 固定窗口:burn rate = 相对 SLO 的预算消耗速度(99.9% SLO、30 天窗口下恒定 0.1% 错误率 = burn rate 1)。固定 1h 窗口、要求 5% 预算消耗 → burn rate 36。precision/检出都好,但 recall 低:35x 持续烧率永远不触发(20.5 小时烧完全部预算),reset 仍长达 58 分钟。
  5. 多烧率:快烧 page、慢烧 ticket。官方建议起点:"We recommend 2% budget consumption in one hour and 5% budget consumption in six hours as reasonable starting numbers for paging, and 10% budget consumption in three days as a good baseline for ticket alerts." 对应配置:
   expr: (
           job:slo_errors_per_request:ratio_rate1h{job="myjob"} > (14.4*0.001)
         or
           job:slo_errors_per_request:ratio_rate6h{job="myjob"} > (6*0.001)
         )
   severity: page

   expr: job:slo_errors_per_request:ratio_rate3d{job="myjob"} > 0.001
   severity: ticket

缺点:参数多;3d 窗口 reset 更长;需要告警抑制——"10% budget spend in five minutes also means that 5% of the budget was spent in six hours, and 2% of the budget was spent in one hour",不抑制会一事故三通知。

  1. 多窗口 + 多烧率(MWMB,最推荐):在多烧率上再 AND 一个短窗口(推荐为长窗口的 1/12),确认"此刻仍在烧"才通知,压掉 false positive 并改善 reset time。官方推荐参数表(99.9% SLO):
Severity长窗口短窗口Burn rate预算消耗
Page1 hour5 minutes14.42%
Page6 hours30 minutes65%
Ticket3 days6 hours110%

完整配置示例:

   expr: (
           job:slo_errors_per_request:ratio_rate1h{job="myjob"} > (14.4*0.001)
         and
           job:slo_errors_per_request:ratio_rate5m{job="myjob"} > (14.4*0.001)
         )
       or
         (
           job:slo_errors_per_request:ratio_rate6h{job="myjob"} > (6*0.001)
         and
           job:slo_errors_per_request:ratio_rate30m{job="myjob"} > (6*0.001)
         )
   severity: page

章末结论:"In most cases, we believe that the multiwindow, multi-burn-rate alerting technique is the most appropriate approach to defending your application's SLOs."

烧率→耗尽时间直觉表(99.9% SLO):burn rate 1→30 天;2→15 天;10→3 天;1000→43 分钟。

低流量服务:10 请求/小时的服务单条失败请求 = 小时错误率 10%,对 99.9% SLO 是 1000x 烧率、立即 page,而 30 天只有 7 次失败配额——单个请求可能因大量"短暂且不值得修"的原因失败。官方给出四个方向:合成流量(blackbox prober/集成测试已有现成部件)、合并共享故障域的小服务一起监控、改产品(客户端重试+指数退避+抖动、fallback 路径)、降低 SLO 与利益相关者协商(99.9%→99%,代价是产品决策,影响错误预算政策)。

极端可用性目标:90% 目标下"1 小时耗 2% 预算"的 page 条件永远不可能触发(100% 宕机一小时也只烧 1.4%);99.999% 月度目标下 100% 宕机 26 秒烧穿预算——比多数监控的采集间隔还短,"The only way to defend this level of reliability is to design the system so that the chance of a 100% outage is extremely low"(靠灰度:先放 1% 用户,同样 1% 烧率下有 43 分钟响应窗口)。

规模化告警:100 个微服务各自定制窗口/烧率 = 不可持续的 toil。"Once you decide on your alerting parameters, apply them to all your services." 把请求类型归入桶:CRITICAL(99.99%, 100ms@90)、HIGH_FAST(99.9%, 100ms)、HIGH_SLOW(99.9%, 1000ms/5s@99)、LOW(99%)、NO_SLO(暗启动/alpha,明确不在 SLO 内)——5 个桶足够保护用户满意度,toil 远小于逐请求类型定制。

来源 4:Grafana Labs《How to manage high cardinality metrics in Prometheus and Kubernetes》

出处:https://grafana.com/blog/how-to-manage-high-cardinality-metrics-in-prometheus-and-kubernetes/ (2022-10,Grafana Labs 官方博客)

基数为什么爆炸:云原生把单机单应用换成多节点多 pod 微服务(每层都要 label);kube_pod_status_phase 这类指标在每个 pod 状态迁移(pending→running→failed)时新建序列,短命 Job 场景尤甚;15+ 语言 client library 让埋点太容易,dev 指标漏进生产;exporter 本身就重——Node exporter 默认约 500 条时间序列,MySQL exporter 约 1000 条(原文:"roughly 500 Prometheus time series by default" / "roughly 1,000 time series and not all of those are valuable");最致命的是无界 label(session_id/user_id/device_id),流量一涨序列跟着涨。

成本影响:更多基数 = 更多存储/计算 = 更高可观测性支出;库变大后查询和面板变慢,"prolong MTTR when troubleshooting outages"(拖长故障定位时间)——成本问题同时是可靠性问题。

识别手段:

  1. 四象限分析:按"基数 vs 价值"画散点,先打第三象限(高成本、没人用),再复查第四象限(高价值高基数)的 label 粒度是否必要;
  2. cardinality 管理面板(Grafana Cloud Pro/Advanced);
  3. Mimirtool(开源 CLI):扫描 dashboards/alerts/recording rules 中未使用的指标输出 JSON,完全未用的可 drop;
  4. Usage Insights:按 label 集追踪序列数随时间,把增长归因到团队/环境/应用。

四个治理杠杆(本文最实操的部分):

  1. 调抓取频率:默认 15s(=4 DPM,datapoints per minute),用 count_over_time(scrape_samples_scraped[1m]) 查实际用量;把不关键指标提到 60s "can reduce costs by up to 75%"(降本上限 75%,这是全文最硬的数字)。
  2. 裁剪直方图桶:每个 bucket 是经 le label 的一条序列;桶应对齐 SLO(50ms SLO 就没必要区分 5ms 和 10ms)。裁剪桶是安全的,因为桶是累积的——被删桶以下的值滚入下一个桶,histogram_quantile 仍可用。
  3. 删 label 要小心:只有当剩余 label 组合仍唯一时才能删;否则 Prometheus 丢弃重复样本造成数据损失(文中例子:一个 env 下多个 ip 值会互相覆盖成 1/3/7)。
  4. recording rules 先聚合再删:agent 不可重配、直接删 label 会撞重复时,先 sum by(env) (my_metric_total{}) 生成聚合序列,再 drop 明细,保留 1+3+7→11 的卷积。

来源 5:Grafana Labs《SLOs: a guide to setting and benefiting from service level objectives》

出处:https://grafana.com/blog/slos-a-guide-to-setting-and-benefiting-from-service-level-objectives/ (Jake Swiss,2025-02-05)

为什么用 SLO:功能还是修 bug 犹豫不决时,SLO 把焦点拉回"your users and their experience";从任意阈值转向"user-impact-driven metrics",从被动救火转向主动事件管理;error budget 是发布与否的"red light, green light"机制——预算烧穿先修问题再上功能。

示例结构(checkout 流):SLI = 点击"Place Order"到确认页完全加载的时间;目标 = 99.9% 交易 2 秒内完成(滚动 30 天);错误预算 = 30 天内最多 0.1% 交易超时。注意 SLI 是端到端用户体验而非某个内部组件指标。

四步建立法:

  1. 识别关键用户旅程/服务,从小做起(如绑定 SLA 的服务);
  2. 基于历史数据和客户预期定目标,拉利益相关者对齐;
  3. 上对齐的工具(Prometheus / Grafana Cloud);
  4. 建立错误预算并"as a strategic tool for prioritization and accountability"。

评审节奏:把 SLO review 塞进 retrospective/sprint review/季度规划;违约时 blameless postmortem("treat them as opportunities for learning rather than failures")。

常见坑:

可引述金句:"Error budgets define how much unreliability you're willing to tolerate within a given period." / "SLOs aren't just a technical tool—they're a strategic advantage."


三、七维提取

1. 核心问题

监控体系从"能用"到"可靠且可负担"之间隔着四个设计问题:指标如何命名才能让人和机器在一年后还能正确消费(单位/类型/碰撞);告警如何定义才能在正确的时间用正确的严重级通知正确的人(precision/recall/detection/reset 四难权衡);成本如何在指标爆炸式增长下受控(cardinality 治理);以及用什么统一框架决定"测什么、何时告警、什么值得花钱"(SLO 与错误预算)。传统静态阈值监控在这四点上系统性失效。

2. 主要主张

3. 方法

五个来源共同的方法论是把监控从"技艺"变成"有判据的工程":

4. 数据与证据

5. 结论

6. 局限

7. 对我的启发

  1. 给自己自托管的服务栈立命名规范:n8n/Whisper/本地网关等自建 exporter 一律 <应用>_<子系统>_<量>_<单位复数>_total,秒和字节做基准单位。最直接的应用:以后写任何 metrics 埋点(包括给自己 LLM 应用记录 token/延迟的指标——可与我此前的"LLM 应用可观测性"精读笔记衔接),先查命名规范再动手,避免 process_cpu 式撞名。
  2. 告警从"阈值表"迁到"烧率表":个人服务的监控常犯的正是 Workbook 方案 1 的错误——抖动就通知。改用双窗口 AND(如 1h+5m 同超阈值才通知)+ 一条 3d ticket 级慢烧规则,可以显著降夜间误报;且不要用 for: 参数替代长窗口(timer 会因短暂回落重置,这是官方实测证伪的方案)。
  3. 成本控制第一动作是降抓取频率和裁桶:不重要的指标 15s→60s(-75% 上限),直方图桶只保留 SLO 附近的档位——对自托管单机 Prometheus 立竿见影,省内存和磁盘;count_over_time(scrape_samples_scraped[1m]) 可以直接拿来审计。
  4. 给个人/小团队场景把 SLO 简化成三件套:一条端到端 SLI(RED 的 E 和 R 就够)、一个 99% 级目标(个人服务不值得 99.9%)、一条 ticket 级慢烧告警。Workbook 的低流量章节说明:小流量下与其硬套高可用参数,不如合成探针(blackbox 已内置)或干脆把 SLO 降到实际影响水平。
  5. 写作素材角度:"告警四属性(precision/recall/detection/reset)"和"烧率=预算消耗速度"是两个非常适合科普的模型;"144 条告警/天且一条不管 SLO 仍达标"和"99.999% 目标 26 秒烧穿预算"是两个现成的反直觉故事钩子。

四、跨源连接图

        ┌────────────────────────────────────────────┐
        │   SLO(Grafana 指南:旅程→SLI→目标→预算)      │
        │   决定:测什么、值得花多少钱、何时算违约          │
        └──────────┬─────────────────┬───────────────┘
                   │                 │
     ┌─────────────▼─────┐   ┌───────▼────────────────┐
     │ 指标命名(官方)      │   │ 告警规则(官方+SRE Workbook)│
     │ 单位进名字/total后缀 │   │ 症状优先 + MWMB 烧率表     │
     │ 无界值禁入 label    │   │ 短窗=长窗/12,参数全局统一  │
     └─────────┬─────────┘   └───────┬────────────────┘
               │                     │
     ┌─────────▼─────────────────────▼────────┐
     │ 成本控制(Grafana):cardinality 治理       │
     │ 采集频率/裁桶对齐SLO/删label/recording rules │
     └────────────────────────────────────────┘

四者闭环:SLO 定义价值 → 命名保证可消费性 → 烧率告警消费错误预算 → cardinality 治理把预算花在服务 SLO 的序列上。


五、参考链接(全部于 2026-11-01 在线精读)

  1. Prometheus Authors, *Metric and label naming* — https://prometheus.io/docs/practices/naming/
  2. Prometheus Authors, *Alerting best practices*(含 Rob Ewaschuk *My Philosophy on Alerting* 引用)— https://prometheus.io/docs/practices/alerting/
  3. Google, *Alerting on SLOs*, SRE Workbook Ch.5 — https://sre.google/workbook/alerting-on-slos/
  4. Grafana Labs, *How to manage high cardinality metrics in Prometheus and Kubernetes* — https://grafana.com/blog/how-to-manage-high-cardinality-metrics-in-prometheus-and-kubernetes/
  5. Grafana Labs (Jake Swiss), *SLOs: a guide to setting and benefiting from service level objectives* — https://grafana.com/blog/slos-a-guide-to-setting-and-benefiting-from-service-level-objectives/

(补充检索线索,未精读仅参考:dlow 博客烧率推导 https://blog.dlow.me/everything/slo-and-burn-rate ;Cisco Outshift 烧率解密 https://outshift.cisco.com/blog/in-depth-tech/burn-rate-demystified )

← 资料库今日播报 →