主题
第六部分 GPU 监控与可观测性(第 22~24 章)
第二~五部分完成了环境搭建、虚拟化共享、K8s 调度与高速网络配置。接下来的问题是:这些昂贵的 GPU 跑得好不好?有没有卡快坏了?利用率是不是只有 5% 却在烧电?
本部分带你从零搭建完整的 GPU 监控体系:从单机
nvidia-smi进阶用法,到 DCGM/dcgm-exporter 指标采集,再到 Grafana 可视化与生产级告警规则,最终交付一套"看得见、告警准、能定位"的监控平台。
第 22 章 nvidia-smi 与监控基础
本章目标
- 掌握
nvidia-smi进阶用法:全量查询、自定义字段、CSV 格式化输出与循环采集 - 正确解读利用率、显存、温度、功耗、降频原因等关键指标,避开常见误区
- 建立"节点 + GPU + 业务"三层监控体系的全局认知;无 GPU 环境也能模拟学习
22.1 nvidia-smi 进阶用法大全
nvidia-smi(NVIDIA System Management Interface)是 GPU 运维的"瑞士军刀"。前面章节我们用过它的默认输出,本节深入它的两大高级模式。
22.1.1 -q:全量信息查询
bash
# 查询所有 GPU 的全部信息(输出很长,适合存档或交给 AI 分析)
nvidia-smi -q
nvidia-smi -q -i 0 # 只看某一张卡(-i 指定索引)
nvidia-smi -q -d TEMPERATURE,POWER,CLOCK,ECC # 只看指定段落-q 的输出按段落组织,运维中最常看的段落:
| 段落 | 关注点 |
|---|---|
Product Name / VBIOS Version | 型号与固件版本 |
Persistence Mode | 是否开启持久模式(生产必须 ON) |
Power Readings | 当前功耗 / 功耗上限 |
Clocks / Clocks Event Reasons | 当前时钟与降频原因(见 22.2) |
Temperature | GPU 核心温度、显存温度、降频阈值 |
ECC Errors / Retired Pages | ECC 错误计数与退役显存页(重要故障信号) |
22.1.2 --query-gpu:自定义字段输出(运维核心技能)
默认输出是给"人"看的,而 --query-gpu 是给"脚本"看的——它让你精确指定要哪些字段、以什么格式输出。
bash
# 基本语法
nvidia-smi --query-gpu=<字段1,字段2,...> --format=csv
# 示例:查询最常用的 5 个字段
nvidia-smi --query-gpu=index,name,utilization.gpu,memory.used,memory.total,temperature.gpu,power.draw \
--format=csv输出示例:
csv
index, name, utilization.gpu [%], memory.used [MiB], memory.total [MiB], temperature.gpu, power.draw [W]
0, NVIDIA A100-SXM4-80GB, 87 %, 62140 MiB, 81920 MiB, 61, 385.22 W常用查询字段对照表:
| 字段 | 含义 | 运维用途 |
|---|---|---|
index / uuid | GPU 序号 / 唯一标识 | 定位具体卡,uuid 跨重启不变 |
name、driver_version | 型号、驱动版本 | 资产清点、版本一致性检查 |
utilization.gpu | SM 利用率百分比(%) | 粗略判断忙闲(注意误区,见 22.2) |
utilization.memory | 显存控制器利用率(%) | 判断显存带宽压力 |
memory.used / memory.total | 已用 / 总显存(MiB) | 显存占用监控 |
temperature.gpu / temperature.memory | 核心 / 显存温度(℃) | 过热告警(显存温度部分卡支持) |
power.draw / power.limit | 当前功耗 / 功耗上限(W) | 功耗与降频分析 |
clocks.sm / clocks.max.sm | SM 当前 / 最大频率(MHz) | 判断是否降频 |
clocks_event_reasons.active | 降频原因(位掩码) | 排查为什么变慢 |
ecc.errors.corrected.volatile.total | 可纠正 ECC 错误总数 | 健康巡检 |
ecc.errors.uncorrected.volatile.total | 不可纠正 ECC 错误总数 | 严重告警信号 |
retired_pages.single_bit_ecc.count | 单比特错误退役页数 | 显存老化评估 |
persistence_mode | 持久模式状态 | 交付检查 |
完整字段列表见
nvidia-smi --help-query-gpu。
22.1.3 循环采集脚本示例
巡检或临时观察训练任务时,常用循环采集脚本:
bash
#!/bin/bash
# gpu_watch.sh —— 每 2 秒采集一次 GPU 关键指标,写入 CSV 日志
LOG=${1:-gpu_metrics_$(date +%Y%m%d_%H%M%S).csv}
FIELDS="timestamp,index,utilization.gpu,utilization.memory,memory.used,temperature.gpu,power.draw,clocks.sm"
echo "采集日志写入: $LOG (Ctrl+C 停止)"
nvidia-smi --query-gpu=$FIELDS --format=csv,noheader,nounits -l 2 >> "$LOG"-l 2 表示每 2 秒循环一次(只看实时画面直接 nvidia-smi -l 1)。配合 nounits(去掉单位)和 noheader(去掉表头),得到的 CSV 可以直接用 pandas 或 Excel 画图分析"训练过程中利用率是否周期性掉零"(常见于数据加载瓶颈)。
22.2 关键指标解读:看懂数字背后的真相
22.2.1 GPU 利用率的误区:100% ≠ 打满算力
utilization.gpu 的官方定义是:在过去采样周期内,GPU 上至少有一个 kernel 在执行的时间占比。这意味着哪怕一个 kernel 只用了 1 个 SM 中的 1 个线程,只要它在运行,这一秒就算"100% 利用率"。典型误区:某任务 util 显示 100%,profiler 却显示 SM 实际活跃占比只有 18%——kernel 大量时间在做显存拷贝、同步等待,或本身并行度很低。
运维启示:
utilization.gpu只能用来判断"卡上有没有活干",不能用来判断"活干得满不满"。- 评估真实算力消耗要用 profiling 指标(见 24.2 的
DCGM_FI_PROF_SM_ACTIVE)。 - 利用率 100% 但训练慢,瓶颈通常在显存带宽、数据加载或通信,而不是"卡不够"。
22.2.2 显存占用
memory.used接近memory.total不代表"快 OOM 了"——PyTorch/TensorFlow 默认会缓存几乎所有空闲显存(caching allocator)。判断真实需求应结合框架内的torch.cuda.max_memory_allocated()。- 显存长期占用但利用率为 0,通常是僵尸进程或忘记释放的任务,是回收资源的第一目标。
22.2.3 温度与功耗
| 指标 | 健康参考(以 A100/H100 为例) |
|---|---|
| GPU 核心温度 | 长期 < 75℃;> 85℃ 需警惕;接近 slowdown 阈值(约 90~95℃)会降频 |
| 显存温度(HBM) | 长期 < 90℃;> 95℃ 需检查风道/散热 |
| 功耗 | 空闲约 60~100W;满载接近 TDP(A100 400W,H100 700W) |
功耗异常低(如满载只有 150W/400W)往往说明降频或供电问题。
22.2.4 时钟降频原因(clocks_event_reasons)
GPU 不会一直跑在最高频率。clocks_event_reasons.active 用位掩码告诉你"现在为什么没跑满频":
| 位标志 | 含义 | 处理建议 |
|---|---|---|
GpuIdle | 卡空闲自动降频省电 | 正常 |
SwPowerCap | 软件功耗封顶触发降频 | 功耗打到 power.limit,正常物理现象 |
HwThermalSlowdown(hw_slowdown) | 硬件过热降频 | 危险:检查风扇、风道、机房温度 |
SwThermalSlowdown | 软件热降频(提前于硬件) | 同上,温度已接近阈值 |
SyncBoost | 多卡组同步 boost 限制 | 一般正常 |
查询命令:
bash
nvidia-smi -q -d CLOCK | grep -A 10 "Clocks Event Reasons"
# 或查询式输出
nvidia-smi --query-gpu=index,clocks_event_reasons.active,\
clocks_event_reasons.sw_power_cap,clocks_event_reasons.hw_thermal_slowdown --format=csv22.3 监控体系全景:三层指标模型
单机的 nvidia-smi 解决不了集群问题。一套完整的 GPU 监控体系分三层:
text
┌─────────────────────────────────────────────────────────┐
│ 第三层:业务指标(训练框架侧) │
│ loss 曲线、吞吐 samples/s、step 时间、MFU │
│ 采集方式:训练代码埋点 → Prometheus / TensorBoard / W&B │
├─────────────────────────────────────────────────────────┤
│ 第二层:GPU 指标(本部分核心) │
│ 利用率、显存、温度、功耗、XID、ECC、NVLink、PCIe 带宽 │
│ 采集方式:dcgm-exporter(DaemonSet 部署,第 23 章) │
├─────────────────────────────────────────────────────────┤
│ 第一层:节点指标 │
│ CPU、内存、磁盘 IO、网络(含 RDMA 网卡)、inode │
│ 采集方式:node-exporter(+ 可选 rdma-exporter) │
└─────────────────────────────────────────────────────────┘为什么要三层?看一个真实排查链路:训练吞吐下降 30% → 业务层(step 时间变长)→ GPU 层(利用率周期性归零)→ 节点层(磁盘 IO 打满,数据加载是瓶颈)。任何单一层的监控都无法完成这个定位。
三层指标统一汇入 Prometheus,由 Grafana 统一展示(第 24 章)。
22.4 无 GPU 环境学习提示
没有 GPU 也能学习本章和后续章节的大部分内容:
- 理解指标结构:dcgm-exporter 的指标格式是公开的,可直接阅读官方字段文档,把每个
DCGM_FI_*字段和nvidia-smi --query-gpu的字段一一对应起来。 - 用假数据搭建演示链路:写一个脚本周期性生成伪造指标,用 node-exporter 的
textfile收集器或迷你 exporter 暴露,接入 Grafana。面板、PromQL、告警规则的设计能力完全可以在假数据上练熟。 - 读真实输出存档:找一份
nvidia-smi -q真实输出(附录或网上),逐段对照 22.1 的表格精读。 - 云实例验证:花几元钱包一小时 T4 实例,把本章命令全部跑一遍,比看十遍文档有效。
本章小结
nvidia-smi -q看全量,--query-gpu --format=csv做脚本化采集,-l循环观察。utilization.gpu = 100%不代表算力打满,只代表"有 kernel 在跑";真实算力要用 PROF 指标评估。- 降频原因看
clocks_event_reasons:功耗封顶多为正常,thermal 降频必须处理。 - 完整监控 = 节点指标(node-exporter)+ GPU 指标(dcgm-exporter)+ 业务指标,三层缺一不可。
- 无 GPU 环境可用模拟数据练习指标、面板与告警设计。
动手实验
- 执行
nvidia-smi --help-query-gpu,找出 5 个本教材未列出的字段,猜测含义并验证。 - 写一个采集脚本:每 5 秒记录所有 GPU 的
utilization.gpu,memory.used,temperature.gpu,power.draw到 CSV,运行 10 分钟(期间跑一个 GPU 任务),画出 4 条曲线。 - 思考题:某卡
utilization.gpu=95%但功耗只有上限的 40%,可能的原因有哪些?(提示:降频、kernel 类型、数据等待) - (无 GPU 环境)编写 bash 脚本生成模拟 CSV 指标文件,字段同实验 2,数值随机但合理(温度 30~85℃)。
第 23 章 DCGM 与 dcgm-exporter
本章目标
- 理解 DCGM 的架构(nv-hostengine、dcgmi)及其与 NVML 的关系
- 掌握
dcgmi常用命令:发现、健康检查、三级诊断 - 在 K8s 中以 DaemonSet 部署 dcgm-exporter,读懂默认指标
- 定制采集字段,并通过 ServiceMonitor 接入 Prometheus
- 理解容器/Pod 级 GPU 指标的归属问题与 MIG 场景的指标特点
23.1 DCGM 架构:是什么、为什么需要它
NVML(NVIDIA Management Library)是驱动自带的底层 C 库——nvidia-smi 就是基于它做的。但它只面向单机。
DCGM(Data Center GPU Manager)是 NVIDIA 面向数据中心的 GPU 管理套件,在 NVML 之上提供了:
- 后台服务
nv-hostengine:持续采集、缓存指标,支持多客户端共享查询 - 命令行工具
dcgmi:分组管理多台机器/多张卡、健康检查、在线诊断 - 导出器
dcgm-exporter:把指标转成 Prometheus 格式(K8s 监控的事实标准组件) - 健康与诊断框架:标准化的 GPU 体检(这是 nvidia-smi 做不到的)
text
应用层 dcgm-exporter dcgmi (CLI) 第三方工具
│ │
└────── DCGM API(C/Python 绑定)──────
│
nv-hostengine(后台采集服务)
│
NVML(驱动用户态库)
│
NVIDIA 内核驱动 → GPU 硬件使用 dcgm-exporter 时,
nv-hostengine会自动以内嵌模式启动,通常不需要手动管理服务;dcgmi命令行则需要连接 hostengine(dcgmi discovery等命令默认连本机)。
23.2 dcgmi 常用命令
DCGM 用 group(组) 组织被管理的 GPU。默认有一个包含本机所有卡的组。
bash
dcgmi discovery -l # 发现:列出本机所有 GPU 及状态
dcgmi group -l # 查看组列表(默认组 ID 以实际输出为准)
dcgmi group -c mygroup # 创建组;dcgmi group -g <组ID> -a 0,1 加卡健康检查(生产高频命令)
bash
dcgmi health -g 0 -s a # 开启全部健康检查项(p=PCIe m=显存ECC t=散热 n=NVLink)
dcgmi health -g 0 -a # 查看健康状态:报告 PCIe、ECC、散热、电源等问题三级诊断(dcgmi diag)——GPU 的"体检套餐"
| 级别 | 命令 | 内容 | 耗时 | 适用场景 |
|---|---|---|---|---|
| Level 1 | dcgmi diag -r 1 | 快速检查:驱动、ECC、PCIe、基本功能 | 数秒~1 分钟 | 日常巡检、交付前初检 |
| Level 2 | dcgmi diag -r 2 | 中等:显存测试、短时压力测试 | 数分钟 | 故障后验证、周检 |
| Level 3 | dcgmi diag -r 3 | 深度:长时间压力测试、NVLink、显存全面测试 | 数十分钟 | 新机器交付验收、疑难故障 |
bash
dcgmi diag -g 0 -r 1 -j # 整组 Level 1,JSON 输出便于脚本处理
dcgmi diag -r 3 -i 2 # 只诊断 2 号卡的 Level 3注意:Level 2/3 诊断会独占 GPU 并产生高负载,只能在排空业务后执行。
统计信息
bash
dcgmi stats -g 0 -e # 开启对组的指标统计
dcgmi stats -g 0 -v # 查看进程级 GPU 使用统计23.3 dcgm-exporter 部署与默认指标
23.3.1 K8s DaemonSet 部署
dcgm-exporter 以 DaemonSet 跑在每个 GPU 节点上,暴露 :9400/metrics:
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata: {name: dcgm-exporter, namespace: monitoring}
spec:
selector:
matchLabels: {app: dcgm-exporter}
template:
metadata:
labels: {app: dcgm-exporter}
spec:
nodeSelector:
nvidia.com/gpu.present: "true" # 只调度到有 GPU 的节点
tolerations:
- {key: nvidia.com/gpu, operator: Exists, effect: NoSchedule}
containers:
- name: dcgm-exporter
image: nvcr.io/nvidia/k8s/dcgm-exporter:3.3.9-3.6.1-ubuntu22.04
ports: [{name: metrics, containerPort: 9400}]
securityContext:
runAsNonRoot: false # DCGM 需要访问驱动设备实际生产中更常用 GPU Operator 一键部署(
dcgmExporter.enabled=true),它自动处理镜像版本、节点选择器与 ServiceMonitor。手动部署适合学习原理。
验证:kubectl -n monitoring get pods -l app=dcgm-exporter -o wide,然后 curl -s http://<节点IP>:9400/metrics | grep DCGM_FI_DEV_GPU_UTIL。
23.3.2 默认指标对照表(背熟这张表)
| Prometheus 指标 | 含义 | 对应 nvidia-smi 字段 |
|---|---|---|
DCGM_FI_DEV_GPU_UTIL | SM 利用率(%) | utilization.gpu |
DCGM_FI_DEV_MEM_COPY_UTIL | 显存控制器利用率(%) | utilization.memory |
DCGM_FI_DEV_FB_USED / DCGM_FI_DEV_FB_FREE | 已用 / 空闲显存(MiB) | memory.used / memory.free |
DCGM_FI_DEV_GPU_TEMP | GPU 核心温度(℃) | temperature.gpu |
DCGM_FI_DEV_MEMORY_TEMP | 显存温度(℃) | temperature.memory |
DCGM_FI_DEV_POWER_USAGE | 当前功耗(W) | power.draw |
DCGM_FI_DEV_SM_CLOCK / DCGM_FI_DEV_MEM_CLOCK | SM / 显存时钟(MHz) | clocks.sm / clocks.mem |
DCGM_FI_DEV_XID_ERRORS | 最近一次 XID 错误码 | 见第七部分,告警核心 |
DCGM_FI_DEV_ECC_SBE/DBE_VOL_TOTAL | 单/双比特 ECC 错误累计 | ecc.errors.corrected/uncorrected.volatile.total |
DCGM_FI_DEV_NVLINK_BANDWIDTH_TOTAL | NVLink 总带宽计数 | NVLink 状态 |
DCGM_FI_DEV_PCIE_TX/RX_THROUGHPUT | PCIe 收发吞吐 | PCIe 带宽 |
每个指标都带标签:gpu(卡序号)、UUID、device、modelName、Hostname(K8s 部署时还有 pod、namespace、container),这是后续做面板和告警分组的基础。
23.4 自定义采集指标
dcgm-exporter 通过一个 CSV 配置文件定义采集哪些字段,格式为 字段ID, 采集频率:
csv
# /etc/dcgm-exporter/custom.csv —— 自定义采集字段
# 格式: DCGM 字段名, 采集间隔(ms),1000 已足够,过密会增加 GPU 负载
DCGM_FI_DEV_GPU_UTIL, 1000
DCGM_FI_DEV_MEM_COPY_UTIL, 1000
DCGM_FI_DEV_FB_USED, 1000
DCGM_FI_DEV_GPU_TEMP, 1000
DCGM_FI_DEV_POWER_USAGE, 1000
DCGM_FI_DEV_XID_ERRORS, 1000
# 追加:profiling 指标(真实算力消耗,见 24.2)
DCGM_FI_PROF_SM_ACTIVE, 1000
DCGM_FI_PROF_SM_OCCUPANCY, 1000
DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, 1000
DCGM_FI_PROF_DRAM_ACTIVE, 1000挂载配置并启用:
yaml
args: ["-f", "/etc/dcgm-exporter/custom.csv"]
volumeMounts:
- name: custom-csv
mountPath: /etc/dcgm-exporter
volumes:
- name: custom-csv
configMap:
name: dcgm-custom-metricsPROF 系列指标需要 DCGM 较新版本,且采集它们本质上是借用 GPU 的硬件性能计数器,与 CUPTI/nsight 等 profiler 同时运行可能冲突。
23.5 与 Prometheus 集成
方式一:ServiceMonitor(Prometheus Operator 环境)
先给 DaemonSet 配一个 Service:
yaml
apiVersion: v1
kind: Service
metadata:
name: dcgm-exporter
namespace: monitoring
labels: {app: dcgm-exporter} # ServiceMonitor 按此 label 选择
spec:
selector: {app: dcgm-exporter}
ports: [{name: metrics, port: 9400, targetPort: 9400}]
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: dcgm-exporter
namespace: monitoring
labels: {release: prometheus} # 与 Prometheus 的 serviceMonitorSelector 匹配
spec:
selector:
matchLabels: {app: dcgm-exporter}
endpoints:
- {port: metrics, interval: 15s, path: /metrics}方式二:PodMonitor 或静态配置
无 Service 时可用 PodMonitor 直接抓 Pod(结构与 ServiceMonitor 类似,podMetricsEndpoints 指定 port: metrics);非 Operator 的原生 Prometheus 则用 kubernetes_sd_configs: role: pod 加 relabel 规则(按 __meta_kubernetes_pod_label_app=dcgm-exporter 保留目标)。二选一即可,中小集群用 ServiceMonitor 最直观。
23.6 容器/Pod 级 GPU 指标归属
这是生产中最容易踩的坑:GPU 是物理设备,指标天然是"卡"维度的,而业务是"Pod"维度的。
归属是怎么建立的
dcgm-exporter 通过读取驱动维护的"进程 → GPU"映射并关联容器 cgroup 信息,给指标打上 pod、namespace、container 标签。前提:exporter 容器能看到宿主的 cgroup/设备信息(GPU Operator 已自动处理);Pod 通过 nvidia.com/gpu 资源申请 GPU(device plugin 分配),而不是手动挂载 /dev/nvidia*。若标签缺失(如业务容器用 CUDA_VISIBLE_DEVICES 自行组合卡),指标只能精确到卡,归属要靠 24.6 的巡检脚本在节点侧人工补齐。
MIG 与共享场景的指标特点
| 场景 | 指标行为 |
|---|---|
| 整卡独占 | 正常,标签齐全 |
| MIG 实例 | 每个 MIG 实例是独立"GPU",指标带 GPU_I_ID / GPU_I_PROFILE 标签;MIG 实例没有独立的温度/功耗(共享物理卡),这些指标只在物理卡级别有效 |
| 时间片共享 / MPS | 多个 Pod 共用一张卡,DCGM_FI_DEV_GPU_UTIL 是整卡合计,无法区分每个 Pod 各用了多少;显存可看到各进程用量 |
| HAMi 等显存切分 | 框架内限制对 DCGM 不可见,DCGM 看到的仍是物理显存 |
运维启示:共享场景下"这张卡忙"≠"某个 Pod 忙",归属分析要结合调度信息(谁被调度到了这台节点这张卡)。
本章小结
- DCGM = nv-hostengine(采集服务)+ dcgmi(CLI)+ dcgm-exporter(Prometheus 导出),构建在 NVML 之上。
dcgmi health -g 0 -a做健康检查,dcgmi diag -r 1/2/3做三级诊断(2/3 级必须排空业务)。- dcgm-exporter 以 DaemonSet 部署,默认指标覆盖利用率、显存、温度、功耗、XID、ECC;CSV 定制字段,PROF 指标需显式开启。
- 用 ServiceMonitor/PodMonitor 接入 Prometheus Operator。
- Pod 级归属依赖 device plugin 分配方式;MIG 无独立温度功耗,共享场景利用率是整卡合计。
动手实验
- 安装 DCGM,执行
dcgmi discovery -l、dcgmi diag -r 1,记录输出。 - 部署 dcgm-exporter(Docker 或 K8s 均可),
curl :9400/metrics,找出本章指标表中的每个指标。 - 修改 CSV 只保留 5 个字段,重启 exporter,验证指标数量变化。
- 思考题:为什么
DCGM_FI_DEV_XID_ERRORS只表示"最近一次 XID 码"而非累计计数?对告警设计有何影响?(提示:24.3 用> 0触发)
第 24 章 Grafana 可视化与告警体系
本章目标
- 基于社区 Dashboard 快速搭建集群级可视化,并设计核心面板
- 理解利用率平均值高估问题,学会用 PROF 指标评估真实算力
- 编写覆盖掉卡、XID、温度、显存、低利用率的 PrometheusRule 告警,并用 Alertmanager 分级路由
- 知道 GPU 相关日志在哪里,了解用 Loki 收集 XID 日志的思路
- 完成一个端到端的"集群 GPU 健康总览"巡检脚本
24.1 Grafana Dashboard 搭建
24.1.1 导入社区 Dashboard(5 分钟见效)
NVIDIA 官方和社区维护了现成的 DCGM Dashboard:
- Grafana → Dashboards → Import
- 输入社区 ID(常用的是 12239,NVIDIA DCGM Exporter Dashboard;以 grafana.com 搜索结果为准)
- 选择 Prometheus 数据源,确认导入
导入后先验证数据:没有曲线时按"Prometheus targets 是否 UP → exporter 是否出指标 → 时间范围"顺序排查。
24.1.2 集群级总览面板设计
社区面板偏"单机多卡",生产还需要一个集群运营视角的总览面板,建议包含:
| 面板 | PromQL 示例 | 说明 |
|---|---|---|
| 集群 GPU 总数 | count(DCGM_FI_DEV_GPU_UTIL) | 有多少张卡被监控到 |
| 健康卡数 | count(DCGM_FI_DEV_XID_ERRORS == 0) | 近似健康度(掉卡时总数会减少,见 24.3) |
| 集群平均利用率 | avg(DCGM_FI_DEV_GPU_UTIL) | 宏观忙闲(注意 24.2 的误区) |
| 集群显存占用比 | sum(DCGM_FI_DEV_FB_USED) / sum(DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE) | 显存维度压力 |
| 温度 TopN 节点 | topk(5, avg by (Hostname) (DCGM_FI_DEV_GPU_TEMP)) | 找出散热隐患节点 |
| XID 事件 | changes(DCGM_FI_DEV_XID_ERRORS[15m]) > 0 | 最近 XID 变动 |
| 利用率分布直方图 | bar gauge 分档统计 | 一眼看出"多少卡闲着" |
24.2 利用率计算误区:为什么平均值会高估
- 问题 1:时间平均高估。 util 表示"采样窗口内有 kernel 在跑的时间占比",一个每 100ms 只跑 5ms kernel 的任务可能显示接近 100%,真实算力消耗只有 5%。
- 问题 2:空间平均掩盖闲置。
avg()把 8 张卡平均后,"7 张满载 + 1 张空闲"显示 87.5%,但那 1 张空闲卡可能正卡着分布式训练的全部进度(木桶效应)。
解决方案:PROF(profiling)指标。 DCGM 可以读取 GPU 硬件性能计数器:
| 指标 | 含义 |
|---|---|
DCGM_FI_PROF_SM_ACTIVE | SM 至少有一个 warp 活跃的时间占比(真实算力消耗的核心指标) |
DCGM_FI_PROF_SM_OCCUPANCY | SM 上 warp 占用率(并行度是否吃满) |
DCGM_FI_PROF_PIPE_TENSOR_ACTIVE | Tensor Core 管道活跃占比(AI 负载关键) |
DCGM_FI_PROF_DRAM_ACTIVE | 显存带宽利用率 |
解读组合示例:GPU_UTIL=100% + SM_ACTIVE=95% → 真满载;GPU_UTIL=100% + SM_ACTIVE=20% + DRAM_ACTIVE=80% → 显存带宽瓶颈;GPU_UTIL=100% + SM_ACTIVE=20% + DRAM_ACTIVE=10% → kernel 并行度低或频繁同步,代码问题。
启用方式:DCGM 2.4+ 在 dcgm-exporter 的 CSV 配置中加入 DCGM_FI_PROF_* 字段(见 23.4),部分部署形态提供 --enable-profiling 类开关。注意 PROF 指标与同节点的 CUPTI profiler(nsys/ncu)互斥。
24.3 告警规则设计(PrometheusRule)
yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata: {name: gpu-cluster-alerts, namespace: monitoring}
spec:
groups:
- name: gpu-hardware
rules:
# P0:掉卡——节点上报的 GPU 数量比 10 分钟前减少
- alert: GPUCardLost
expr: |
count by (Hostname) (DCGM_FI_DEV_GPU_UTIL)
< on(Hostname) count by (Hostname) (DCGM_FI_DEV_GPU_UTIL offset 10m)
for: 2m
labels: {severity: P0}
annotations:
summary: "节点 {{ $labels.Hostname }} 掉卡"
description: "10 分钟内 GPU 数量减少,常见 XID 79/48,需立即排查并考虑下线节点。"
# P0:XID 错误(出现即告警,XID 语义见第七部分)
- alert: GPUXIDError
expr: DCGM_FI_DEV_XID_ERRORS > 0
labels: {severity: P0}
annotations:
summary: "{{ $labels.Hostname }} GPU {{ $labels.gpu }} 出现 XID {{ $value }}"
description: "79=掉总线、48=双比特ECC、63/64=显存故障,通常需隔离维修。"
# P1:不可纠正 ECC 错误增长 / 温度过高
- alert: GPUECCDBEGrowing
expr: increase(DCGM_FI_DEV_ECC_DBE_VOL_TOTAL[30m]) > 0
labels: {severity: P1}
annotations:
summary: "{{ $labels.Hostname }} GPU {{ $labels.gpu }} 双比特 ECC 错误增长"
- alert: GPUTemperatureHigh
expr: DCGM_FI_DEV_GPU_TEMP > 85
for: 5m
labels: {severity: P1}
annotations:
summary: "{{ $labels.Hostname }} GPU {{ $labels.gpu }} 温度 {{ $value }}℃"
# P2:显存占用长期 >95%(OOM 风险)
- alert: GPUMemoryPressure
expr: DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE) > 0.95
for: 30m
labels: {severity: P2}
annotations:
summary: "{{ $labels.Hostname }} GPU {{ $labels.gpu }} 显存占用长期超 95%"
# P3:占着显存但利用率长期 <10% —— 资源浪费
- alert: GPUIdleWaste
expr: |
avg_over_time(DCGM_FI_DEV_GPU_UTIL[6h]) < 10
and on(Hostname, gpu) DCGM_FI_DEV_FB_USED > 1000
for: 1h
labels: {severity: P3}
annotations:
summary: "{{ $labels.Hostname }} GPU {{ $labels.gpu }} 占显存但 6h 平均利用率 <10%"设计要点:
- 掉卡用"卡数对比"而非 exporter down:两者是两回事,应另配
up == 0采集告警。 - XID 用
> 0瞬时触发:该指标表示最近一次错误码,为 0 才是无错误。 - 低利用率要加显存条件:完全空闲是"未分配",占着显存不用才是"浪费"。
- 阈值按自家卡型(T4/A100/H100 不同)和业务特点调整。
24.4 告警分级与通知(Alertmanager)
yaml
# alertmanager.yaml 片段
route:
receiver: default-im
group_by: [alertname, Hostname]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- matchers: [severity = "P0"] # 掉卡/XID —— 电话 + IM
receiver: p0-phone-and-im
repeat_interval: 30m
- matchers: [severity = "P1"] # 硬件风险 —— IM @值班
receiver: p1-im-oncall
- matchers: [severity =~ "P2|P3"] # 优化类 —— 进周报队列
receiver: weekly-report-queue
receivers:
- name: p0-phone-and-im
webhook_configs: [{url: http://phone-gateway/alert}] # 电话通知网关
- name: p1-im-oncall
webhook_configs: [{url: http://im-bot/oncall}] # 企业微信/飞书 @值班人
- name: weekly-report-queue
webhook_configs: [{url: http://report-collector/gpu}] # 收集后每周汇总
- name: default-im
webhook_configs: [{url: http://im-bot/general}]分级哲学:P0(掉卡、XID 79/48,业务正在受损,分钟级响应,电话);P1(温度异常、ECC 增长,硬件风险信号,小时级响应,IM @值班);P2(显存压力等,天级处理,工单/日报);P3(低利用率浪费,资源优化议题,进周报,绝不打扰值班人)。
24.5 日志体系补充:指标之外的关键信息
指标告诉你"卡出问题了",日志告诉你"为什么"。GPU 相关日志位置:
| 日志来源 | 位置 | 内容 |
|---|---|---|
| 内核日志 | dmesg / journalctl -k | XID 错误的权威出处(NVRM: Xid ...)、驱动加载、掉卡 |
| 系统日志 | /var/log/syslog | 驱动相关用户态事件 |
| kubelet | journalctl -u kubelet | Pod 分配 GPU 失败、device plugin 注册异常 |
| device plugin | kubectl -n kube-system logs <nvidia-device-plugin-pod> | 卡发现、健康上报、分配记录 |
| fabric manager | journalctl -u nvidia-fabricmanager | NVSwitch 机型(DGX/HGX H100)NVLink fabric 状态 |
| dcgm-exporter | Pod 日志 | 采集异常 |
用 Loki 收集 XID 日志的示意(Promtail 管道规则):
yaml
# promtail 配置片段:从内核日志中识别 XID,打标签便于检索与告警
pipeline_stages:
- match:
selector: '{job="node-journal", unit="kernel"}'
stages:
- regex:
expression: 'NVRM: Xid \(PCI:(?P<pci>[^)]+)\): (?P<xid>\d+),'
- labels: {xid: "", pci: ""}之后在 Grafana 用 LogQL 检索 {job="node-journal"} |= "NVRM: Xid",并可配置"高危 XID → 告警"的日志告警规则,与 24.3 的指标告警互补(日志通常比指标更早出现细节)。
24.6 完整实战:集群 GPU 健康总览巡检脚本
即使有了全套监控,运维仍需要一份"一键跑完、一眼看完"的巡检脚本——用于交班、交付验收、故障初判。以下脚本在每个 GPU 节点执行(或用 pssh/ansible 批量下发):
bash
#!/bin/bash
# gpu_health_report.sh —— 集群 GPU 健康总览巡检(单节点版)
# 用法: bash gpu_health_report.sh (需要 nvidia-smi;dcgmi 可选)
echo "================ GPU 健康巡检报告: $(hostname) $(date) ================"
# 1. 卡数与型号
echo -e "\n[1] GPU 清单"
nvidia-smi --query-gpu=index,name,driver_version,persistence_mode \
--format=csv,noheader | column -t -s ','
# 2. 核心指标表:利用率/显存/温度/功耗/时钟
echo -e "\n[2] 核心指标 (util% | mem_used/total MiB | temp℃ | power W | sm_clock MHz)"
nvidia-smi --query-gpu=index,utilization.gpu,memory.used,memory.total,\
temperature.gpu,power.draw,clocks.sm \
--format=csv,noheader,nounits | \
awk -F',' '{printf "GPU%-2s util:%4s%% mem:%7s/%-7s temp:%3s℃ power:%6sW clk:%5sMHz\n",\
$1,$2,$3,$4,$5,$6,$7}'
# 3. 降频原因检查(列出非 Idle 的激活原因)
echo -e "\n[3] 降频原因 (非 Idle 项)"
nvidia-smi --query-gpu=index,clocks_event_reasons.sw_power_cap,\
clocks_event_reasons.sw_thermal_slowdown,clocks_event_reasons.hw_thermal_slowdown \
--format=csv,noheader,nounits | \
awk -F',' '{if($2!~/(^0|Not)/ || $3!~/(^0|Not)/ || $4!~/(^0|Not)/)
print "GPU"$1" 降频激活: sw_power_cap="$2" sw_thermal="$3" hw_thermal="$4}'
# 4. ECC 与退役页(DBE 或双比特退役页 >0 时标记"关注")
echo -e "\n[4] ECC 错误 / 退役页"
nvidia-smi --query-gpu=index,ecc.errors.corrected.volatile.total,\
ecc.errors.uncorrected.volatile.total,retired_pages.double_bit_ecc.count \
--format=csv,noheader,nounits | \
awk -F',' '{flag=($3>0 || $4>0)?" <== 关注":"";
printf "GPU%-2s SBE:%-6s DBE:%-4s retired_dbe:%-4s%s\n",$1,$2,$3,$4,flag}'
# 5. 最近 XID(内核日志)
echo -e "\n[5] 最近 10 条 XID 日志"
{ dmesg -T 2>/dev/null; journalctl -k --no-pager 2>/dev/null; } | \
grep -i "NVRM: Xid" | tail -n 10 || echo "(无权限或无 XID 记录)"
# 6. GPU 上的进程
echo -e "\n[6] 占卡进程"
nvidia-smi --query-compute-apps=gpu_uuid,pid,process_name,used_memory \
--format=csv,noheader || echo "无计算进程"
# 7. DCGM Level 1 快速诊断(如安装了 dcgmi)
if command -v dcgmi >/dev/null 2>&1; then
echo -e "\n[7] DCGM Level 1 快速诊断"
dcgmi diag -r 1 2>/dev/null | grep -E "Result|Overall|Fail" || echo "诊断执行失败"
fi
echo -e "\n================ 巡检完成 ================"输出节选示例:
text
[2] 核心指标
GPU0 util: 87% mem: 62140/81920 temp: 61℃ power:385.2W clk: 1410MHz
[4] ECC 错误 / 退役页
GPU1 SBE:0 DBE:2 retired_sbe:0 retired_dbe:3 <== 关注批量执行:
pssh -h gpu_nodes.txt -i 'bash -s' < gpu_health_report.sh,输出汇总到跳板机归档,配合周报使用。
本章小结
- 先导入社区 DCGM Dashboard 快速见效,再按集群运营视角自建总览面板(卡数/健康/利用率/温度 TopN)。
GPU_UTIL平均值会高估真实算力,用DCGM_FI_PROF_SM_ACTIVE等 PROF 指标还原真相,组合可区分算力/带宽/代码瓶颈。- 告警五件套:掉卡(卡数对比)、XID(>0 瞬时)、温度、显存压力、低利用率浪费;按 P0~P3 分级路由,优化类进周报。
- XID 的权威信息在内核日志,用 Loki/Promtail 收集并打标。
- 巡检脚本是监控体系的补充:交班、验收、故障初判一键完成。
动手实验
- 导入社区 DCGM Dashboard,指出 3 个面板对应的 PromQL,解释每个函数的作用。
- 新建"集群总览"Dashboard,实现 24.1.2 表格中至少 4 个面板。
- 应用 24.3 的 PrometheusRule,手工构造条件(模拟指标或压力工具)触发任意两条告警。
- 配置 Alertmanager,把 P3 级告警路由到独立 webhook,验证分组与静默逻辑。
- 运行 24.6 巡检脚本并归档输出;找出输出中每一项与 DCGM 指标的对应关系。
- 思考题:"集群平均利用率 60%"为何不能直接用于汇报资源使用情况?应补充哪些维度?(提示:分布、PROF 指标、排队任务数)
下一部分预告:第七部分 GPU 故障诊断与运维实战——把本部分学到的监控告警能力用在刀刃上,系统处理 XID 错误、掉卡、ECC 故障、NVLink 异常等真实生产故障。