3. NVIDIA驱动与容器运行时

在 Kubernetes 集群中启用 GPU 资源调度,底层依赖三个核心环节:NVIDIA 内核驱动、容器运行时接口以及CUDA 基础镜像。任何一个环节的版本不匹配或配置错误,都会导致 GPU 无法被 Pod 识别或调度失败。本章从驱动安装约束开始,逐步深入到运行时配置与镜像选型,帮助你在集群层面建立稳定的 GPU 基础环境。

3.1 NVIDIA 驱动安装要求

NVIDIA 驱动是 GPU 与操作系统之间的桥梁。在 Kubernetes 节点上安装驱动时,需要同时满足内核版本、驱动版本与 CUDA 版本的兼容性约束。

3.1.1 驱动版本与内核版本匹配

NVIDIA 驱动以内核模块(nvidia.ko)的形式加载,必须与当前 Linux 内核版本严格匹配。驱动安装后,建议通过以下命令验证模块加载状态:

# 检查驱动模块是否加载
lsmod | grep nvidia

# 查看驱动版本
nvidia-smi | grep "Driver Version"
常见问题:内核升级后驱动模块未重新编译,导致 nvidia-smi 报错 "Failed to initialize NVML: Driver/library version mismatch"。此时需要重启节点或重新安装驱动。

3.1.2 驱动版本与 CUDA 版本兼容性

驱动版本决定了支持的最高 CUDA 版本。下表列出常见驱动版本与 CUDA 版本的对应关系:

NVIDIA 驱动版本 支持的最高 CUDA 版本 推荐场景
525.60.11 CUDA 12.0 新集群、A100/H100 系列
470.182.03 CUDA 11.4 V100/T4 稳定生产环境
418.165.02 CUDA 10.1 旧版 GPU(K80/M60)

选型建议:优先选择 NVIDIA 官方 LTS(长期支持)驱动分支,例如 470 系列或 525 系列,避免使用 Beta 或快速迭代分支。

3.1.3 驱动安装方式对比

安装方式 优点 缺点 适用场景
NVIDIA 官方 .run 包 版本最新、可定制安装参数 需手动处理内核模块签名 开发测试环境
操作系统包管理器(apt/yum) 自动处理依赖、支持 DKMS 版本可能滞后 生产环境推荐
NVIDIA GPU Operator Kubernetes 原生管理、自动升级 依赖 Operator 生命周期 大规模集群
生产建议:使用操作系统包管理器安装驱动,并启用 DKMS(Dynamic Kernel Module Support),确保内核升级后驱动模块自动重建。

3.2 nvidia-docker2 与 containerd 配置

容器运行时需要能够将宿主机 GPU 设备挂载到容器内部。传统方案使用 nvidia-docker2,而 Kubernetes 1.24+ 默认使用 containerd,两者配置方式不同。

3.2.1 nvidia-docker2 配置(Docker 运行时)

如果集群仍使用 Docker 作为容器运行时,需要安装 nvidia-docker2 并配置 Docker daemon:

# 安装 nvidia-docker2
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \
  sudo tee /etc/yum.repos.d/nvidia-docker.repo
sudo yum install -y nvidia-docker2

# 重启 Docker 服务
sudo systemctl restart docker

# 验证 GPU 容器
docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi

配置完成后,Docker 会自动将 --gpus 参数转换为设备挂载和 nvidia-container-runtime 调用。

3.2.2 containerd 配置(Kubernetes 默认运行时)

Kubernetes 1.24+ 默认使用 containerd,需要配置 nvidia-container-runtime 作为 containerd 的运行时 handler:

# 安装 nvidia-container-runtime
sudo yum install -y nvidia-container-runtime

# 编辑 containerd 配置文件 /etc/containerd/config.toml
# 在 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes] 下添加:
[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"

# 重启 containerd
sudo systemctl restart containerd
关键配置项说明:
  • runtime_type:固定为 io.containerd.runc.v2,表示使用 runc 作为底层运行时。
  • BinaryName:指定 nvidia-container-runtime 可执行文件路径,用于拦截容器创建请求并注入 GPU 设备。

3.2.3 运行时配置对比

特性 nvidia-docker2 containerd + nvidia-container-runtime
适用运行时 Docker containerd
配置复杂度 低(一键安装) 中(需手动编辑 config.toml)
Kubernetes 原生支持 需额外配置 device plugin 原生支持 CRI
推荐场景 旧集群迁移过渡 新集群、K8s 1.24+
避坑提示:containerd 配置中如果缺少 runtime_type 字段,nvidia-container-runtime 将无法正确注册,Pod 会报错 Failed to create sandbox: rpc error: code = Unknown desc = failed to start sandbox container。

3.3 CUDA 基础镜像选择

CUDA 基础镜像决定了容器内可用的 CUDA 工具包版本和运行时库。选择不当会导致应用无法调用 GPU 或出现符号链接错误。

3.3.1 镜像标签体系

NVIDIA 官方提供多种 CUDA 镜像标签,常见分类如下:

标签类型 示例 包含内容 镜像大小
base nvidia/cuda:12.0.0-base-ubuntu22.04 CUDA 运行时库、cudart ~800 MB
runtime nvidia/cuda:12.0.0-runtime-ubuntu22.04 base + CUDA 工具(cuBLAS、cuFFT 等) ~1.5 GB
devel nvidia/cuda:12.0.0-devel-ubuntu22.04 runtime + 头文件、静态库、nvcc 编译器 ~3.5 GB

3.3.2 选型原则

  • 生产推理服务:优先使用 runtime 标签,包含推理所需的 cuBLAS 和 TensorRT 库,同时镜像体积适中。
  • 训练任务:使用 devel 标签,因为训练框架(如 PyTorch、TensorFlow)需要 nvcc 编译自定义算子。
  • 最小化镜像:如果应用仅依赖 cudart,可以使用 base 标签,但需自行安装其他 CUDA 库。
版本对齐:CUDA 基础镜像的版本必须 ≤ 宿主机驱动支持的最高 CUDA 版本。例如驱动版本 525.60.11 支持 CUDA 12.0,则镜像可以使用 CUDA 12.0 或更低版本,但不能使用 CUDA 12.1。

3.3.3 多阶段构建示例

推荐使用多阶段构建分离编译环境和运行环境:

# 第一阶段:编译
FROM nvidia/cuda:12.0.0-devel-ubuntu22.04 AS builder
COPY src/ /app/src
WORKDIR /app
RUN nvcc -o gpu_app src/main.cu

# 第二阶段:运行
FROM nvidia/cuda:12.0.0-runtime-ubuntu22.04
COPY --from=builder /app/gpu_app /usr/local/bin/
CMD ["gpu_app"]

这种方式将编译工具链隔离在构建阶段,最终镜像仅包含运行时库,体积减少约 60%。

3.4 整体架构关系

下图展示了驱动、运行时与镜像在 Kubernetes 节点上的协作关系:

NVIDIA 驱动与容器运行时架构关系 GPU 硬件(物理设备) NVIDIA 内核驱动(nvidia.ko) nvidia-docker2(Docker 运行时) nvidia-container-runtime(containerd) 容器(CUDA 基础镜像 + 应用) 关键依赖链 驱动版本 → 运行时版本 → CUDA 镜像版本,三者必须满足兼容性约束

从图中可以看出,GPU 硬件通过内核驱动暴露给操作系统,容器运行时负责将 GPU 设备挂载到容器内,而 CUDA 基础镜像提供应用所需的运行时库。任何一层的版本断裂都会导致 GPU 不可用。

3.5 配置验证清单

完成驱动安装和运行时配置后,建议按以下步骤逐层验证:

  1. 宿主机验证:执行 nvidia-smi,确认驱动版本和 GPU 列表正常显示。
  2. 运行时验证:使用 docker run --rm --gpus all nvidia/cuda:12.0-runtime nvidia-smi(Docker)或 crictl run(containerd)测试 GPU 容器启动。
  3. Kubernetes 验证:部署一个请求 GPU 资源的 Pod,检查 kubectl logs 输出是否包含 GPU 信息。
生产环境最佳实践:
  • 所有 GPU 节点使用相同的驱动版本和运行时配置,避免调度偏差。
  • 将驱动安装和运行时配置纳入节点初始化脚本(如 cloud-init 或 Ansible),确保节点重建后自动恢复。
  • 定期检查 NVIDIA 官方安全公告,及时更新驱动版本。