第7章 平台可观测性
平台自身的度量与监控
章节导读
可观测性(Observability)一词源自控制论,指从系统的外部输出推断其内部状态的能力。在软件工程中,它演化为「通过日志(Logs)、指标(Metrics)、追踪(Traces)三大支柱(加上后来的 Profiling 与事件)理解系统行为」的实践体系。平台工程时代,可观测性呈现出双重身份:一方面,平台自身是一个复杂的生产系统——IDP 门户、能力层工作流引擎、CI/CD 基础设施、Crossplane 控制器、K8s 集群本身——它需要被监控、被度量、被赋予 SLO,因为平台宕机意味着全组织的交付能力瘫痪;另一方面,平台是可观测性能力的提供者——业务服务的日志、指标、追踪接入不应该是每个团队自己研究的课题,而应该是平台默认交付的服务(Observability as a Service)。本章同时覆盖这两个维度:平台自身的可观测性,与平台为用户提供的可观测性。
先谈第一个维度:平台也是系统,也需要监控。这个看似显然的命题在实践中经常被忽视——平台团队忙于给业务服务建监控,自己的系统却跑在「裸奔」状态:Backstage 门户没有 SLO、工作流引擎的失败率无人知晓、K8s 集群的容量趋势没有预测。后果在平台规模化后集中爆发:某天早上门户登录变慢,数百名开发者的日常工作受阻,平台团队却在用户投诉轰炸后才开始排查——没有告警、没有仪表盘、没有事故流程。成熟组织把平台自身当作「Tier-0 服务」对待:定义平台 SLO(门户可用性 99.9%、环境创建工作流成功率 99%、P90 完成时间 < 15 分钟)、建立平台状态页(status.acme.internal,公开各平台能力的实时健康度与事故历史)、配置面向平台团队的告警体系、执行平台自身的事故复盘。平台状态页的价值超越技术层面:它是平台团队与用户之间的信任契约——「我们知道平台现在有问题,正在处理,预计恢复时间 X」的透明沟通,远好于用户在黑暗中猜测与抱怨。
平台自身的度量维度可以分为四组。可用性组:门户与各能力 API 的可用率(SLO 追踪)、工作流成功率、K8s 控制平面健康度。性能组:自助操作的端到端时长(环境创建 P50/P90)、流水线时长、API 延迟。使用组:各能力的使用量(日活开发者、操作次数)、自助化率、缓存命中率。体验组:开发者满意度调查得分、错误信息的自助解决率、支持请求量(Slack 频道提问数——这个「反向指标」的下降意味着平台自解释能力的提升)。四组指标共同构成平台的「产品仪表盘」,是平台团队周会的固定议程与季度汇报的数据基础。
第二个维度——为平台用户提供可观测性——的设计哲学是「默认接入,标准呈现」。传统模式下,每个团队自己研究:用什么客户端库暴露指标?日志格式怎么定?追踪怎么采样?Grafana 仪表盘怎么画?告警规则怎么写?结果是组织内的可观测性质量呈幂律分布:少数精英团队有完善的 SLO 与告警,大多数团队只有基础日志,排障靠 grep 与猜测。平台化模式把这一切变成黄金路径的默认交付:服务模板内置指标暴露(RED 指标:请求率、错误率、延迟分布,带标准标签 service/env/version/team)、结构化日志约定(JSON 格式,必含 timestamp/level/service/trace_id 字段)、追踪自动埋点(OpenTelemetry SDK 或 agent 注入,采样策略平台统一)、标准仪表盘自动生成(每个服务创建时自动获得一个包含 RED 指标、资源用量、部署事件标记的 Grafana 仪表盘)、默认告警规则(基于 SLO 燃烧率的高置信度告警,宁少勿滥)。开发者沿黄金路径创建服务,可观测性「免费」就位——这就是「可观测性即服务」(Observability as a Service)的含义:可观测性不是团队要自建的能力,而是平台提供的基础设施。
标准化是可观测性平台化的核心价值,其深层原因是「关联」(correlation)。排障的本质是跨信号关联:从告警(指标异常)跳到相关日志(同一时间窗口、同一服务),从日志跳到追踪(trace_id 关联),从追踪跳到代码(版本映射)与部署事件(「异常开始时间与最近一次部署重合」)。关联的前提是标签与字段的一致性:如果 A 团队的服务标签叫 service_name、B 团队叫 app、C 团队叫 component,跨服务的追踪聚合与全局查询就不可能。平台通过黄金路径强制统一标签体系(service、environment、version、team 四维标签),使「三个一键」(告警→日志→追踪的无缝跳转)成为结构性可能。OpenTelemetry(OTel)的崛起为这种标准化提供了厂商中立的协议基础:OTel 统一了三大信号的采集、传输与语义约定(semantic conventions),平台只需对接 OTel Collector,后端(Prometheus、Tempo、Loki、Datadog、Honeycomb)可以按需替换——可观测性栈的「平台无关化」大幅降低了锁定风险与演进成本。
平台可观测性还面临三个特有挑战。多租户隔离:数百个团队共享可观测性栈,查询性能与数据隔离需要设计(按团队路由的 Collector 管道、查询配额、敏感日志的访问控制)。成本控制:可观测性数据量随服务规模爆炸(一个中型公司的日志量可达每天 TB 级),存储成本与查询性能的平衡需要策略(热/温/冷分层、采样策略、日志聚合与去重、按价值分级保留——生产错误日志保留 90 天,debug 日志保留 7 天)。数据量与信号质量的悖论:更多的数据不等于更好的可观测性——告警泛滥(alert fatigue)让真正的信号淹没在噪音中,平台需要用「高置信度默认告警 + 团队自定义告警分层」的策略对抗熵增。最后一个主题是「从可观测性数据反推平台改进」:平台的可观测性数据不只是排障工具,更是产品决策的输入——环境创建工作流的阶段级时长分析揭示优化点,错误日志的主题聚类发现文档缺陷,使用量数据决定能力的投资优先级。可观测性闭环(数据 → 洞察 → 改进 → 验证)是平台持续演进引擎的核心部件。
核心概念
- 可观测性
- SLO
- 平台度量
- 可观测性即服务
要点精析
【平台自身的可观测性:把平台当 Tier-0 服务运维】平台的基础设施属性决定了它的故障爆炸半径远超普通业务服务:IDP 门户不可用,数百名开发者无法自助操作;工作流引擎故障,全组织的环境创建与部署停滞;K8s 控制平面异常,所有工作负载的调度与自愈能力丧失。因此平台自身必须按最高等级的服务标准运维,其可观测性体系包含四个层次。第一层,组件级监控:平台的每个组件(门户、API 网关、工作流引擎、目录服务、Crossplane 控制器、CI runner 池)都有标准的 RED 指标采集与告警——平台组件跑在平台自己的 K8s 上,用平台自己的黄金路径部署(吃自己的狗粮),监控接入自动完成。第二层,能力级 SLO:以「用户能力」而非「组件」为单位定义 SLO——「环境创建能力:99% 的请求在 20 分钟内成功完成」「生产部署能力:99.9% 的部署请求被受理且流水线基础设施可用」。能力级 SLO 比组件级更贴近用户感知:单个组件的短暂故障若被重试与降级吸收,能力 SLO 不受影响;反之多个组件都「健康」但组合起来慢(如目录服务正常但认证服务慢),能力 SLO 会捕获问题。第三层,依赖链追踪:平台能力通常是跨组件的工作流(门户 → API → 工作流引擎 → Crossplane → 云 API),OpenTelemetry 追踪贯穿全链路,工作流的每个阶段有 span——「环境创建 P90 恶化」可以下钻到「哪个阶段变慢了」(常见根因:云 API throttling、镜像拉取慢、DNS 解析超时)。第四层,容量与趋势:runner 池利用率、etcd 存储增长、Prometheus TSDB 容量、云 API 配额使用率——平台的增长性资源需要趋势预测与提前扩容(K8s etcd 在对象数超过阈值后性能劣化,平台作为全组织资源的控制平面尤其敏感)。配套的运营机制:平台状态页(公开各能力的实时状态与事故历史)、平台 on-call 轮值(与业务 on-call 分离,平台事故有独立的响应流程)、平台事故复盘(复盘报告对用户公开——透明度是信任的基石)。
【平台度量维度:可用性、性能、使用率、开发者体验】平台的度量体系需要覆盖四个维度,每个维度回答不同的管理问题。可用性维度回答「平台可靠吗」:能力级 SLO 达成率、错误预算消耗速度、平台事故数与时长(MTTR)。性能维度回答「平台快吗」:自助操作的端到端时长分布(P50/P90/P99,按能力分解——环境创建、部署、日志查询各有目标)、流水线时长、门户页面加载时间(前端性能也是体验——一个加载 8 秒的目录页面会被开发者放弃)。使用率维度回答「平台被用吗」:日活/周活开发者数(占全体工程师的比例)、各能力的使用次数与趋势、自助化率(高频任务中自助完成的占比)、黄金路径覆盖率。使用率数据的深层用法是「能力健康诊断」:使用量持续下降的能力要么被更好的替代方案取代(应调研并可能下线),要么体验恶化(应修复);使用量暴涨的能力需要容量预警。开发者体验维度回答「平台好用吗」:季度调查的满意度得分(按能力分解)、NPS、错误信息自助解决率、支持渠道请求量(Slack #platform-help 的提问数是「平台自解释能力」的反向指标——文档与错误信息越好,提问越少;提问主题聚类直接生成文档改进 backlog)。四维度的度量节奏不同:可用性与性能是实时指标(仪表盘 + 告警),使用率是周度分析(平台团队周会),体验是季度调查(全组织发布结果与改进行动)。一个关键的反模式警告:不要用「平台访问量」这类虚荣指标向管理层汇报——1000 次页面访问可能是 100 个满意用户各来 10 次,也可能是 10 个困惑用户各迷路 100 次;任务完成率与时长才是真实信号。
【为用户提供的可观测性:默认接入与标准化仪表盘】「可观测性即服务」的实现机制是「默认接入 + 标准呈现 + 自助深化」三层。默认接入层:黄金路径的服务模板内置 OpenTelemetry SDK(或自动注入 instrumentation agent——K8s 的 OTel Operator 可以无侵入地为 Java/Python/Node 应用注入自动埋点),应用启动即暴露 RED 指标(http_server_duration、http_requests_total 按 status 分解)、结构化日志(JSON,标准字段)、W3C TraceContext 传播。开发者零配置获得基础可观测性——「不知道要接监控」的新服务不再有监控盲区。标准呈现层:服务创建时平台自动生成三件套——服务仪表盘(Grafana:RED 指标 + 资源用量 + 部署事件 annotation + SLO 燃烧率,按黄金路径的标准布局)、默认告警规则(PrometheusRule CR:SLO 燃烧率告警采用多窗口多燃烧率模式——1 小时窗口 14.4 倍燃烧率触发紧急页呼,6 小时窗口 6 倍燃烧率触发工单;加上资源饱和告警:内存 > 90% 持续 15 分钟、磁盘预测 4 小时内耗尽)、服务 runbook 骨架(每条默认告警链接到对应的排查步骤模板)。自助深化层:标准配置覆盖 80% 需求后,剩余 20% 的定制通过自助能力满足——自定义仪表盘(Grafana 的团队空间,平台提供数据源与变量模板)、自定义告警(自助创建 PrometheusRule,平台校验其质量:告警必须有 runbook 链接、必须设置合理的 for 持续时间——防止告警噪音污染)、自定义指标(业务指标的暴露指南与命名规范校验)、日志查询的保存与分享。三层设计的度量验证:新服务的「监控接入率」应为 100%(默认接入的结构性保证)、默认告警的「精确率」(触发后确认真实问题的比例,目标 > 70%——低于此值说明阈值需要调优)、开发者「自定义告警的采用率」(反映标准告警的覆盖缺口)。
【可观测性即服务:日志、指标、追踪的自助接入架构】平台级可观测性栈的参考架构分四层。采集层:OpenTelemetry 是统一的采集协议——应用侧用 OTel SDK/agent 产生信号,节点侧用 OTel Collector(DaemonSet 模式)做第一跳聚合。Collector 的管道设计(receivers → processors → exporters)是平台策略的执行点:processor 阶段实施属性标准化(把各应用五花八门的标签映射到平台四维标签体系)、敏感数据脱敏(正则匹配并遮蔽日志中的信用卡号、身份证号、token——脱敏在采集侧执行,敏感数据根本不进入存储)、采样决策(tail-based sampling:错误与慢请求 100% 保留,正常请求按 1-10% 采样——在 Collector 层而非应用层做尾采样才能基于完整 trace 决策)、多租户路由(按 team 标签把数据路由到不同的存储后端/命名空间,实施查询隔离与配额)。传输与存储层:指标走 Prometheus/Thanos/Mimir(长期存储与全局查询),日志走 Loki/Elasticsearch(Loki 的「索引标签、不索引全文」设计使成本比全文索引低一个数量级,适合大规模日志),追踪走 Tempo/Jaeger(对象存储后端,成本极低)。呈现层:Grafana 统一查询三大信号并实现关联跳转(日志行的 trace_id 一键跳追踪、追踪 span 一键跳对应时间窗口的指标)——关联体验是三大信号同栈的最大价值。治理层:数据保留策略(分级:生产错误日志 90 天、普通日志 30 天、debug 7 天、指标原始 15 天 + 降采样 2 年)、成本分摊(按 team 标签统计各团队的存储与查询消耗,月度成本报告——成本可见性驱动团队自主优化日志量)、访问控制(敏感服务的日志查询需要额外授权,审计所有查询行为)。自助接入的用户界面:门户中的「可观测性」页面提供服务的实时仪表盘入口、日志查询器(预填服务与时间过滤器)、追踪搜索、告警管理——一切以服务目录实体为锚点组织,开发者不需要知道底层是哪个存储系统。
【平台可观测性的挑战:多租户、成本与数据量】三大挑战需要专门的架构对策。多租户隔离:数百团队共享栈的隔离需求分三级——数据隔离(A 团队默认不能查询 B 团队的日志,通过 Collector 路由到租户命名空间 + 查询侧的认证授权实现;Loki/Mimir/Tempo 原生支持 X-Scope-OrgID 租户头)、性能隔离(一个团队的爆炸性查询——无时间范围的全量日志扫描——不能拖垮共享查询引擎,对策:查询配额(每团队并发查询数与扫描量上限)、查询守卫(强制时间范围、拒绝无标签选择器的查询)、资源分池(关键团队路由到独立查询实例))、故障隔离(Collector 与存储的按租户限流,防止单租户数据洪峰影响全局)。成本控制:可观测性成本通常占云支出的 10-20% 且随规模超线性增长,控制手段按杠杆大小排序——采样策略(追踪的尾采样把数据量降 90% 而保留几乎全部诊断价值,是最大杠杆)、日志分级(应用日志级别的平台化管理:生产默认 INFO,debug 需要临时申请且自动过期——「临时提升日志级别」做成自助能力而非永久配置)、聚合替代原始(指标能回答的问题不存日志——把高频日志模式转化为指标计数器)、保留策略分级(按数据价值差异化保留期)、存储分层(热数据 SSD、温数据对象存储、冷数据归档)。数据量与信号质量:告警泛滥的治理是持续战争——平台的对策包括:默认告警的高置信度设计(只保留 SLO 燃烧率与资源饱和两类,历史数据显示这两类的精确率最高)、告警质量度量(每条告警规则的触发次数、确认率、静音率——静音率 > 50% 的规则自动进入「待整改清单」)、告警聚合(同一服务的关联告警合并为一个事故通知,附带上下文摘要而非 20 条独立页呼)、定期告警审查(季度清理:过去 90 天从未触发的规则可能阈值失效,触发后从未被处理的规则可能无价值)。
【从可观测性数据反推平台改进:数据驱动的平台演进】平台的可观测性数据是产品决策的金矿,成熟平台团队建立系统化的「数据 → 洞察 → 改进」闭环。闭环的四个数据源与对应洞察。工作流阶段分析:环境创建工作流的每个阶段(校验 → 资源分配 → 部署 → 注册 → 通知)有 span 时长,月度聚合发现「P90 恶化集中在云 API 调用阶段」→ 洞察:云 API throttling → 改进:实现请求队列与指数退避、申请配额提升 → 验证:下月 P90 回落。错误日志主题聚类:平台各组件的错误日志按月聚类(简单的正则分组或 LLM 辅助的主题提取),发现「38% 的用户错误是 quota exceeded,其中多数发生在月末」→ 洞察:配额周期设计不合理(月度重置导致月末集中耗尽)→ 改进:配额预警(80% 时通知)+ 弹性临时配额 → 验证:quota 错误下降 70%。使用路径分析:门户的前端埋点(页面访问序列、搜索关键词、放弃点)揭示「25% 的用户搜索服务名后没有点击任何结果」→ 洞察:搜索相关性或结果呈现问题 → 改进:搜索算法与 UI 迭代。支持请求挖掘:#platform-help 频道的问题按周聚类,高频问题(「怎么给服务加自定义域名」出现 12 次)直接转化为文档改进或功能需求(自助域名配置能力进入路线图)。闭环的运营机制:平台团队周会固定议程「上周数据洞察」(15 分钟,数据分析师或轮值工程师呈现);季度平台评审用数据验证上季度改进的效果(改进 → 指标变化的归因追踪);年度用户调查与行为数据交叉验证(用户说「环境创建慢」与实测 P90 数据是否一致——不一致本身是洞察:可能是感知问题(等待时无进度反馈)而非实际性能问题)。这个闭环的本质是把平台运营从「响应式」(用户投诉驱动)升级为「前瞻式」(数据异常驱动),从「直觉式」(平台团队猜用户要什么)升级为「证据式」(数据显示用户卡在哪)。
【平台 SLO 的定义与追踪:错误预算的运营艺术】平台 SLO 的设计需要平衡雄心与现实,其方法论与业务服务 SLO 一致但有平台特有的考量。SLO 定义三步法。第一步,选择 SLI(服务水平指标):平台能力的 SLI 通常是「成功率」(工作流成功完成 / 总请求)与「时效率」(P90 时长 < 目标值的请求占比)的组合——环境创建能力的 SLI:99% 的请求在 20 分钟内成功。可用性类 SLI 用「好事件 / 总事件」比率,基于真实用户请求(而非合成探测)计算。第二步,设定 SLO 目标:从历史数据出发(过去 90 天的实际达成率)设定略高于现状的目标——直接设 99.99% 会让错误预算瞬间耗尽、团队疲于救火;也不宜过低(99% 意味着每月 7 小时不可用,对日常依赖平台的组织不可接受)。典型平台 SLO:门户可用性 99.9%(月度 43 分钟预算)、核心自助能力成功率 99%、生产部署通道可用性 99.95%(部署通道是最关键能力,标准最高)。第三步,错误预算运营:错误预算 = 1 - SLO,是「允许的不可靠额度」——它的真正价值是决策机制:预算充足时平台团队可以激进演进(大版本升级、架构重构、新功能快速上线);预算告急(消耗 > 80%)时冻结非必要变更、专注可靠性;预算耗尽时停止全部功能开发直到可靠性恢复。这个机制把「稳定性 vs 迭代速度」的永恒争论转化为数据驱动的自动决策,也向用户透明化了平台的权衡(状态页公开错误预算消耗——用户理解「为什么这个月平台没上新功能」)。平台 SLO 的特有考量:(1)维护窗口的处理——平台的计划内维护(K8s 集群升级)是否计入 SLO?推荐计入但提前通知(用户视角不区分计划内外,但透明的维护日历让「意外」变「预期」);(2)依赖的传导——平台能力依赖云 API,云厂商故障导致的 SLO 违约如何归因?SLI 按依赖分解(平台自身错误率 vs 依赖错误率),对用户的 SLO 承诺是端到端的(用户不关心根因),但内部改进按归因分配;(3)SLO 评审节奏——季度评审 SLO 目标的合理性(持续 100% 达成的 SLO 太松应调紧,持续违约的要么修复要么调松并公开说明)。
【OpenTelemetry:平台可观测性的标准化基石】OpenTelemetry(OTel)已成为可观测性采集层的事实标准,平台团队对其的采纳深度决定了可观测性栈的长期灵活性。OTel 的架构价值:统一的 API/SDK(应用埋点一次,信号可以发送到任何兼容后端——从 Prometheus 自建栈迁移到 Datadog 商业栈不需要改应用代码)、统一的协议(OTLP,gRPC/HTTP)、统一的语义约定(HTTP、数据库、消息队列的 span 属性命名标准化——http.request.method 而非各家自创的 method/httpMethod/verb)、统一的 Collector(独立部署的信号管道,承担处理、路由、采样、脱敏的平台策略)。平台采纳 OTel 的分层策略。第一层(必须):Collector 全面部署——即使后端仍是 Prometheus/Loki 原生协议,Collector 作为统一采集入口的价值已经成立(策略执行点、缓冲与重试、多后端扇出);应用侧新服务强制 OTel SDK(黄金路径模板内置),存量服务提供迁移指南。第二层(推荐):追踪全面 OTel 化——追踪是三大信号中标准化收益最大的(此前各家 tracing 格式互不兼容,OTel 终结了碎片化);K8s 侧部署 OTel Operator 实现自动注入(Java/Node/Python 应用零代码改动获得自动埋点)。第三层(演进中):指标与日志的 OTel 化——OTel 的 metrics 与 logs 信号晚于 traces 成熟,2024 年后逐渐生产可用;平台的策略是「新接入用 OTel,存量 Prometheus 客户端不强制迁移」(Prometheus 生态与 OTel 的互操作性持续改善——Prometheus receiver/exporter 让两者可以共存于同一 Collector 管道)。Profiling 信号(连续性能剖析,如 Pyroscope/Parca 集成)是 OTel 的下一个前沿——CPU/内存 profile 与 trace 的关联让「这个慢 span 的热点函数是什么」一键可达。平台团队跟踪 OTel 演进的方式:语义约定的稳定性等级(stable/experimental)决定平台默认配置的保守程度,OTel 社区的平台工程相关 SIG(如 Profiling SIG)是参与标准制定的入口。
【告警体系设计:从噪音海洋到信号绿洲】告警是可观测性中「体验差异最大」的环节——设计糟糕的告警体系让 on-call 工程师夜不能寐、白天麻木,设计优秀的告警体系让每个页呼都值得立即响应。平台级告警设计的六条原则。原则一:告警分级与路由分离——P1(SLO 燃烧率紧急告警:1 小时窗口 14.4 倍燃烧率)页呼 on-call;P2(6 小时窗口 6 倍燃烧率)创建工作工单;P3(趋势预警:磁盘 7 天后满)进日报摘要。分级路由让「需要立即人工行动的」与「需要知道但不必立即行动的」彻底分离——混在一起是告警疲劳的根源。原则二:症状告警优先于原因告警——告警「用户可感知的症状」(SLO 违约、错误率升高)而非「可能的原因」(CPU 高、某个 Pod 重启);原因类信号放在仪表盘供排障时查看,不主动页呼。CPU 90% 但服务 SLO 完好不需要叫醒任何人——它可能是正常的负载高峰。原则三:每条告警必须可操作——告警通知包含:什么症状(错误率 5% 超过 SLO 的 1%)、影响面(哪些服务/环境/用户比例)、runbook 链接(排查步骤)、最近变更(时间窗口内的部署事件——「15 分钟前 payments-api 部署了 v2.3.1」是排障的第一线索)。原则四:告警必须有 owner——无主告警必然腐烂;告警规则的元数据包含 owning 团队,季度审查清理无主与低质量规则。原则五:多窗口多燃烧率(multi-window multi-burn-rate)作为 SLO 告警的标准模式——短窗口高燃烧率捕获急性故障(快速页呼),长窗口低燃烧率捕获慢性劣化(避免短窗口的统计噪音),Google SRE Workbook 的参数组合(1h/14.4x + 6h/6x + 3d/1x)是经过验证的起点。原则六:告警质量持续度量——每条规则的月度统计:触发次数、页呼后确认真实问题的比例(精确率)、被静音的时长占比;精确率 < 50% 的规则强制整改(调阈值、改窗口、或降级为工单);平台把「告警精确率」作为可观测性服务的 SLO 之一——噪音本身就是平台的质量缺陷。
【可观测性驱动的事故管理:平台在事故中的角色】生产事故是可观测性体系的「压力测试」,也是平台价值最集中的展现时刻。平台在事故生命周期各阶段的角色。检测阶段:标准化的 SLO 告警缩短检测时间(MTTD)——事故管理的第一目标是「比用户先知道」;平台的部署事件流与告警的自动关联(「告警开始时间 ±30 分钟内的部署」自动附到告警通知)把「变更引起的事故」的定位时间从小时级压缩到分钟级(业界数据:约 70% 的事故与最近的变更相关)。诊断阶段:「三个一键」的关联体验(告警 → 相关日志 → 完整追踪 → 部署 diff)是诊断加速的核心;平台提供的「事故仪表盘」(自动生成:受影响服务的 RED 指标、依赖服务健康度、最近部署、相关告警聚合)让事故指挥官在 60 秒内建立态势感知。恢复阶段:平台的标准化部署通道让回滚成为一键操作(且回滚本身走金丝雀验证——回滚也可能引入问题,如数据库 schema 已变更);自助扩缩容能力应对流量型事故(突发流量导致的容量事故,团队可以立即自助扩容而无需等待基础设施审批)。复盘阶段:平台数据的完整性决定复盘质量——部署历史、告警时间线、指标快照、追踪样本、操作审计日志(谁在事故中执行了什么操作)全部可回溯,复盘报告的时间线由平台数据自动生成(而非靠记忆拼凑);复盘产出的行动项中,平台类行动(「这个服务的默认告警缺失」「回滚流程需要自动化」)进入平台团队 backlog 并公开追踪。事故驱动的平台改进是最有说服力的投资论证:每次大事故复盘回答「平台能力如何能让这次事故更快发现/诊断/恢复」,累积的案例库就是平台路线图的「可靠性证据链」——向管理层争取平台投资时,「上个季度的 3 次 P1 事故,如果有 X 能力可以各缩短 40 分钟」比任何抽象的生产力论证都有力。
代码示例
/* 示例 1:OTel Collector 平台管道——采集侧的策略执行点 */
/* DaemonSet 模式部署,处理全节点应用信号:标准化、脱敏、采样、路由 */
apiVersion: v1
kind: ConfigMap
metadata:
name: otel-collector-platform
namespace: observability
data:
relay: |
receivers:
otlp:
protocols:
grpc: { endpoint: 0.0.0.0:4317 }
http: { endpoint: 0.0.0.0:4318 }
prometheus:
config:
scrape_configs:
- job_name: platform-nodes
kubernetes_sd_configs: [{ role: node }]
processors:
/* 属性标准化:把各应用的异构标签映射到平台四维标签体系 */
transform/normalize:
trace_statements:
- context: resource
statements:
- set(attributes["service"], attributes["service.name"])
- set(attributes["platform.acme.com/team"], attributes["team"])
- delete_key(attributes, "service.name")
/* 敏感数据脱敏:采集侧遮蔽,敏感内容不进入存储 */
redaction:
blocked_values:
- "4[0-9]{12}(?:[0-9]{3})?" /* 信用卡号 */
- "[0-9]{17}[0-9Xx]" /* 身份证号 */
- "(?i)(api[_-]?key|token|secret)=[^&\s]+"
/* 尾采样:错误与慢请求全保留,正常流量 5% */
tail_sampling:
decision_wait: 10s
policies:
- name: keep-errors
type: status_code
status_code: { status_codes: [ERROR] }
- name: keep-slow
type: latency
latency: { threshold_ms: 2000 }
- name: sample-normal
type: probabilistic
probabilistic: { sampling_percentage: 5 }
memory_limiter:
check_interval: 1s
limit_mib: 1536
exporters:
prometheusremotewrite:
endpoint: http://mimir.observability:9009/api/v1/push
external_labels: { cluster: prod-ap-southeast-1 }
otlphttp/tempo:
endpoint: http://tempo.observability:4318
loki:
endpoint: http://loki.observability:3100/loki/api/v1/push
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, transform/normalize, redaction, tail_sampling]
exporters: [otlphttp/tempo]
metrics:
receivers: [otlp, prometheus]
processors: [memory_limiter, transform/normalize]
exporters: [prometheusremotewrite]
logs:
receivers: [otlp]
processors: [memory_limiter, redaction]
exporters: [loki]解释:这份 OTel Collector 配置是「可观测性即服务」架构中平台策略的集中执行点,四个 processor 各承担一类平台职责。transform/normalize 实施标签标准化:不同团队的应用可能用 service.name(OTel 语义约定)、service(Prometheus 习惯)或自定义标签指代同一概念,Collector 在采集侧统一映射到平台四维标签体系——这是「三个一键」关联体验的前提(Grafana 的日志→追踪跳转依赖 trace_id 与 service 标签的一致性);标准化放在 Collector 而非要求应用侧统一,是「平台吸收复杂性」的典型:应用用自然的约定,平台负责翻译。redaction 处理器实施采集侧脱敏:信用卡号、身份证号、api_key/token/secret 模式的正则匹配在数据离开节点前完成遮蔽——这个位置选择是安全设计的关键:脱敏在存储之前意味着敏感数据根本不进入可观测性后端,即使存储被未授权访问也无泄漏;对比「存储后查询侧脱敏」方案,采集侧脱敏的防御深度更强。tail_sampling 实施智能采样:错误 trace 与超过 2 秒的慢 trace 100% 保留(排障最需要的数据一个不丢),正常流量概率采样 5%(数据量降 95%)——尾采样必须基于完整 trace 决策(一个 trace 的根 span 正常但某个子 span 报错,头采样可能已丢弃),因此只能在 Collector 层做,decision_wait: 10s 是等待 trace 完整的窗口。memory_limiter 是 Collector 自身的稳定性护栏(防止数据洪峰打爆 Collector 内存,触发背压而非崩溃)。pipelines 的三信号分离让每类信号有独立的处理链(traces 需要采样,logs 不需要;metrics 走 remote write 到 Mimir 长期存储)。多租户扩展:生产环境在 exporters 前增加 routing processor,按 team 属性路由到不同的租户端点,实施数据隔离与配额。/* 示例 2:平台 SLO 定义——多窗口多燃烧率告警的完整实现 */
/* 以「环境创建能力」为例:SLO = 99% 的请求在 20 分钟内成功 */
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: platform-env-creation-slo
namespace: platform-system
labels:
platform.acme.com/slo-owner: platform-team
spec:
groups:
- name: env-creation-slo
rules:
/* SLI 记录规则: 好事件比率(成功且 20 分钟内完成) */
- record: sli:env_creation:good_ratio
expr: |
sum(rate(platform_workflow_completed_total{workflow="env-creation",
outcome="success", duration_bucket="under-20m"}[5m]))
/
sum(rate(platform_workflow_completed_total{workflow="env-creation"}[5m]))
/* 燃烧率: 相对于允许错误率(1%)的燃烧速度 */
- record: sli:env_creation:burn_rate
expr: (1 - sli:env_creation:good_ratio) / 0.01
/* P1 紧急告警: 1h 窗口 14.4x 燃烧率(2% 预算/小时消耗) */
- alert: EnvCreationSLOBurnCritical
expr: |
sli:env_creation:burn_rate{window="1h"} > 14.4
and
sli:env_creation:burn_rate{window="5m"} > 14.4
for: 2m
labels:
severity: page
slo: env-creation
annotations:
summary: "环境创建能力 SLO 快速燃烧(1h 燃烧率 {{ $value }}x)"
description: >
过去 1 小时的错误率是 SLO 允许值的 {{ $value }} 倍。
按此速度错误预算将在数小时内耗尽。
runbook: "https://platform.acme.internal/runbooks/env-creation-slo"
dashboard: "https://grafana.acme.internal/d/platform-env-creation"
/* P2 工单告警: 6h 窗口 6x 燃烧率(慢性劣化) */
- alert: EnvCreationSLOBurnWarning
expr: |
sli:env_creation:burn_rate{window="6h"} > 6
and
sli:env_creation:burn_rate{window="30m"} > 6
for: 15m
labels:
severity: ticket
slo: env-creation
annotations:
summary: "环境创建能力慢性劣化(6h 燃烧率 {{ $value }}x)"
runbook: "https://platform.acme.internal/runbooks/env-creation-slo"
/* 错误预算余量: 30 天滚动窗口的剩余预算百分比 */
- record: slo:env_creation:budget_remaining
expr: |
1 - (
sum(increase(platform_workflow_completed_total{workflow="env-creation",
outcome!="success"}[30d]))
/
sum(increase(platform_workflow_completed_total{workflow="env-creation"}[30d]))
) / 0.01解释:这份 PrometheusRule 是平台 SLO 工程的完整参考实现,展示了从 SLI 定义到分级告警到预算追踪的全链条。SLI 设计的细节:good_ratio 的分子同时要求 outcome=success 与 duration_bucket=under-20m——「成功但花了 40 分钟」不算好事件,因为 SLO 承诺的是「20 分钟内成功」的复合体验;duration_bucket 由工作流引擎在上报事件时计算(平台埋点设计需要预先考虑 SLI 的可计算性——这是「SLO 驱动埋点」的实践)。燃烧率(burn rate)的数学:(1 - SLI) / 允许错误率,值为 1 表示恰好按 SLO 允许的速度消耗预算,14.4 表示 14.4 倍速——14.4x 持续 1 个月会消耗 1440% 的预算,即 30 天预算在约 2 天耗尽,因此 1h 窗口 14.4x 是「急性大出血」的信号,值得页呼。双窗口条件(1h AND 5m 都超阈值)是多窗口模式的核心:只看长窗口会对刚发生的故障反应迟钝(1 小时数据稀释了 5 分钟前开始的故障),只看短窗口会被统计噪音误触发(5 分钟内的随机波动);两个窗口同时超阈值才告警,兼顾灵敏度与精确率——Google SRE Workbook 验证这组参数把误报率控制在可接受水平。P1/P2 的分级路由通过 severity 标签实现(page → PagerDuty 页呼 on-call,ticket → 创建工作项),annotations 的三件套(summary 说症状、runbook 给步骤、dashboard 供下钻)落实「每条告警可操作」原则。budget_remaining 记录规则支撑错误预算的运营决策:这个值渲染在平台状态页上(用户可见平台的可靠性承诺兑现情况),也驱动平台团队的变更策略(预算 < 20% 时冻结非必要变更)。slo-owner 标签保证每条规则有主,季度审查时按 owner 分组评估告警质量。/* 示例 3:平台自动生成的服务仪表盘——Grafana Dashboard as Code */
/* 服务创建时由平台工作流自动生成,JSON 模型的 Terraform 风格片段 */
resource "grafana_dashboard" "service_standard" {
for_each = var.services
config_json = jsonencode({
title = "${each.key} - 服务标准视图"
uid = "svc-${each.key}"
tags = ["platform-generated", "golden-path-v3"]
timezone = "browser"
refresh = "30s"
templating = { list = [
{ name = "environment", type = "query",
query = "label_values(up{service="${each.key}"}, environment)",
current = { text = "production", value = "production" } }
]}
annotations = { list = [
/* 部署事件标记: 指标曲线上的竖线,事故定位的第一线索 */
{ name = "Deployments", datasource = "Prometheus",
expr = "changes(platform_deployment_events_total{service="${each.key}"}[1m]) > 0",
iconColor = "blue", tagKeys = "version,actor" }
]}
panels = [
{ title = "请求率 (R)", type = "timeseries", gridPos = { h = 8, w = 8, x = 0, y = 0 },
targets = [{ expr = "sum(rate(http_server_duration_count{service="${each.key}", environment="$environment"}[5m])) by (http_route)" }] },
{ title = "错误率 (E)", type = "timeseries", gridPos = { h = 8, w = 8, x = 8, y = 0 },
targets = [{ expr = "sum(rate(http_server_duration_count{service="${each.key}", environment="$environment", http_response_status_code=~"5.."}[5m])) / sum(rate(http_server_duration_count{service="${each.key}", environment="$environment"}[5m]))" }],
thresholds = { steps = [
{ color = "green", value = null }, { color = "red", value = 0.01 } ] } },
{ title = "延迟分布 (D)", type = "timeseries", gridPos = { h = 8, w = 8, x = 16, y = 0 },
targets = [
{ expr = "histogram_quantile(0.99, sum(rate(http_server_duration_bucket{service="${each.key}", environment="$environment"}[5m])) by (le))", legendFormat = "p99" },
{ expr = "histogram_quantile(0.50, sum(rate(http_server_duration_bucket{service="${each.key}", environment="$environment"}[5m])) by (le))", legendFormat = "p50" } ] },
{ title = "SLO 错误预算余量 (30d)", type = "gauge", gridPos = { h = 8, w = 6, x = 0, y = 8 },
targets = [{ expr = "slo:service_${each.key}:budget_remaining" }] },
{ title = "资源用量 vs 请求", type = "timeseries", gridPos = { h = 8, w = 10, x = 6, y = 8 },
targets = [
{ expr = "sum(container_memory_working_set_bytes{namespace="${each.value.namespace}"})", legendFormat = "实际内存" },
{ expr = "sum(kube_pod_container_resource_requests{namespace="${each.value.namespace}", resource="memory"})", legendFormat = "请求值" } ] },
{ title = "最近部署", type = "table", gridPos = { h = 8, w = 8, x = 16, y = 8 },
targets = [{ expr = "topk(10, platform_deployment_info{service="${each.key}"})", format = "table", instant = true }] }
]
})
}解释:Dashboard as Code 是「标准呈现层」的实现机制——服务创建时平台工作流自动执行这段 Terraform(或等价的 API 调用),为每个新服务生成统一布局的标准仪表盘。设计决策逐一分析。布局的信息架构:第一行是 RED 三件套(请求率、错误率、延迟分布)——排障时 90% 的问题从这三个面板开始(错误率升高?哪个路由?延迟劣化?p99 还是 p50?);错误率面板的 threshold 在 1% 处画红线(与 SLO 对齐,视觉即标准);第二行是 SLO 预算 gauge(可靠性状态的单值摘要)、资源用量 vs 请求对比(容量问题的信号:实际用量贴近请求值说明需要扩容或右尺寸化)、最近部署表(变更关联——「问题开始时间附近的部署」是排障第一假设的数据支撑)。部署事件 annotation 是画龙点睛之笔:所有时序面板上自动叠加部署时刻的蓝色竖线(带 version 与 actor 标签),「错误率在竖线后立即爬升」的视觉模式让变更归因零成本——这个设计源自 Google 内部监控的长期实践,平台把它标准化到每个服务。templating 的 environment 变量让同一仪表盘切换环境视图(生产/预发对比排障)。tags 中的 platform-generated 与 golden-path-v3 支持仪表盘的批量管理:黄金路径 v4 升级仪表盘布局时,平台按 tag 搜索全部 v3 仪表盘并批量更新(Grafana 的 folder/团队权限设计保证平台可以更新自动生成的仪表盘,而团队自建仪表盘不受影响——「平台生成的归平台,团队自定义的归团队」的所有权分离)。for_each = var.services 的批量生成模式意味着仪表盘永远与服务目录同步:新服务自动有仪表盘,服务下线自动清理(Terraform state 移除即删除)——「监控接入率 100%」由此获得结构性保证而非纪律保证。/* 示例 4:平台状态页的数据源——健康聚合 API 的实现骨架 */
/* 聚合各平台能力的 SLO 状态、事故与错误预算,供状态页与通知消费 */
from dataclasses import dataclass
from enum import Enum
import httpx, asyncio
class HealthState(Enum):
OPERATIONAL = "operational"
DEGRADED = "degraded" /* SLO 燃烧率 > 1 但预算充足 */
BUDGET_AT_RISK = "budget_at_risk" /* 30d 错误预算余量 < 20% */
OUTAGE = "outage" /* 能力不可用或 P1 事故进行中 */
@dataclass
class CapabilityStatus:
name: str /* 如 "环境创建", "生产部署", "目录查询" */
state: HealthState
slo_target: float /* 0.99 */
sli_current: float /* 过去 1h 的实际好事件比率 */
budget_remaining: float /* 30d 滚动预算余量百分比 */
active_incidents: list /* 进行中的事故(标题、开始时间、状态页链接) */
p90_duration: str /* 能力性能摘要,如 "11m" */
async def fetch_prometheus(query: str) -> float:
async with httpx.AsyncClient() as client:
r = await client.get("http://mimir.observability:9009/prometheus/api/v1/query",
params={"query": query})
result = r.json()["data"]["result"]
return float(result[0]["value"][1]) if result else 0.0
async def aggregate_capability(name: str, slo: float) -> CapabilityStatus:
sli = await fetch_prometheus(f'sli:{name}:good_ratio{{window="1h"}}')
budget = await fetch_prometheus(f'slo:{name}:budget_remaining')
burn = await fetch_prometheus(f'sli:{name}:burn_rate{{window="1h"}}')
incidents = await fetch_active_incidents(name) /* 事故管理系统 API */
/* 状态判定逻辑: 事故 > 预算风险 > 燃烧劣化 > 正常 */
if incidents:
state = HealthState.OUTAGE
elif budget < 0.2:
state = HealthState.BUDGET_AT_RISK
elif burn > 1.0 and sli < slo:
state = HealthState.DEGRADED
else:
state = HealthState.OPERATIONAL
return CapabilityStatus(name, state, slo, sli, budget, incidents,
await fetch_p90(name))
/* 状态页渲染: 每能力一行(绿/黄/橙/红),附 90 天历史条带图、 */
/* 进行中事故的实时更新、维护日历、订阅通知(能力劣化时邮件/Slack) */解释:平台状态页是平台与用户之间的「信任界面」,这个聚合服务是其数据后端,设计中有几个值得展开的决策。能力导向而非组件导向:状态页的行是「环境创建」「生产部署」「目录查询」等用户能力,而非「Backstage」「ArgoCD」「Crossplane」等内部组件——用户关心「我能不能创建环境」,不关心哪个组件故障;组件级健康是平台团队的内部仪表盘,能力级状态才是对外契约。四级状态模型的判定优先级(事故 > 预算风险 > 燃烧劣化 > 正常)编码了严重性排序:OUTAGE 有进行中事故(人工确认的最高优先级信号);BUDGET_AT_RISK 是「尚未故障但可靠性余量告急」的预警态——这个状态对外公开是成熟度的标志(多数组织只公开「好/坏」二元状态,预算预警的透明化让用户理解平台团队为何冻结变更);DEGRADED 用「燃烧率 > 1 且 SLI 低于目标」双条件判定,避免单一指标的噪音误判。数据来源的组合:SLI 与预算来自 Prometheus(示例 2 的记录规则),事故来自事故管理系统 API(PagerDuty/Opsgenie/自研),P90 时长来自工作流引擎的度量——状态页是平台可观测性数据的「用户视图聚合」,其实现质量直接依赖底层埋点的完整性。运营细节决定状态页的公信力:历史条带图(90 天每日状态色块)让用户看到长期趋势而非孤立快照;维护日历提前公布计划内维护(维护期间的状态标注「计划维护」而非「故障」);订阅通知让用户主动选择关注的能力(环境创建劣化时通知我)——被动等待用户查看状态页是不够的,主动通知把「用户发现平台故障」逆转为「平台告知用户故障」,这个顺序差异就是信任差异。/* 示例 5:告警质量度量——用数据治理告警噪音 */
/* 平台按月统计每条告警规则的质量指标,驱动自动整改流程 */
groups:
- name: alert-quality
interval: 1h
rules:
/* 每条规则的月度触发次数 */
- record: alert_quality:firing_count:30d
expr: |
sum by (alertname, namespace, slo_owner) (
increase(ALERTS{alertstate="firing"}[30d])
)
/* 页呼级告警的「无操作触发」比例——触发后 30 分钟内 */
/* 无任何 ack/操作记录的告警,视为疑似噪音(需事故系统数据 join)*/
- record: alert_quality:noop_rate:30d
expr: |
sum by (alertname) (platform_alerts_noop_total[30d])
/
sum by (alertname) (platform_alerts_fired_total[30d])
/* 静音时长占比: 规则被团队静音的时间 / 总时间 */
- record: alert_quality:silence_ratio:30d
expr: |
sum by (alertname) (increase(amtool_silence_duration_seconds_total[30d]))
/ (30 * 86400)
---
/* 告警质量审查的自动化流程(平台 CI 中的月度任务,伪代码) */
/* for rule in all_alert_rules: */
/* metrics = query(rule) */
/* if metrics.noop_rate > 0.5: */
/* create_ticket(owner=rule.slo_owner, priority="alert-quality", */
/* body=f"告警 {rule.name} 过去 30 天触发 {metrics.firing_count} 次," */
/* f"其中 {metrics.noop_rate:.0%} 无人处理。" */
/* f"请评估: 调整阈值 / 降级为工单 / 删除规则。" */
/* f"连续 2 个月未整改将自动降级为 severity: info。") */
/* if metrics.firing_count == 0 (90d): */
/* flag_as_possibly_dead(rule) /* 从未触发的规则可能查询已失效 */ */解释:告警体系的熵增是必然的——服务在变、负载模式在变、阈值会过时,没有治理机制的告警系统必然滑向噪音海洋。这个示例把「告警质量」本身变成被度量的对象,用数据驱动治理闭环。三个质量指标的设计逻辑:firing_count 是基础量(高频触发的规则要么是真实问题未修复——应推动根因解决,要么是阈值过敏——应调整);noop_rate(无操作率)是精确率的行为学代理——真正的告警会引发人的响应(ack、查看仪表盘、执行 runbook、回滚部署),触发后 30 分钟内无任何相关操作的页呼级告警,大概率被 on-call 判定为「不用管」,即噪音;这个指标需要告警系统与操作审计数据的 join(平台把两者都掌握在手里才可能计算——这是平台化可观测性的独特能力);silence_ratio 是最诚实的信号——团队用静音投票,长期被静音的规则已经事实死亡,却还在消耗注意力与维护成本。自动化审查流程的设计体现「渐进施压」:第一次超标创建工单给规则 owner(附数据与三个整改选项),给一个月整改期;连续两个月未整改自动降级为 info 级(不再页呼)——自动降级是关键威慑,它把「整改告警」从道德义务变为利益相关(不整改就失去告警保护,owner 需要显式确认接受)。「从未触发」的规则同样被标记:90 天零触发可能意味着规则健康(系统稳定),也可能意味着查询失效(指标改名、标签变更后查询永远为空)——后者是「沉默的守护失效」,比噪音更危险,需要人工确认。这套机制的运营成果可以量化汇报:「季度告警治理:清理低质量规则 47 条,页呼量下降 62%,页呼精确率从 41% 提升到 78%」——on-call 生活质量的改善是平台可观测性最得人心的成就。实验笔记
【实验目标】本实验构建一个「可观测性即服务」的最小闭环:为示例服务实现默认监控接入(指标 + 日志 + 追踪)、自动生成标准仪表盘、配置 SLO 与多窗口燃烧率告警,并搭建一个简易平台状态页。实验模拟平台团队的完整交付:业务团队零配置获得生产级可观测性。预计耗时 6-8 小时。
【环境准备】kind 集群(建议 8GB+ 内存分配,可观测性栈资源消耗较大);kube-prometheus-stack(helm 安装,含 Prometheus + Grafana + Alertmanager);Loki + Promtail(helm,日志聚合);Tempo(helm,追踪后端)+ OpenTelemetry Collector(helm chart opentelemetry-collector);OTel Demo 应用(opentelemetry-demo,官方微服务演示应用,含 10+ 服务、完整的三大信号输出——强烈推荐用它替代自写应用,节省大量时间);alertmanager 配置一个 webhook 接收器(可用 requestbin 或本地 nc 监听观察告警 payload)。
【步骤一:部署可观测性栈与 Demo 应用(90 分钟)】按顺序安装 kube-prometheus-stack、loki-stack、tempo、otel-collector,然后部署 opentelemetry-demo(helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts)。验证三大信号流通:Grafana 中查询 demo 应用的指标(如 app_requests_total);Loki 中查询日志({service_name=~".+"});Tempo 中搜索追踪(Grafana Explore → Tempo 数据源 → 按 service 搜索)。画出你环境中的信号流图:应用 → Collector(哪个模式?DaemonSet 还是 Deployment?)→ 各后端。检查 Collector 配置中的 pipelines 结构,对照本章代码示例 1 找出差异。
【步骤二:标准化与脱敏管道(75 分钟)】修改 OTel Collector 配置,添加两个 processor:(1)transform processor——为所有信号注入统一标签 platform.acme.com/lab=true 与 cluster=kind-lab(模拟平台的属性标准化);(2)redaction processor——配置一条信用卡号正则与一条 token 模式(参考示例 1)。验证:向 demo 应用的某个端点发送含测试信用卡号(4111 1111 1111 1111)的请求(或向日志写入含该模式的行),在 Loki/Tempo 中确认敏感模式已被遮蔽为 ***;确认新标签出现在指标与追踪中。记录 redaction 的性能影响观察(Collector 的 CPU 用量变化,通过 Grafana 的 Collector 自身监控查看)。
【步骤三:SLO 与燃烧率告警(90 分钟)】选择一个 demo 服务(如 checkout 或 frontend),为其定义 SLO:请求成功率(非 5xx 占比)目标 99%。实现:(1)编写 SLI 记录规则(good_ratio,基于 http 请求指标按 status code 分解);(2)编写燃烧率记录规则(1h 与 6h 窗口——用 offset 或 subquery 实现窗口比率);(3)配置两条告警:1h 窗口 14.4x(severity: page)与 6h 窗口 6x(severity: ticket),annotations 含 summary/runbook/dashboard 三要素(参考示例 2 的结构);(4)用 Prometheus 的告警测试工具(promtool test rules)编写单元测试:构造时序样本验证燃烧率计算与告警触发条件。然后制造真实故障:把 demo 的某个服务镜像替换为高错误率版本(或注入故障——demo 自带 fault injection 功能,通过 feature flag 服务开启 checkout 的失败注入),观察:告警多久触发?Alertmanager 的 webhook 收到什么 payload?恢复故障后告警多久解除?记录完整时间线。
【步骤四:标准仪表盘与状态页(90 分钟)】(1)用 Grafana 的 dashboard JSON 模型为 demo 服务手工构建「标准视图」仪表盘:RED 三面板 + 部署事件 annotation(用 demo 的重启事件模拟)+ SLO 预算 gauge,导出 JSON 并思考:如何模板化为「每个服务自动生成」(变量抽取、命名约定)?(2)搭建简易状态页:用一个静态 HTML + JavaScript 定时查询 Prometheus HTTP API(/api/v1/query 查询各服务的 SLI 与燃烧率),按四级状态模型(operational/degraded/budget_at_risk/outage,参考示例 4 的判定逻辑)渲染每个「能力」(demo 的各服务模拟平台能力)的状态色块。部署到集群(nginx 容器)并访问验证:故障注入时状态页是否变红?
【检查清单】(1)三大信号(指标/日志/追踪)在 Grafana 中全部可查询且能相互跳转(日志行的 trace_id 链接到 Tempo 追踪);(2)redaction 验证成功——测试信用卡号在存储中不可见;(3)SLO 记录规则在 Prometheus 中可查询且 promtool 单元测试通过;(4)故障注入后燃烧率告警在预期时间窗口内触发,webhook 收到含 runbook 链接的完整 payload;(5)标准仪表盘包含 RED + annotation + SLO gauge 三类面板;(6)状态页正确反映服务的实时健康状态且故障时变色;(7)实验记录包含信号流图与故障-告警-恢复的完整时间线。
【进阶挑战】(1)配置尾采样:在 Collector 添加 tail_sampling processor(错误 100% 保留、正常 10% 采样),对比采样前后 Tempo 的存储增长率;(2)实现「告警质量度量」:统计实验期间每条告警的触发次数与处理情况,体验示例 5 的 noop_rate 思想;(3)把仪表盘生成自动化:写一个脚本读取「服务清单」(一个 YAML 文件),用 Grafana HTTP API 为每个服务批量创建模板化仪表盘——体验 Dashboard as Code 的规模化机制;(4)多租户初探:部署第二个 OTel Collector 实例模拟「租户 B」,配置路由规则按团队标签分流到不同的 Loki 租户(X-Scope-OrgID),验证查询隔离。
延伸阅读
- 《Observability Engineering》(Charity Majors 等,O'Reilly 2022):可观测性工程的方法论权威,Honeycomb 创始人团队撰写。核心贡献是区分「监控」(已知问题的预定义仪表盘)与「可观测性」(未知问题的探索式分析)——高基数、高维度的数据模型与探索式工作流是平台可观测性设计的思想基础;书中关于告警疲劳与 on-call 可持续性的章节直接支撑本章的告警治理实践。
- 《Site Reliability Workbook》(Google SRE 团队,O'Reilly 2018)第 4-6 章:SLO 工程的实操圣经。多窗口多燃烧率告警的完整推导(为什么是 14.4x 与 6x)、SLI 选择的分类学(可用性/质量/新鲜度/正确性)、错误预算的政策化运营(预算耗尽时冻结发布的具体机制)——本章示例 2 的全部参数都源于此书的推荐值。
- OpenTelemetry 官方文档(opentelemetry.io):重点精读 Collector 的 Configuration 文档(receivers/processors/exporters/pipelines 模型)、Tail Sampling 设计文档与 Semantic Conventions(HTTP、DB、RPC 的标准属性命名)。OTel 的语义约定是平台标签标准化的上游依据——平台自定义标签应尽量复用而非重造约定。
- Grafana 官方文档的 Dashboard as Code 与 Provisioning 章节:仪表盘的文件化管理(provisioning 目录自动加载 JSON)、变量与模板化设计、注解(annotations)的数据源配置。配合 Terraform grafana provider(本章示例 3 的实现基础)可以构建完整的「仪表盘即代码」流水线。
- Loki 官方文档的设计哲学章节(《Loki: like Prometheus, but for logs》):理解「索引标签而非全文」的成本模型——为什么 Loki 的存储成本比 Elasticsearch 低一个数量级,以及这个设计的查询约束(LogQL 的标签选择器优先模式)。平台选择日志后端时,Loki 与 ES 的成本/能力权衡是核心决策输入。
- Argo Rollouts 的 Analysis 文档与 Flagger 项目:渐进式交付的自动分析实现,其 AnalysisTemplate 的 metric provider 抽象展示了「可观测性数据驱动部署决策」的标准接口——本章第 6 章的金丝雀分析与本章的 SLO 告警共享同一套 Prometheus 查询基础设施,两个项目的文档相互印证。
- CNCF可观测性白皮书(Observability White Paper)与 OpenTelemetry 平台工程相关 SIG 材料:行业视角的可观测性标准化趋势,包括 OTel Profiling 信号的演进路线、可观测性管道的多租户模式、以及「可观测性即平台能力」的架构参考——平台团队制定 3 年可观测性路线图时的趋势输入。