第 7 课:Metrics、Logs、Traces 与 SLO Burn Rate

参考答案版:包含完整代码实现与问答题深度参考解析。建议先独立完成练习题后再展开核对。

本课目标与完成标准

本课产出:实现错误预算 burn rate,并设计从服务症状下钻到 GPU/网络/存储根因的观测链。

通过要求:唯一代码填空题通过给定检查;Q1~Q3 都给出因果链;能指出一个正确性边界和一个性能/运营取舍;总分至少 8/10。

与既有六条主线的边界

inference/lesson08 定义服务 SLO;本课关注平台如何持续观测和告警,而不是离线 benchmark。

前置:Linux/网络基础、runtime 补充线、train 分布式章节。本课只补 AI Infra 缺口,不重复已经完成的 kernel 或并行算法推导。

核心心智模型

1. 它是什么,解决什么问题

在由成百上千张高端加速卡构建的大规模 AI 生产基础设施中(包含在线高吞吐大模型推理 Serving 与长周期万卡预训练 Training),平台运营与 SRE 工程师面临着严峻的可观测性与告警困境:

  1. 告警风暴与告警疲劳(Alert Fatigue):
    若依据传统静态底层阈值设置告警(如“GPU 利用率 <80%< 80\%”、“CPU 内存 >90%> 90\%”、“网络发生丢包”),由于分布式训练中定期的 Checkpoint 刷盘、异步数据预取抖动与临时调度重试,值班人员每天会收到数百条虚假警报,导致真正致命的业务事故被海量噪音淹没。

  2. 表面繁荣与业务隐形崩溃(The “GPU 100% Fallacy”):
    监控大屏上 GPU 利用率维持在 100%,看似算力拉满,实际上可能因为 NCCL 集合通信死锁导致的 CUDA 核心空转自旋(Spin-wait)、动态序列异常导致的死循环、或重试风暴,真正的业务有效吞吐(Goodput)早已归零。

  3. 可观测性数据孤岛(Observability Silos):
    时序指标(Metrics)只能看到宏观聚合统计,日志(Logs)零散分布在各个容器与内核缓冲区中,分布式调用链路(Traces)缺乏跨节点的上下文传播。当用户端报错或推理延迟激增时,排查人员无法快速将上层业务症状下钻关联到底层的物理硬件与通信根因。

本课构建现代 AI 算力平台的可观测性三支柱(Metrics, Logs, Traces,如图 7-1 所示),并引入 Google SRE 体系中的错误预算消耗率(Error Budget Burn Rate)告警模型与多窗口分级判定流(如图 7-2 所示),实现从业务影响到硬件根因的精准穿透定位。

2. 它如何工作

(1) AI 基础设施可观测性三支柱(如图 7-1 所示)

flowchart LR
    subgraph Telemetry["集群可观测性三支柱"]
        M["Metrics (GPU 利用率, 温度, ECC, NCCL 吞吐)"]
        L["Logs (内核 dmesg, PyTorch 栈日志, K8s 事件)"]
        T["Traces (分布式跨节点 RPC 与 NCCL 通信耗时)"]
    end
    Telemetry --> BurnRate["SLO 错误预算消耗率 (Burn Rate = 当前故障率 / 允许故障率)"]

图 7-1:集群立体化监控度量与 SLO 错误预算 (Burn Rate) 监控模型

  • Metrics(指标层,秒级聚合):
    依托 Prometheus 与 NVIDIA DCGM-Exporter 导出立体化时序指标。不仅监测宏观的 DCGM_FI_DEV_GPU_UTIL,更深度透视:

    • DCGM_FI_PROF_SM_ACTIVE(SM 真实活跃周期比例);
    • DCGM_FI_PROF_TENSOR_ACTIVE(张量核心 Tensor Core 计算活跃度);
    • DCGM_FI_DEV_POWER_USAGE(物理功耗与热节流状态);
    • DCGM_FI_DEV_ECC_DBE_VOL_TOTAL(未纠正双位 ECC 错误计数)。
  • Logs(日志层,离散结构化事件):
    汇聚操作系统内核日志(dmesg 捕获 PCIe AER 错误、NVIDIA Xid 硬件异常报错)、Kubernetes 事件(Pod OOMKilled、NodeNotReady)、以及通信栈日志(NCCL_DEBUG=INFO 记录 Communicator 握手状态与超时挂起)。

  • Traces(分布式链路追踪,上下文穿透):
    基于 OpenTelemetry 标准。在线推理网关为每个传入请求注入全局唯一的 TraceID,跨越 Prefill 阶段、Decode 阶段、KV Cache 调度与跨卡张量并行(TP)通信。一旦发生 p99 延迟毛刺,可通过 TraceID 毫秒级还原该请求在每个算子、内存搬运及网络传输上的精确时间跨度。

(2) 错误预算与 Burn Rate 数学模型

在现代可靠性工程中,告警应当基于用户可见的服务等级目标(Service Level Objective, SLO): 设系统设定的 SLO 目标可用度为 TSLOT_{\text{SLO}}(如 99.9%,即 0.9990.999)。
系统在统计周期内允许的错误预算比例为: Error Budget=1−TSLO=1−0.999=0.001(0.1%)\text{Error Budget} = 1 - T_{\text{SLO}} = 1 - 0.999 = 0.001 \quad (0.1\%)

设在观测时间窗口内,总服务请求数(或训练 Step 总数)为 NtotalN_{\text{total}},发生异常、超时或失败的事件数为 NbadN_{\text{bad}},实际观测故障率为: Observed Bad Rate=NbadNtotal\text{Observed Bad Rate} = \frac{N_{\text{bad}}}{N_{\text{total}}}

错误预算消耗率(Burn Rate)定义为实际故障率相对于错误预算的消耗倍速: Burn Rate=Observed Bad RateError Budget=Nbad/Ntotal1−TSLO\text{Burn Rate} = \frac{\text{Observed Bad Rate}}{\text{Error Budget}} = \frac{N_{\text{bad}} / N_{\text{total}}}{1 - T_{\text{SLO}}}

  • 物理直观意义:
    • Burn Rate=1.0\text{Burn Rate} = 1.0:故障率恰好与预算持平,30 天的错误预算将在整整 30 天内平稳耗尽;
    • Burn Rate=10.0\text{Burn Rate} = 10.0:消耗速度是基准的 10 倍,30 天的预算将在 3 天内耗尽;
    • Burn Rate=14.4\text{Burn Rate} = 14.4:30 天的预算将在 50 小时(约 2 天)内耗尽,意味着短短 1 小时内就烧掉了整个月预算的 2%!

(3) 多窗口多消耗率联合告警策略

如图 7-2 所示,为彻底杜绝毛刺误报并极速捕获真正严重的事故,工业界执行多窗口联合校验:

flowchart TD
    MetricStream["时序指标持续采集 (Prometheus + DCGM-Exporter)"] --> EvalWindow["多窗口联合评估: 1小时消耗率 > 14.4x 或 6小时 > 6x"]
    EvalWindow --> Spike{"是否发生急剧突发严重故障?"}
    Spike -->|"是 (高 Burn Rate)"| P1Alert["触发 P1 紧急告警,直接呼叫值班并启动自动下线隔离"]
    Spike -->|"否 (慢速漂移)"| P3Ticket["创建 P3 低优先级工单排查慢掉队节点"]
    P1Alert --> HotMigration["触发作业热迁移与断点恢复自愈"]

图 7-2:多窗口 SLO 消耗率告警分级判定与自动化应急响应流程

  • P1 紧急电话呼叫(Page On-call):
    要求 1 小时窗口的 Burn Rate >14.4> 14.4 且 最近 5 分钟窗口的 Burn Rate >14.4> 14.4。长窗口确认已经造成了实质性的预算大出血,短窗口确认故障仍在持续发生,触发紧急呼叫并启动作业热迁移与硬件隔离自愈;

  • P2 工单处理(Ticket):
    要求 6 小时窗口的 Burn Rate >6> 6 且 30 分钟窗口的 Burn Rate >6> 6。表明系统存在中等程度的慢性出血,通知值班工程师日间排查;

  • P3 慢速巡检:
    36 小时窗口 Burn Rate >1> 1,捕获由慢掉队卡(Straggler)或亚健康网络链路引发的轻微漂移。

3. 正确性条件与常见误区

  • 误区一:盲目迷信单一指标“GPU 利用率 = 100%”
    在英伟达驱动机制中,nvidia-smi 报告的 GPU Utilization 定义为“在采样周期内,至少有一个 Kernel 在 GPU 上执行的时间比例”。若模型代码中由于线程死锁发生 CUDA 同步自旋(Spin-wait),或者 PyTorch 算子不断触发异常并进入死循环,SM 利用率可能持续稳定在 100%,但实际没有产生任何有价值的 token 或梯度更新。必须以业务端有效吞吐(Goodput,如每秒生成的 Tokens 数或有效训练 Step 进度)作为真正的第一指标,将 GPU Utilization 降级为辅助诊断参考。

  • 误区二:短窗口发生毛刺立即发送呼叫警报(Page)
    在秒级短窗口(如 1 分钟)内,偶发的大 Prompt 批次涌入或 Checkpoint 刷盘可能导致错误率瞬间跳高,产生极高的瞬时 Burn Rate。若直接据此触发电话呼叫,值班人员将被海量自愈的毛刺折磨至筋疲力尽。必须采用长短窗口双重确认机制(Short & Long Window Dual-Check),只有当长窗口确认了总体预算的大幅削减,且短窗口确认故障仍在持续发生时,才发出紧急呼叫。

  • 误区三:分布式 Trace 采用无差别均匀采样或仅采样成功请求
    为了降低网络与存储开销,系统通常会配置链路追踪采样率(如 1%)。若采用简单的随机采样,发生超时、异常或 HTTP 500 的罕见错误请求几乎 100% 会被丢弃,导致 Trace 系统中全是健康的绿线,在故障发生时无法提供任何排障价值。必须部署尾部自适应采样(Tail-based Sampling):在内存中缓冲完整 Trace,一旦判定该链路包含错误状态码或 p99 尾延迟严重发散,强制 100% 全量落盘上报。

4. 性能与工程取舍

  • 可观测性颗粒度与探针开销(Observer Effect / Probe Overhead):
    无死角的极致观测(例如在每个 CUDA Kernel 发射时注入 CUPTI 回调,或开启每秒数十万次的详细系统调用追踪)会抢占 GPU 驱动栈和 Host CPU 周期,甚至改变多线程执行时序,掩盖原有的竞态条件。在生产集群中,默认只开启秒级 DCGM 采样与轻量级分布式 Trace,仅在调试环境中才开启深度 CUPTI Profiler。

  • 错误预算的业务容忍度设定:
    追求绝对的 100% 可用度在物理分布式系统中是不可能实现的(代码中强制要求 0<slo_target<10 < \text{slo\_target} < 1),过度追求 99.999% 的可用性会导致研发迭代被频繁冻结。错误预算的本质是为工程团队提供安全创新的额度,当预算充裕时允许大胆发布新模型与新算子;当预算被快速 Burn 掉时,必须强制进入稳定性封版熔断。

具体演示

设在线大模型推理服务设定的可用度目标为 SLO=99.9%\text{SLO} = 99.9\%(0.9990.999),对应的错误预算为: Error Budget=1−0.999=0.001(0.1%)\text{Error Budget} = 1 - 0.999 = 0.001 \quad (0.1\%)

在过去 1 小时的监控窗口内,网关共处理了 10,00010,000 次请求,其中有 100100 次请求发生超时或 HTTP 500 错误: Observed Bad Rate=10010,000=0.01(1.0%)\text{Observed Bad Rate} = \frac{100}{10,000} = 0.01 \quad (1.0\%)

此时系统的错误预算消耗率为: Burn Rate=0.010.001=10.0\text{Burn Rate} = \frac{0.01}{0.001} = 10.0

这意味着当前系统的错误率是允许预算的 10 倍速。如果保持此故障速度,原本计划供全月 30 天使用的错误预算,将在仅仅 30/10=330 / 10 = 3 天内彻底归零!监控系统应立刻触发严重告警。若观测故障数为 0,则 Burn Rate 为 0。

请先独立复述“输入 → 状态变化 → 输出/指标”,再开始填空。

实践任务:唯一代码填空题

补齐 burn rate,并拒绝没有错误预算的 100% SLO。

只能修改 TODO/______ 位置,不得删除断言或放宽通过条件。

Code
def burn_rate(bad_events, total_events, slo_target):
    if total_events <= 0 or bad_events < 0 or bad_events > total_events or not 0 < slo_target < 1:
        raise ValueError("invalid SLO window")
    observed_bad = bad_events / total_events
    error_budget = 1 - slo_target
    # TODO:当前坏事件比例消耗预算的倍速。
    return ______

assert abs(burn_rate(100, 10_000, 0.999) - 10.0) < 1e-9
assert burn_rate(0, 10_000, 0.999) == 0

检查方法

运行本单元格,所有断言必须通过;再补一个边界输入并解释预期。

Q1

为什么 GPU utilization=100% 可能是坏消息也可能是好消息?

你的答案:

Q2

短窗口 burn 高、长窗口正常时是否立即 page?

你的答案:

Q3

trace 采样只保留成功请求,会造成什么诊断盲区?

你的答案:

评分规则

  • 代码 4 分:正常输入 2 分、边界输入 1 分、解释 1 分;
  • Q1~Q3 各 2 分;
  • 一票否决:混淆测量与推测、忽略租户/请求隔离、用平均值掩盖尾延迟、删除失败路径。

参考答案(仅 answer 分支)

先独立完成。核对后请改变一个规模或故障条件重新推演。

Code
def burn_rate(bad_events, total_events, slo_target):
    if total_events <= 0 or bad_events < 0 or bad_events > total_events or not 0 < slo_target < 1:
        raise ValueError("invalid SLO window")
    observed_bad = bad_events / total_events
    error_budget = 1 - slo_target
    return observed_bad / error_budget

assert abs(burn_rate(100, 10_000, 0.999) - 10.0) < 1e-9
assert burn_rate(0, 10_000, 0.999) == 0

Q1 参考答案

在现代 AI 系统中,单一的“GPU Utilization = 100%”指标具有极强的欺骗性,必须结合业务层产出与微架构指标进行辨证分析:

  1. 属于好消息的场景(算力高效释放):当 GPU Utilization 达到 100%,同时硬件监控显示 Tensor Core 活跃度(DCGM_FI_PROF_TENSOR_ACTIVE)高、显存带宽逼近物理上限、芯片功耗接近 TDP 标称上限,且业务层指标显示单位时间有效计算量(如训练每秒 Step 耗时稳定、推理端 Tokens/s 吞吐达标)符合预期时,说明算力被充分压榨,系统处于健康的高吞吐计算密集型状态;

  2. 属于坏消息的场景(死锁空转与虚假繁荣):英伟达驱动对 GPU Utilization 的统计口径仅是“采样窗口内有任意 Kernel 在 SM 上执行的时间比例”。在以下恶性故障下,指标同样呈现 100%:

    • 集合通信死锁与同步自旋(CUDA Spin-Wait / Barrier Hang):多卡并行中因单卡掉队,其他正常卡停留在 NCCL 集合通信核函数内进行微秒级自旋等待,SM 核心完全被打满,但没有任何实际梯度归约产出;
    • 死循环与异常重试风暴:业务代码捕获了运行时异常但未正确退出,在死循环中持续发起高频无效 Kernel 发射;
    • 低效内存未对齐算子:算子未能使用张量核心,完全退化为低效的普通 CUDA Core 运算,SM 忙碌但算力产出极其低下。必须使用“业务有效产出率(Goodput)”取代裸利用率作为终极衡量标准。

Q2 参考答案

绝对不应立即发起 Page 电话呼叫。在 Google SRE 规范与现代告警架构中,短窗口高消耗率而长窗口正常的现象必须被审慎对待:

  1. 短窗口尖峰极大概率为自愈型瞬时抖动(Transient Spikes):短窗口(如 5 分钟)内的 Burn Rate 飙升,但长窗口(如 1 小时或 6 小时)指标正常,表明这通常是由单次网络瞬时闪断、短时间突发 Incast 流量涌入、或周期性 Checkpoint 刷写引起的短暂波动。这种抖动往往会在几分钟内迅速自愈;

  2. 防范告警疲劳(Alert Fatigue):瞬时抖动消耗的总体错误预算微乎其微(通常不足全月预算的 0.1%)。若短窗口一发生跳变就向值班工程师发送 Page 电话呼叫,工程师将被无休止的误报疲劳轰炸,最终在真正的大事故发生时产生麻木与忽视;

  3. 多窗口双重确认规范(Multi-Window Dual-Confirmation):SRE 黄金告警法则明确要求:触发 P1 紧急 Page 告警必须同时满足两个条件:

    • 长窗口 Burn Rate 超标(确认错误预算已经被实质性、成规模地严重消耗);
    • 短窗口 Burn Rate 同样超标(确认该故障在当下这一刻仍然在持续恶化,而非已经过去的偶发抖动)。若仅短窗口超标,系统应仅在监控控制台记录低优先级的 Warning 事件并保持持续观察。

Q3 参考答案

若在构建分布式链路追踪(Distributed Tracing)系统时,为了节省网络带宽与存储成本而设置了“仅采样成功请求(HTTP 200 / Success Only)”的过滤策略,将造成毁灭性的幸存者偏差(Survivorship Bias)诊断盲区:

  1. 核心故障根因现场完全蒸发:链路追踪系统的根本使命是在服务发生延迟发散或系统崩溃时提供精准排障。若过滤规则排除了失败请求,所有遭遇超时的请求(HTTP 504)、内存耗尽的请求(HTTP 500)、或触发 NCCL 通信超时的跨节点 RPC 链路将被全量丢弃。工程师在 Trace 控制台看到的永远是一片绿色的成功链路,导致排查人员彻底沦为“睁眼瞎”;

  2. 尾延迟(Tail Latency)因果链彻底断裂:绝大多数成功请求往往集中在轻量级且未发生资源竞争的快速黄金路径上,而诱发生产级雪崩的往往是处于 p99/p99.9 尾部的请求(如发生了跨机 NVLink 拥塞、或者大模型 KV Cache 驱逐换页)。丢弃长尾与失败样本,将导致基于 Trace 的火焰图拓扑分析完全失去可信度;

  3. 正确解法:尾部自适应采样(Tail-based Sampling):在分布式 Collector 收集器端维护小容量环形内存缓冲区,全量暂存链路数据。当该请求链路完整结束时,根据最终结果执行判定:凡是包含错误状态码、异常日志、或总耗时超过阈值的 Trace,实行 100% 强制持久化保存;对于正常的快速成功请求则执行极低比例(如 0.1%)的抽样,确保兼顾极低存储成本与 100% 捕获故障现场。

参考资料

API 与平台能力会演进;部署前应按目标版本重新核对。