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"
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 生命周期 | 大规模集群 |
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+ |
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 库。
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 节点上的协作关系:
从图中可以看出,GPU 硬件通过内核驱动暴露给操作系统,容器运行时负责将 GPU 设备挂载到容器内,而 CUDA 基础镜像提供应用所需的运行时库。任何一层的版本断裂都会导致 GPU 不可用。
3.5 配置验证清单
完成驱动安装和运行时配置后,建议按以下步骤逐层验证:
- 宿主机验证:执行
nvidia-smi,确认驱动版本和 GPU 列表正常显示。 - 运行时验证:使用
docker run --rm --gpus all nvidia/cuda:12.0-runtime nvidia-smi(Docker)或crictl run(containerd)测试 GPU 容器启动。 - Kubernetes 验证:部署一个请求 GPU 资源的 Pod,检查
kubectl logs输出是否包含 GPU 信息。
- 所有 GPU 节点使用相同的驱动版本和运行时配置,避免调度偏差。
- 将驱动安装和运行时配置纳入节点初始化脚本(如 cloud-init 或 Ansible),确保节点重建后自动恢复。
- 定期检查 NVIDIA 官方安全公告,及时更新驱动版本。