2. 安装与配置NVIDIA Container Toolkit

安装与配置NVIDIA Container Toolkit 学习卡片

为什么需要 NVIDIA Container Toolkit

宿主机上装好 NVIDIA 驱动后,nvidia-smi 能看到 GPU,但容器默认只能看到宿主机的 CPU、内存和普通设备节点,看不到 /dev/nvidia* 这些字符设备,也拿不到驱动提供的用户态库。NVIDIA Container Toolkit 的作用就是在容器启动时,把宿主机的 GPU 设备节点、驱动库和必要环境变量注入到容器内,让容器里的进程能直接调用 CUDA。

它由三部分组成:nvidia-container-toolkit(核心包,含 nvidia-container-runtime 与 nvidia-container-cli)、nvidia-container-toolkit-base(基础工具)、以及运行时适配层。安装后还需要把容器运行时(containerd 或 Docker)的配置指向 NVIDIA 的 runtime,否则容器仍走默认 runc,GPU 不会出现。

宿主机 (GPU Node) NVIDIA 驱动 nvidia.ko / nvidia-uvm.ko libcuda.so / libnvidia-ml.so /dev/nvidia0, /dev/nvidiactl 物理 GPU A100 / V100 / T4 PCIe 设备 设备节点与库 /dev/nvidia* /usr/lib/x86_64-linux-gnu/libcuda* 由驱动提供,容器默认不可见 NVIDIA Container Toolkit nvidia-container-cli 探测设备、挂载库、设置环境变量 nvidia-container-runtime 包装 runc,注入 GPU 资源 runtime 配置适配 containerd / Docker 指向 nvidia 容器运行时 containerd → nvidia-container-runtime Docker → nvidia-container-runtime

安装 nvidia-container-toolkit

以下命令适用于 Ubuntu/Debian 系 GPU 节点。先添加 NVIDIA 官方仓库,再安装工具包。安装前确认驱动已就绪(nvidia-smi 正常输出),否则后续配置无法生效。

# 1. 添加 NVIDIA 容器工具包仓库
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
  | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
  | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
  | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

# 2. 更新并安装
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

# 3. 确认版本
nvidia-container-toolkit --version
nvidia-container-cli --version

安装完成后,nvidia-container-runtime 会出现在 /usr/bin/ 下。此时容器运行时还不知道它的存在,需要下一步配置。

配置 containerd 运行时

Kubernetes 1.24 之后默认使用 containerd 作为容器运行时,因此这里以 containerd 为主。使用 nvidia-ctk 工具自动生成配置,避免手工编辑 TOML 出错。

# 生成 containerd 配置并写入默认路径
sudo nvidia-ctk runtime configure --runtime=containerd

# 查看生成的配置片段
sudo cat /etc/containerd/config.toml | grep -A 5 nvidia

# 重启 containerd 使配置生效
sudo systemctl restart containerd
sudo systemctl status containerd --no-pager

该命令会在 /etc/containerd/config.toml 中注册一个名为 nvidia 的 runtime,并设置 default_runtime_name = "nvidia"。关键配置片段如下:

[plugins."io.containerd.grpc.v1.cri".containerd]
  default_runtime_name = "nvidia"

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
  runtime_type = "io.containerd.runc.v2"
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
    BinaryName = "/usr/bin/nvidia-container-runtime"
如果节点同时使用 Docker,可执行 sudo nvidia-ctk runtime configure --runtime=docker,它会修改 /etc/docker/daemon.json 并添加 nvidia runtime,然后 sudo systemctl restart docker。Kubernetes 节点通常只需配置 containerd。

验证容器能否访问 GPU

配置完成后,用官方 CUDA 镜像跑一个容器,直接执行 nvidia-smi。如果容器内能看到与宿主机一致的 GPU 列表,说明工具链已打通。

# containerd 环境下用 ctr 验证
sudo ctr run --rm --gpus 0 docker.io/nvidia/cuda:12.4.0-base-ubuntu22.04 gpu-test nvidia-smi

# Docker 环境下验证
sudo docker run --rm --gpus all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi

预期输出应包含 GPU 型号、驱动版本、显存信息,且与宿主机 nvidia-smi 一致。若报错 no CUDA-capable device is detected,说明 runtime 未生效或设备未注入,需回到上一步检查 default_runtime_name 是否已改为 nvidia,并确认 containerd 已重启。

常见坑:nvidia-ctk runtime configure 执行后必须重启 containerd,否则配置不加载;若节点使用 kubelet 的 --container-runtime-endpoint 指向非默认 socket,需确认该 socket 对应的 containerd 实例就是被修改配置的那个。

关键检查点速查

检查项命令通过标准
工具包已安装nvidia-container-toolkit --version输出版本号,无报错
runtime 已注册grep -A3 nvidia /etc/containerd/config.toml存在 runtimes.nvidia 段
默认 runtime 已切换grep default_runtime_name /etc/containerd/config.toml值为 nvidia
containerd 已重启systemctl status containerdactive (running)
容器可见 GPUctr run --rm --gpus 0 ... nvidia-smi输出 GPU 列表与宿主机一致