ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

nvidia_gpu_exporter 实战指南:只用 nvidia-smi 就能跨平台导出 GPU 指标的 Prometheus Exporter

nvidia_gpu_exporter 实战指南:只用 nvidia-smi 就能跨平台导出 GPU 指标的 Prometheus Exporter
  • 可观测性
  • 指标监控

【免费下载链接】nvidia_gpu_exporter

Nvidia GPU exporter for prometheus using nvidia-smi binary OR using NVML

项目地址:https://gitcode.com/gh_mirrors/nv/nvidia_gpu_exporter
点击查看免费下载

nvidia_gpu_exporter 是一个面向 Prometheus 的 NVIDIA GPU 指标导出器:默认通过调用nvidia-smi二进制完成采集、解析与导出,另可选读 NVML 驱动库的 nvml 后端,以及无需任何 GPU 的 demo 合成数据后端,覆盖 Linux、Windows、macOS 与裸机、Docker、Kubernetes 部署。本文以项目 README 为主线,结合仓库源码逐层讲清它的工作原理、三种采集后端、各平台安装方式、发布物签名验证与安全边界,读完即可在自己机器或集群里把 GPU 指标接入监控栈。

项目定位与适用场景

README 的第一句话概括了它:一个用nvidia-smi(.exe)二进制来收集、解析并导出指标的简单 exporter。由于只依赖nvidia-smi,它不需要 C 语言绑定,因此 Windows 同样能跑——不需要 Docker、也不需要 Linux。

从 README 的 Use cases 一节看,它瞄准的是数据中心的重量级工具链覆盖不到、或成本过高的场景:

  • 消费级与专业级显卡(GeForce/RTX):数据中心工具链对它们暴露的信息很少,nvidia-smi往往是利用率、显存、功耗、温度唯一统一的来源;
  • 小型 Kubernetes 集群、边缘盒子与家庭实验室:想要 GPU 指标,但不想引入整套 NVIDIA GPU Operator;
  • 虚拟化或受限环境(vGPU 客户机、MIG 切片、强管控容器):深层 GPU 计数器不暴露,但nvidia-smi仍然能回答;
  • 新旧显卡混编的机群:需要一个在各处行为一致的 exporter;
  • 游戏主机:边玩游戏边在仪表盘上看 GPU 状态。

README 也给出了明确的边界:如果你在 Kubernetes 上用 GPU Operator 跑数据中心卡,DCGM-exporter 可能更合适,本项目针对的是上述场景。此外 README 保留了一个诚实的提示:这是一个开发者利用业余时间维护的 side project,issue 和 PR 的响应速度无法保证。

它的核心卖点(Highlights)可以归纳为六点,后文会逐一展开:

  1. 任何装有nvidia-smi(.exe)的系统都能跑,Windows、Linux、macOS,无需 C 绑定;
  2. 甚至可以不在被监控机器上运行——把--nvidia-smi-command指向 SSH 命令即可远程采集;
  3. 自动发现nvidia-smi能暴露的指标字段(面向未来,新驱动加了字段就能被捡到);
  4. 可选的 per-process GPU 指标:看到哪个进程用了多少显存;
  5. 可选的后台采集模式:按定时器跑nvidia-smi,而不是每次 scrape 都跑一次;
  6. 自带两套官方 Grafana 仪表盘:单卡详情视图与多卡总览视图,互相有跳转链接。

工作原理:从 nvidia-smi 的 CSV 到 Prometheus 指标

从源码结构看,整个程序是一条清晰的调用链:

cmd/nvidia_gpu_exporter/main.go // 进程入口,信号处理 └─ internal/app/app.go // 命令行解析、后端装配、HTTP 服务 ├─ internal/nvidiasmi // nvidia-smi 命令执行与输出解析 ├─ internal/collect // 同步/后台采集循环 ├─ internal/exporter // 表格到 Prometheus 指标的转换 └─ internal/nvmlnative // NVML 后端(-nvml 构建)

入口 main.go 只做信号处理,把参数交给 app.Run。下面挑几个与日常运维最相关的机制展开。

字段自动发现(AUTO)

--query-field-names默认值AUTO的行为在 resolve.go 中实现:启动时先跑nvidia-smi --help-query-gpu发现可用字段,再跑一次真实的--query-gpu查询建立「查询字段 → 返回列名」的映射。值得注意的是它的降级策略:

  • 自动发现失败时,回退到内置字段表(builtinResolvedFields),保证 exporter 总能起来;
  • 用户显式指定的字段列表如果内置映射覆盖不了,则直接报错而不是静默替换——「auto 模式必须能启动,显式列表不允许被悄悄改写」是代码注释里写明的原则;
  • 无论字段列表来自哪里,都会经过 withRequiredFields 补入一组固定的身份字段(uuid、name、driver_version、vbios_version、pci_bus_id、serial、index等 11 项,见 infoFields),因为它们支撑nvidia_smi_gpu_info指标,也是所有 GPU 序列按uuid关联的锚点。这也是 CONFIGURE 文档里「nvidia_smi_gpu_info背后的字段不可排除」的原因。

命令执行与防卡死

实际查询在 query.go 中完成:把字段列表拼成--query-gpu=... --format=csv执行,再把 CSV 输出解析成表格。两个防御性细节:

  • 命令由 exporter 自己拆分(SplitCommand)后直接exec,不经过 shell,所以 flag 值无法夹带第二条命令——这是 SECURITY_MODEL.md 里「命令注入」威胁的对策;
  • exec.Cmd.WaitDelay设为 2 秒(query.go 处为waitDelay),即使被杀死的nvidia-smi进程不释放输出管道,采集也不会被永久挂住。

--collect.timeout(默认 10s)约束每个采集周期的总时长,包括启动时的字段发现。超时的周期被记为一次失败采集,而不是挂死 scrape。注意文档也声明了这是 best-effort:卡在不可中断内核等待里的进程杀不死;对 wrapper 命令(如 ssh)只能杀掉 wrapper 本身。

后端选择与参数校验

--collect.backend有三个取值exec/nvml/demo,常量定义在 app.go。参数组合在启动时由 validateBackendFlags 校验,非法组合直接报启动错误而不是静默忽略:

  • --nvidia-smi-command不能与nvml/demo后端组合(没有命令可定制);
  • --collect.pcie-throughput要求nvml后端;
  • --collect.compute-apps-mig要求nvml或demo后端,且要求开启--collect.compute-apps;
  • --demo-config只在 demo 后端有效。

-nvml发行版构建在构建期把默认后端从exec覆盖为nvml(见 DefaultBackend 的注释),所以-nvml制品开箱即用 NVML 后端,普通静态二进制传这个 flag 会直接报错。

采集模式:同步 vs 后台

--collect.interval=0(默认)时每次 scrape 同步跑一次nvidia-smi,同一时刻到达的多个 scrape 共享同一次运行的结果(多个 Prometheus HA 成员不会放大nvidia-smi进程数)。设置--collect.interval后进入后台模式:nvidia-smi按固定间隔在后台跑,scrape 只读最近一次成功结果,nvidia-smi的进程数从此只取决于间隔。后台模式的注意点(源自 CONFIGURE.md):

  • 服务的数据可能陈旧约「一个间隔 + 一次采集时长」,Prometheus 按 scrape 时刻打时间戳,应配合nvidia_smi_last_collect_success_timestamp_seconds判断数据新鲜度;
  • 陈旧告警建议留「几个间隔 + timeout」的余量,例如间隔 15s、默认 10s 超时时:time() - nvidia_smi_last_collect_success_timestamp_seconds > 55 or nvidia_smi_last_collect_success == 0;
  • 后台运行失败时 GPU 指标会从输出中消失(而不是悄悄变陈旧),nvidia_smi_last_collect_success报告失败——失败不可见比数据陈旧更糟,这是它的设计取向。

Scrape 侧的三个保护层

从 app.go 可以看到 metrics 端点还内置了两层保护:

  • 并发上限:--web.max-requests默认 40,超限的 scrape 立即收到 503,而不是排队堵在慢采集后面耗尽 goroutine;
  • 跟随 Prometheus 的超时:scrape 上下文取请求头X-Prometheus-Scrape-Timeout-Seconds减去--web.timeout-offset(默认 500ms,给响应回传留时间),超时的采集成分被取消,scrape 以nvidia_smi_last_collect_success 0应答,因此不需要手工保证--collect.timeout小于 Prometheus 的scrape_timeout。

/-/healthy与/-/ready是进程级健康检查:只要进程活着就返回 200,与采集成败无关。这样nvidia-smi出问题的机器仍保持可 scrape,故障在健康指标里可见,而不是目标直接从抓取列表里消失。Helm chart 的 liveness/readiness 探针用的就是这两个端点。

快速开始:Docker 五分钟跑起来

在一台装有 NVIDIA 驱动和 NVIDIA Container Toolkit 的 Linux 机器上:

docker run -d --name nvidia_gpu_exporter --restart unless-stopped \ --gpus all -e NVIDIA_DRIVER_CAPABILITIES=utility -p 9835:9835 \ utkuozdemir/nvidia_gpu_exporter:latest curl http://localhost:9835/metrics

没有 GPU 也完全可以体验:nvidia_gpu_exporter --collect.backend demo在任何机器上都能服务逼真的合成指标。Windows、macOS、各平台包管理与 Kubernetes 的完整步骤见 docs/INSTALL.md。

三种采集后端详解

exec(默认):跑 nvidia-smi

就是上面机制一节描述的路径。它的独特优势在于:可以用--nvidia-smi-command换成任意命令(sudo、ssh wrapper、甚至测试用的 fake),并且对卡死的驱动调用有最强的隔离——子进程可以被杀掉。

远程采集是 exec 后端的独有能力:exporter 只要求命令的输出「长得像nvidia-smi的输出」,所以可以这样在一台树莓派上采集家里 PC 的 GPU:

nvidia_gpu_exporter --nvidia-smi-command "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null SSH_USER@SSH_HOST nvidia-smi"

macOS 的典型用法正是如此:Mac 上没有 NVIDIA GPU,exporter 跑在 Mac 上、通过 SSH 去采集另一台机器的nvidia-smi。注意容器镜像里没有ssh和 shell(distroless),远程采集只适用于二进制安装,或基于官方镜像自建的 fuller base 镜像。

排除慢字段:AUTO 模式下如果某些字段读得慢或触发告警(例如部分 vGPU 客户机里remapped_rows.histogram.*会触发内核告警),可以:

nvidia_gpu_exporter --query-field-names-exclude "remapped_rows.histogram.*" # 或排除多个具体字段 nvidia_gpu_exporter --query-field-names-exclude "inforom.checksum_validation,fan.speed"

名称按字面匹配,*是任意字符序列通配。支撑nvidia_smi_gpu_info的身份字段不可排除。

nvml(实验性):直读驱动库

--collect.backend=nvml不再执行nvidia-smi,而是直接读驱动库libnvidia-ml.so.1。对两个后端共同服务的所有查询字段,指标在名称、标签和取值上完全一致(文档说明这已逐字段在真实硬件上核对过),所以现有仪表盘和告警无缝可用。在此之上它提供nvidia-smi给不了的指标族:

  • 总能耗计数器nvidia_smi_energy_joules_total(Volta 及以前的卡没有);
  • PCIe 吞吐nvidia_smi_pcie_throughput_{tx,rx}_bytes_per_second,需--collect.pcie-throughput显式开启——驱动对每个方向各用一个 20ms 计数器窗口采样,每 GPU 每次采集约增加 40ms(8 卡节点约 320ms),两个方向是先后采样而非同时成对;
  • 每个 MIG 实例的指标:nvidia_smi_mig_info、nvidia_smi_mig_memory_{total,used,free,reserved}_bytes、nvidia_smi_mig_{graphics_activity,sm_activity,sm_occupancy,tensor_activity}_ratio等,无需配置,MIG 实例存在即出现;
  • XID 错误计数器nvidia_smi_xid_errors_total与nvidia_smi_xid_last_timestamp_seconds:XID 是驱动层的编号错误事件(卡死的 kernel、ECC 故障、掉线的 GPU),nvidia-smi完全看不到,它们只通过驱动事件或内核日志暴露;
  • per-process 指标的 MIG 归因标签(--collect.compute-apps-mig)。

CONFIGURE.md 给出的后端能力对照表值得原样保留:

能力execnvmldemo
查询字段指标(名称/标签/取值一致)是是合成数据
带cuda_version标签的gpu_info是是是
per-process 指标(--collect.compute-apps)是是是
采集状态指标command_exit_codenvml_return_codenvml_return_code
自定义命令、远程采集(ssh、sudo)是否否
对卡死驱动的最强隔离(可杀子进程)是否不适用
目录追赶前的新驱动字段(AUTO)是否否
总能耗计数器否是是
PCIe 吞吐否是(--collect.pcie-throughput)默认开启
per-MIG-instance 指标否是是
per-process MIG 归因否是是
XID 错误计数器否是是

它标记为实验性的原因(也即使用它的限制):

  • 目前仅 Linux x86_64、glibc 系统,且只存在于专门的-nvml发行档与-nvml镜像 tag 中;普通二进制保持完全静态,传--collect.backend=nvml会得到错误;
  • 可查询字段来自编译进二进制的内置目录而非运行时发现,因此不自动是 exec 的超集:少数字段尚无可靠映射而被故意不服务;新驱动加的字段会先出现在默认后端;
  • 卡住的驱动调用无法像子进程那样被杀死,--collect.timeout只约束 scrape 等待时长;
  • 在 590 分支以前的驱动上,时钟原因指标族在两个后端之间可能一个叫clocks_throttle_reasons_*一个叫clocks_event_reasons_*(文档说明尚未锁定确切改名版本)。

-nvml构建不需要nvidia-smi二进制,容器里 NVIDIA 运行时注入驱动库即可。它用独立的发布 flavor 分发,镜像 tag 自带该后端并默认启用,无需任何 flag:

docker run -d \ --name nvidia_gpu_exporter \ --restart unless-stopped \ --gpus all \ -e NVIDIA_DRIVER_CAPABILITIES=utility \ -p 9835:9835 \ utkuozdemir/nvidia_gpu_exporter:latest-nvml

两个实践提醒:nvidia_smi_*这个指标前缀在两个后端保持不变——它命名的是数据 schema 而非采集机制;如果你的镜像自动化基于 semver 过滤 tag(例如 FluxImagePolicy),-nvml后缀会被解析成 semver pre-release,需要显式过滤 flavor tag,例如filterTags: {pattern: '^(?P<version>\d+\.\d+\.\d+)-nvml$', extract: '$version'}。

demo:无 GPU 的完整体验

--collect.backend=demo在没有 GPU、没有驱动、甚至不是 Linux 的机器上服务一份模仿 nvml 后端完整指标面的合成数据,适合试用 exporter、开发仪表盘和告警。启动时它会打印一条 warn 日志,防止 demo 实例被误认为真实实例:

nvidia_gpu_exporter --collect.backend demo

内置配置由 default-config.yaml 定义:回放一份真实捕获的 H200 输出(state: load),仿真 2 张 H200,第一张卡上有 MIG 拓扑,并预置了 XID 79 的历史与 10 分钟间隔的随机事件,使所有指标族开箱就有内容。

NVML-only 指标族在合成时保持自洽:能耗计数器对表格里报告的功耗做积分;MIG 实例构成一致的拓扑(繁忙实例温度高、其余空闲);PCIe 吞吐在可配置范围内抖动;XID 计数器随时间累积。per-process 指标(含 MIG 归因标签)同样可用。

用--demo-config换成自己的场景:

# 内置捕获二选一: # linux-x86_64__nvidia-h200__590.48.01.txt # linux-x86_64__nvidia-geforce-rtx-4080-super__595.71.05.txt capture: linux-x86_64__nvidia-h200__590.48.01.txt state: load # 服务捕获的哪个状态:idle 或 load gpus: 4 # 把捕获的 GPU 复制成这么多 fluctuate: true # scrape 之间抖动自然变化的值 extras: # demo 专属部分,每个键都可省略 seed: 42 # 固定随机性以复现数值 energy-fallback-power-watts: 120 # 功耗字段被排除时使用的兜底值 pcie: tx-bytes-per-second: {min: 0.2e9, max: 3e9} rx-bytes-per-second: {min: 0.5e9, max: 8e9} mig: - gpu: 0 # 仿真 GPU 列表中的索引 instances: - {gi: 2, profile: 3g.71gb, cis: 2, busy: true} - {gi: 7, profile: 1g.18gb} xids: initial: [{gpu: 1, xid: 79, count: 2}] # 预置错误历史 interval: 10m # 后续随机事件的平均间隔,省略即关闭 codes: [13, 31, 79] # 后续事件抽取的码池

extras以上部分与仓库里 fakenvidia-smi(cmd/fake-nvidia-smi)共用同一份配置 schema,完整键参考随其文档提供;fake 的故障注入键(exit、delay、stderr-msg、fail-arg)在 demo 模式被忽略,因为它们测的是子进程处理,而 demo 是进程内路径。

配置文件在每个采集周期都会重读:编辑即时生效、无需重启;编辑坏了就表现为一次失败采集(nvidia_smi_last_collect_success 0)直到修好;编辑同时会重置合成状态(能耗/XID 计数器、随机序列),类似驱动重载;唯一例外是cuda_version标签只在启动时读一次。两个容易踩的细节:demo 模式 PCIe 族默认全开,而 nvml 后端需--collect.pcie-throughput——用 demo 数据验证过的仪表盘在 nvml 默认部署上 PCIe 面板会是空的;要完全可复现的数值,设extras.seed并关闭fluctuate。

可视化:两套官方 Grafana 仪表盘

项目提供两套官方仪表盘,它们在 Grafana 里互相有跳转链接:

  • Nvidia GPU Metrics(ID14574):单卡详情视图,覆盖利用率、功耗、温度、时钟、ECC、进程列表、MIG 面板等;
  • Nvidia GPU Overview(ID25547):把一台节点上的所有 GPU 并排对比,并可下钻到详情仪表盘。

使用方式有两种:在 Grafana 里按 ID 导入(Dashboards → New → Import),或在 Helm chart 中启用grafanaDashboard让两套仪表盘被自动 provision。两套仪表盘的 JSON 也随仓库发布,位于 docs/grafana(dashboard.json 与 dashboard-overview.json)。

上面文章开头的截图即单卡详情仪表盘:顶部是 Health 状态条,中部为利用率/功耗/风扇/温度的仪表盘组与时钟原因(throttle reasons)时间线,下方依次是显存、ECC、按进程统计的 GPU 进程表、Fabric 状态、XID 事件面板以及 MIG 库存与活动面板。多卡总览仪表盘则把同一节点每张卡的利用率、内存、功耗、时钟、温度、throttle 状态码、ECC、PCIe 吞吐等以多序列曲线并排展示,并在底部保留每张卡的内存条与 MIG 活动条——它是从nvidia_smi_gpu_info按uuid关联所有序列的典型用法。

注意官方仪表盘同时包含 NVML-only 面板(能耗、MIG、XID):在默认 exec 后端下这些面板是空的,在 nvml 后端下会自动填满——这正是 README 所说「同一套仪表盘,换后端即得新指标」的落地形态。

安装:每个平台怎么装

完整分平台步骤在 docs/INSTALL.md,这里按 README 的指针整理关键决策点。

前提:被监控机器上要有 NVIDIA 驱动,且 exporter 能跑nvidia-smi——「nvidia-smi能打出你的 GPU,exporter 就能工作」。例外是-nvmlflavor:它直读驱动库,不需要nvidia-smi,仅存在于 Linux x86_64。装好后监听9835端口,curl http://localhost:9835/metrics自检。文档反复提醒:示例里的latest与X.Y.Z只是占位,生产请锁定具体版本。

Linux(x86_64 与 arm64 都有构建)有三种方式:

  • deb/rpm 包:二进制装到/usr/bin,创建系统用户nvidia_gpu_exporter,安装 systemd unit 并设为开机自启,systemctl status nvidia_gpu_exporter检查。包只支持 systemd;
  • 纯二进制:从 releases 下对应架构的归档,tar解出后移入PATH;
  • 二进制 + 手工 systemd:创建系统用户,把仓库里的 nvidia_gpu_exporter.service 复制到/etc/systemd/system/,daemon-reload后enable --now。

Docker:镜像不含任何 NVIDIA 组件,GPU 设备、驱动库与nvidia-smi由 NVIDIA Container Toolkit 在容器启动时注入,因此同一镜像适配任意驱动版本、任意 GPU 数量与任意 CPU 架构。容器以 uid 65534(nobody)运行而非 root。三个高频坑:

  • NVIDIA_*环境变量是配置 NVIDIA 运行时的,不是选择运行时的;没有--gpus/设备预留/runtime: nvidia时容器拿不到 GPU,exporter 仍会启动但只服务自身健康指标,nvidia_smi_last_collect_success 0;
  • 镜像是 distroless:没有 shell、没有包管理器,docker exec进不去,也不要在派生镜像里用 shell 写RUN步骤。需要额外工具时基于更完整的 base 拷贝二进制即可,且注意派生镜像的用户由 base 决定;
  • 无法装 toolkit 的宿主机可手工挂载/dev/nvidia*、nvidia-smi与libnvidia-ml.so*到默认库目录,但驱动升级会断符号链接,能用 toolkit 就用 toolkit。

Kubernetes:以 DaemonSet 运行,靠 NVIDIA 运行时注入 GPU 访问。最重要的一条红线:不要为 exporter 申请nvidia.com/gpu资源——设备插件按整卡独占分配,监控 pod 申请一张卡等于把卡从真实工作负载手里拿走;环境变量方式让 exporter 看到节点上所有 GPU 而不占用任何一张。Helm chart 即仓库内的 charts/nvidia-gpu-exporter:

helm install nvidia-gpu-exporter oci://ghcr.io/utkuozdemir/charts/nvidia-gpu-exporter \ --set runtimeClassName=nvidia

不用 Helm 时可用最小 DaemonSet:镜像 +NVIDIA_VISIBLE_DEVICES=all/NVIDIA_DRIVER_CAPABILITIES=utility环境变量 +runtimeClassName: nvidia(若 NVIDIA 运行时不是默认),端口 9835。托管平台(AKS/GKE/EKS)的 GPU 节点镜像自带驱动与 toolkit,DaemonSet 可直接用。chart README 提供完整 values 参考、ServiceMonitor/PodMonitor/告警/仪表盘等可选项,以及restrictedPod Security Standard 命名空间的 security context 配置——默认安装即可在 restricted 命名空间被准入。

Windows(仅 x86_64 构建):

  • all-in-one PowerShell 脚本(install/windows-all-in-one.ps1)在一台机器上装好 exporter、Prometheus 和 Grafana,数据源与两套仪表盘直接 provision 好,重跑安全;
  • winget install utkuozdemir.nvidia_gpu_exporter(或 Scoop bucket);
  • 原生 Windows 服务:exporter 自己实现了服务控制管理器协议,nvidia_gpu_exporter install注册服务,无需 NSSM 等第三方 wrapper;传给install的 flag 会固化进服务命令行(如nvidia_gpu_exporter install --web.listen-address=:9836),重跑install原地重配置,日志写入 Application 事件日志。

macOS:只有 Intel 构建(Apple Silicon 走 Rosetta)。Mac 通常没有 NVIDIA GPU,典型用法即上文提到的远程采集。

发布物验证与供应链安全

README 用一整节强调:发布物都经过签名,可以核实它确实来自本项目的发布流水线:

  • release 附带的checksums.txt有一个 keyless cosign 签名包(checksums.txt.sigstore.json),覆盖所有二进制、归档与包;没有该文件的旧 release 改用 GPG 签名。容器镜像与 Helm chart 同样 keyless 签名并绑定 release workflow 身份;经典 Helm 仓库额外携带 GPG provenance 文件(因为 Helm 只认 GPG);
  • docs/INSTALL.md 给出确切验证命令,核心是先用 cosign 验签名再校 checksum(&&保证签名失败不会走到 checksum 那步):
cosign verify-blob checksums.txt \ --bundle checksums.txt.sigstore.json \ --certificate-oidc-issuer=https://token.actions.githubusercontent.com \ --certificate-identity-regexp='^https://github\.com/utkuozdemir/nvidia_gpu_exporter/\.github/workflows/release\.yml@refs/tags/v.*$' && sha256sum --ignore-missing -c checksums.txt
  • 此外,自 v1.15.1 起 release 文件可复现构建:同一 commit 在任何机器上产出逐字节相同的二进制、归档与包(-nvml是 cgo 构建,只有匹配的 C 工具链才能复现,发布 runner 是 Ubuntu 24.04 默认 GCC);release workflow 本身会在第二台 runner 上从零重建所有 release 并在校和不一致时失败。你可以用goreleaser release --clean --skip=publish,sign,sbom,docker,announce自建一份再diffchecksums 验证。

安全模型详见 docs/SECURITY_MODEL.md,与本文主题强相关的要点:exporter 只读不写、不改任何 GPU 设置;默认配置下没有任何出站连接(自定义--nvidia-smi-command除外,远程采集就是 ssh);采集失败时它不提供 GPU 数据而不是陈旧数据,失败在自身健康指标里可见;指标端点默认明文 HTTP(与其他 Prometheus exporter 一致),能到达端口的人能看到全部导出内容——包括 GPU 清单(UUID、序列号、PCI 地址、驱动与 VBIOS 版本)以及开启--collect.compute-apps后的进程名与 PID,因此端口应保持在可信网络内,或用--web.config.file启用 TLS 与 basic auth。解析器全部有 fuzz target 且种子语料每次测试重放,未知状态值被跳过并记日志而不是猜测。问题报告走 SECURITY.md。

指标速览

完整的指标说明在 docs/METRICS.md,每块被抓取到的 GPU × 驱动版本 × 负载状态各有一份期望输出文件放在 internal/integration/testdata,是集成测试逐字节对比的基准,也是「一次真实 scrape 长什么样」的最权威样例。结构上:

  • 每 GPU 序列都带uuid标签,与nvidia_smi_gpu_info(携带name、driver_version、vbios_version、cuda_version等身份标签的恒为 1 的 gauge)关联;
  • 采集健康指标不带uuid:nvidia_smi_last_collect_success、nvidia_smi_last_collect_success_timestamp_seconds、nvidia_smi_last_collect_duration_seconds、nvidia_smi_failed_scrapes_total(注意它统计的是失败采集而非失败 scrape,名字因兼容保留)、nvidia_smi_command_exit_code(exec 后端;nvml/demo 后端换成nvidia_smi_nvml_return_code,-1表示采集根本没拿到 NVML 状态——超时、被拒、或零可见 GPU,零 GPU 被故意判为失败,防止坏的设备挂载看起来像健康的空闲 scrape)。

摘一段单卡机器的真实 scrape 输出形态(来自 METRICS.md):

# HELP nvidia_smi_gpu_info A metric with a constant '1' value labeled by gpu uuid, name, driver_model_current, driver_model_pending, vbios_version, driver_version, pci_bus_id, serial, compute_cap, pci_sub_device_id, index, cuda_version. # TYPE nvidia_smi_gpu_info gauge nvidia_smi_gpu_info{uuid="df6e7a7c-7314-46f8-abc4-b88b36dcf3aa",name="NVIDIA GeForce RTX 2080 SUPER",driver_version="471.11",cuda_version="11.4",pci_bus_id="00000000:71:00.0",index="0",...} 1 # HELP nvidia_smi_utilization_gpu_ratio utilization.gpu [%] # TYPE nvidia_smi_utilization_gpu_ratio gauge nvidia_smi_utilization_gpu_ratio{uuid="df6e7a7c-7314-46f8-abc4-b88b36dcf3aa"} 0.42 # HELP nvidia_smi_memory_used_bytes memory.used [MiB] # TYPE nvidia_smi_memory_used_bytes gauge nvidia_smi_memory_used_bytes{uuid="df6e7a7c-7314-46f8-abc4-b88b36dcf3aa"} 7.06740224e+08 # HELP nvidia_smi_power_draw_watts power.draw [W] # TYPE nvidia_smi_power_draw_watts gauge nvidia_smi_power_draw_watts{uuid="df6e7a7c-7314-46f8-abc4-b88b36dcf3aa"} 28.07 # HELP nvidia_smi_temperature_gpu temperature.gpu # TYPE nvidia_smi_temperature_gpu gauge nvidia_smi_temperature_gpu{uuid="df6e7a7c-7314-46f8-abc4-b88b36dcf3aa"} 34

几个写告警时需要知道的语义:

  • 枚举型字段被映射为数值:两态字段(Enabled/Disabled、Yes/No、Active/Not Active等,涵盖persistence_mode、ecc.mode.*、mig.mode.*、全部clocks_event_reasons.*限频标志)变成 1/0;N/A、[Not Supported]、[Insufficient Permissions]与未识别的值直接不导出并记日志;
  • nvidia_smi_pstate是裸性能状态号(P0 最高性能到 P15),不是负载 gauge;nvidia_smi_gpu_recovery_action > 0是现成的「GPU 不健康」告警源(0 None、1 GPU Reset、2 Node Reboot、3 Drain P2P、4 Drain and Reset);
  • XID 告警优先用时间戳加显式码白名单而不是 rate:time() - nvidia_smi_xid_last_timestamp_seconds{xid=~"48|62|64|74|79|95|119|120"} < 300,因为它能覆盖一个序列的首个事件(Prometheus 从未观测过它的 0,increase(...) > 0会漏掉);对所有码告警是噪音——13、31、43 多为应用故障,63、92 属信息性事件。Helm chart 自带按此方式构建好的告警规则。

贡献一份 GPU capture

nvidia-smi的输出随 GPU 型号、驱动版本、操作系统与空闲/负载状态变化很大,项目的应对方式是维护一个真实输出语料库 internal/captures:每个捕获是一个自包含的.txt文件,按<os>-<arch>__<model>__<driver>.txt命名,内容含元数据头与分段命令输出(--help-query-gpu、完整 CSV、--query-compute-apps、idle 与 load 两态等)。这些捕获是「可执行的」:cmd/fake-nvidia-smi 按字面回放捕获文件,internal/integration 的集成测试对语料库里的每个捕获跑真实 exporter 并与 checked-in 的期望输出逐字节比对——所以贡献一份捕获会自动扩展测试套件。

对拥有仓库尚未见过的硬件(新 GPU 型号、全新驱动)的读者,README 给出的贡献流程只需要一条命令:

./internal/captures/collect.sh # 加 --load 再采一份负载样本

它只需nvidia-smi、bash与标准 coreutils,只跑只读命令,默认掩码会破坏机器指纹的标识(GPU UUID、序列号、主机名)。生成一个.txt文件后提交并开 PR,或附到 issue 上。Windows 上在 Git Bash / WSL2 里跑同样的命令即可。

参考入口

  • 主文档:README.md
  • 配置:docs/CONFIGURE.md(完整 flag 参考、后端对照、demo 模式)
  • 指标:docs/METRICS.md
  • 安装:docs/INSTALL.md
  • 安全模型:docs/SECURITY_MODEL.md
  • Helm chart:charts/nvidia-gpu-exporter/README.md
  • 仪表盘 JSON:docs/grafana/dashboard.json、docs/grafana/dashboard-overview.json
  • 集成测试期望输出(真实 scrape 样例):internal/integration/testdata
  • 贡献:CONTRIBUTING.md、路线图 docs/ROADMAP.md、治理 GOVERNANCE.md
  • 可观测性
  • 指标监控

【免费下载链接】nvidia_gpu_exporter

Nvidia GPU exporter for prometheus using nvidia-smi binary OR using NVML

项目地址:https://gitcode.com/gh_mirrors/nv/nvidia_gpu_exporter
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进