Nvidia Device Plugin入门三之volume mount策略

1. 背景:原始的 envvar 模式

在前一篇文章里面提到最早的envvar实现里,NVIDIA Device Plugin 分配 GPU 的方式是:

  1. Pod 申请 GPU → kubelet 调用 Device Plugin 的 Allocate() 方法
  2. Device Plugin 返回一个环境变量:
ini 复制代码
    NVIDIA_VISIBLE_DEVICES=<GPU-UUID 或 index>
  1. 容器 runtime(nvidia-container-runtime)启动时读取这个环境变量,决定注入哪些 /dev/nvidia* 设备

好处

  • 简单,runtime 无需改动 CRI API
  • 跨 Docker / containerd / CRI-O / Podman 都能用

缺点

  • 安全漏洞 :任何 Pod 只要能设置 NVIDIA_VISIBLE_DEVICES=all,就能访问所有 GPU,绕过 Device Plugin 的分配逻辑
  • 默认镜像问题 :很多 NVIDIA 官方镜像(nvidia/cuda:*)默认就带 NVIDIA_VISIBLE_DEVICES=all,直接全卡开放
  • 不受 Kubernetes 资源模型约束:K8s 无法阻止用户在 PodSpec 里手动设置这个 envvar

2. volume-mounts 模式的设计目标

目标

  1. 防止非特权容器绕过 Device Plugin
    • 不再用环境变量传递 GPU 列表
    • 改成通过容器内的一个特殊目录 /var/run/nvidia-container-devices 传递
    • 这个目录由 kubelet 挂载,普通用户不能自己挂载
  2. 保持兼容性
    • runtime 仍然可以从这个目录读取 GPU 列表
    • 特权容器(如监控、Device Plugin 自身)仍然可以访问全部 GPU
  3. 简化实现
    • 不引入新的 CRI API
    • 只是把"传递 GPU 列表"的方式从 envvar → volume mount

4. volume-mounts 的工作方式

  1. Device Plugin 分配 GPU
    在 AllocateResponse 里返回挂载信息:

    javascript 复制代码
    hostPath=/dev/null
    containerPath=/var/run/nvidia-container-devices/<GPU-UUID>

    文件名部分 <GPU-UUID> 就是 GPU 身份标识。

  2. kubelet 写进 Pod spec
    生成容器的挂载配置。

  3. containerd/runc 启动容器
    在容器内创建 /var/run/nvidia-container-devices 目录,并挂载 /dev/null<GPU-UUID> 文件。

  4. nvidia-container-runtime 启动前解析
    遍历 /var/run/nvidia-container-devices,读取文件名(UUID),决定注入哪些 /dev/nvidia*


5. 解决的问题

5.1 安全性

  • 非特权容器不能随便挂载 /var/run/nvidia-container-devices,因此不能伪造 GPU 列表
  • 即使用户在 PodSpec 里设置 NVIDIA_VISIBLE_DEVICES=all,runtime 也会忽略(accept-nvidia-visible-devices-envvar-when-unprivileged=false

5.2 避免默认镜像全卡开放

  • 即使镜像里有 NVIDIA_VISIBLE_DEVICES=all,也不会生效
  • 只有 Device Plugin 分配的 GPU 会被注入

5.3 与 Kubernetes 资源模型一致

  • GPU 分配完全由 Device Plugin 控制
  • 用户无法绕过调度器直接访问 GPU

6. 局限性

  • 如果集群管理员没有禁用 hostPath 挂载,用户理论上可以自己挂载 /var/run/nvidia-container-devices 目录伪造 GPU 列表(所以生产环境应禁用 hostPath)
  • envvar模式一样,systemctl daemon-reload会导致容器内失去GPU操作权限
  • 这是 CDI(Container Device Interface)出现前的临时方案,在2020年提出后实现的,现已经被CDI模式取代

7. 总结一句话

volume-mounts 模式的用途

用一个容器内的只读挂载目录 /var/run/nvidia-container-devices 代替环境变量传递 GPU 列表,

防止非特权容器绕过 Kubernetes Device Plugin 直接访问 GPU,保证 GPU 分配的安全性和一致性。

8. 常见问题

该模式下启动容器报错

bash 复制代码
Warning  Failed   5s (x2 over 6s)  kubelet  Error: failed to create containerd task: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running prestart hook #0: exit status 1, stdout: , stderr: Auto-detected mode as 'legacy'
nvidia-container-cli: device error: /var/run/nvidia-container-devices: unknown device

这个模式需要调整节点上的nvidia容器运行时配置,/etc/nvidia-container-runtime/config.toml中设置

ini 复制代码
accept-nvidia-visible-devices-as-volume-mounts = true
相关推荐
zzz.105 小时前
【Kubernetes知识点】CRD客户资源定义及Gateway
云原生·容器·kubernetes
泡沫冰@17 小时前
K8S集群管理(3)
云原生·容器·kubernetes
nathan052920 小时前
Kubernetes 实战练习指南
云原生·容器·kubernetes
無名之輩21 小时前
Nvidia Device Plugin入门二之envvar策略
kubernetes
syty20201 天前
K8s是什么
容器·kubernetes·dubbo
灵犀物润1 天前
Kubernetes 配置检查与发布安全清单
安全·容器·kubernetes
360智汇云1 天前
k8s交互桥梁:走进Client-Go
golang·kubernetes·交互
xy_recording1 天前
Day20 K8S学习
学习·容器·kubernetes
衍余未了1 天前
k8s 内置的containerd配置阿里云个人镜像地址及认证
java·阿里云·kubernetes