在容器内使用 `rocm-smi` 监控 GPU 利用率

解读

国内互联网、金融、自动驾驶公司普遍把 AMD GPU(MI100/MI210 等)作为 CUDA 之外的第二选择,面试时考官想确认三件事:

  1. 你是否真正在容器里跑过 ROCm 栈,还是只在宿主机敲过命令;
  2. 能否把驱动、设备、权限、镜像、运行时五条线一次打通;
  3. 出现 “rocm-smi: command not found” 或 “Permission denied” 时,能否两分钟定位并给出修复方案。
    回答必须体现“容器视角”——从镜像构建、引擎启动参数、到 cgroup 隔离,每一步都要让 GPU 可见且可监控,同时满足最小权限+可复现+可灰度的落地规范。

知识点

  1. ROCm 内核驱动版本与容器内用户态库版本必须大版本一致(如宿主机 5.7.x,镜像里 ROCm 5.7.x),否则 rocm-smi 读不到内核接口。
  2. 设备挂载:/dev/kfd + /dev/dri/ 下所有 renderD* 节点必须 --device 显式透传,不能只挂 dri 目录
  3. 用户组映射:宿主机 render 组 gid 需与容器内对齐,否则出现 “Permission denied”;国内大厂常用 --group-add=$(getent group render | cut -d: -f3) 动态注入。
  4. 特权与 seccomp:ROCm 5.5+ 已无需 --privileged,但需关闭 seccomp 默认策略中对 amdgpu_* ioctl 的屏蔽,推荐自定义 seccomp profile 而非直接 --security-opt seccomp=unconfined
  5. 镜像体积优化:rocm-smi 依赖 python3-amdsmi,多阶段构建时先 apt-get install rocm-smiapt-get purge 编译依赖,可把镜像从 3.8 GB 压到 1.1 GB。
  6. CI/CD 采集:在 GitLab-Runner 或 Jenkins k8s 插件里,把 rocm-smi --showuse --json 输出写到 $CI_PROJECT_DIR/gpu_util.json后续 stage 用 jq 提取 GPU 利用率做质量门禁(>95 % 触发排队限流)。
  7. 故障排查三板斧
    • dmesg | grep amdgpu 看驱动是否加载;
    • ls -l /dev/kfd 确认 666 权限;
    • rocminfo 能否列出 Agent,若失败则基本可判定为驱动/设备问题而非容器问题

答案

  1. 宿主机准备
    以 Ubuntu 22.04 为例,安装官方 ROCm 5.7 驱动:

    sudo apt update && sudo apt install -y amdgpu-dkms rocm-dev
    sudo usermod -aG render,video $USER
    

    新开会话使组权限生效,执行 rocm-smi 验证宿主机可见 GPU。

  2. 最小 Dockerfile

    FROM ubuntu:22.04
    ARG ROCM_VER=5.7
    RUN apt-get update && \
        apt-get install -y --no-install-recommends \
        ca-certificates gnupg2 wget \
        && wget -q -O - https://repo.radeon.com/rocm/rocm.gpg.key | apt-key add - \
        && echo "deb [arch=amd64] https://repo.radeon.com/rocm/apt/${ROCM_VER} ubuntu main" > /etc/apt/sources.list.d/rocm.list \
        && apt-get update \
        && apt-get install -y rocm-smi-lib \
        && apt-get clean \
        && rm -rf /var/lib/apt/lists/*
    ENV PATH=/opt/rocm/bin:$PATH
    ENTRYPOINT ["rocm-smi"]
    
  3. 构建与运行

    docker build -t rocm-smi:5.7 .
    docker run --rm \
      --device=/dev/kfd \
      --device=/dev/dri \
      --group-add $(getent group render | cut -d: -f3) \
      --security-opt seccomp=default-with-amdgpu.json \
      rocm-smi:5.7 --showuse
    

    其中 default-with-amdgpu.json 在官方 seccomp 模板里增加 amdgpu_ioctl 允许列表,符合国内安全基线

  4. 持续监控脚本
    在容器启动脚本里加入:

    while true; do
      rocm-smi --showuse --json > /tmp/gpu.json
      cat /tmp/gpu.json | jq '.[] | "\(.gpu) \(.gpu_use)%"'
      sleep 10
    done &
    

    日志通过 stdout 输出,可被 Loki/ELK 直接采集

  5. 常见错误与修复

    • rocm-smi: command not found → 镜像未装 rocm-smi-lib,或 PATH 未包含 /opt/rocm/bin;
    • hsa api call failure:0x1008 → 宿主机驱动与容器 ROCm 版本不一致,统一升级到 5.7
    • Permission denied on /dev/kfd → 未加 render 组,或宿主机 udev 规则把 kfd 设成 600,修复 udev 规则为 666

拓展思考

  1. 多 GPU 隔离:国内训练集群常把 8 卡拆成 2×4 组,用 DOCKER_ROCM_DEVICES=card0,card1,card2,card3 环境变量,启动时通过 --device 逐一挂载,并在容器内用 rocm-smi --id 0,1,2,3 限定查询范围,实现业务级 GPU 分区
  2. 与 Kubernetes 设备插件联动:AMD 官方 k8s-device-plugin 已支持 device plugin v1beta1,在 Pod 里申请 amd.com/gpu: 1 后,插件会自动注入 /dev/kfd 与对应 renderD*,无需人工写 volumeMount;但监控 sidecar 仍需共享 IPC,建议用 EmptyDir 共享 /tmp/rocm 让 sidecar 读到同一 hsa 句柄。
  3. 安全加固:金融场景要求非 root 运行,可在 Dockerfile 加 USER 65534:65534,同时把 /dev/kfd 权限改成 666,并通过 AppArmor 限制容器对 /sys/class/kfd 的写操作,实现“看得见、改不了”。
  4. 镜像预热与缓存:大模型镜像 8 GB+,国内 Harbor 可开 P2P 预热,结合 Dragonfly 把 rocm-smi 层提前分发到 GPU 节点,使 100 节点同时拉起时间从 15 min 降到 90 s
  5. 与 Prometheus 生态对接:社区已提供 rocm-smi-exporter,容器化后挂在 DaemonSet,自动把 GPU 利用率、显存、温度转为 Prometheus 指标,再经 Grafana 模板展示,面试时可现场画一条 PromQLrate(rocm_gpu_utilization_percent[5m]) > 90,体现可观测性落地能力