3. NVIDIA GPU Operator部署:安装、配置RuntimeClass与验证可调度性

好,咱们进入实战环节。

上一章我们把Kubernetes集群搭好了,GPU驱动也装上了。但说实话,那只是万里长征第一步。你想想看,如果每次部署一个需要GPU的Pod,都得手动去配驱动版本、配容器运行时、配设备插件……那运维同学怕是要疯掉。

NVIDIA GPU Operator就是来解决这个问题的。它把GPU相关的所有组件——驱动、运行时、设备插件、监控——全都打包成Kubernetes原生资源,一键部署,自动管理。

我个人习惯在生产环境里优先用Operator,而不是手动拼凑组件。为什么?因为升级、回滚、扩缩容,Operator都能帮你搞定,省心太多。

3.1 什么是NVIDIA GPU Operator

说白了,GPU Operator就是一个Kubernetes的Operator,它负责管理GPU集群的整个生命周期。

它包含以下几个核心组件:

  • GPU Driver:自动在节点上安装NVIDIA驱动
  • CUDA Runtime:提供容器内CUDA运行环境
  • NVIDIA Container Toolkit:让容器能访问GPU设备
  • Kubernetes Device Plugin:向Kubelet注册GPU资源
  • DCGM Exporter:采集GPU监控指标
  • MIG Manager:管理MIG(多实例GPU)配置

嗯,这里要注意:GPU Operator不是必须的。你可以手动装驱动、配运行时、部署Device Plugin。但如果你有10台、100台GPU节点,手动维护就是噩梦。Operator的价值就在这里。

核心思路:GPU Operator把GPU资源抽象成Kubernetes的扩展资源,让Pod像申请CPU一样申请GPU。

3.2 安装GPU Operator

安装之前,先确认几个前提条件:

  1. Kubernetes集群已正常运行(上一章我们搞定了)
  2. 节点上有NVIDIA GPU(检查一下:nvidia-smi能跑通)
  3. 节点上不要预装NVIDIA驱动(Operator会帮你装)
  4. Helm 3已安装(我们用Helm部署Operator)

我曾经踩过一个坑:节点上提前装了驱动,结果Operator检测到驱动版本不一致,直接报错。所以建议让Operator全权管理驱动。

好,开始安装。先添加Helm仓库:

helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update

然后创建一个命名空间:

kubectl create namespace gpu-operator

接下来,安装GPU Operator。我个人习惯把配置参数写进values文件,方便后续管理:

cat << EOF > gpu-operator-values.yaml
operator:
  defaultRuntime: containerd
  use_ocp_driver_toolkit: false

driver:
  enabled: true
  version: "535.154.05"
  repoConfig:
    configMapName: nvidia-driver-repo-config

toolkit:
  enabled: true

devicePlugin:
  enabled: true
  version: "v0.14.1"

dcgmExporter:
  enabled: true

migManager:
  enabled: false
EOF

这里有几个关键点:

  • defaultRuntime: containerd:指定容器运行时。Kubernetes 1.24+默认用containerd,别选错了。
  • driver.version:指定驱动版本。建议选一个经过验证的稳定版本,别追新。
  • migManager.enabled: false:MIG功能默认关掉,需要时再开。

执行安装:

helm install gpu-operator nvidia/gpu-operator \
  --namespace gpu-operator \
  --values gpu-operator-values.yaml

等几分钟,检查Pod状态:

kubectl get pods -n gpu-operator

你应该能看到类似这样的输出:

NAME                                                          READY   STATUS    RESTARTS   AGE
gpu-operator-7f8b9c6d4b-abcde                                1/1     Running   0          5m
nvidia-container-toolkit-daemonset-xxxxx                      1/1     Running   0          4m
nvidia-dcgm-exporter-xxxxx                                    1/1     Running   0          4m
nvidia-device-plugin-daemonset-xxxxx                          1/1     Running   0          4m
nvidia-driver-daemonset-xxxxx                                 1/1     Running   0          5m

所有DaemonSet都处于Running状态,说明安装成功。

小技巧:如果驱动安装失败,检查节点上的操作系统版本和内核版本。Operator会下载对应版本的驱动包,如果源里没有,就会卡住。我遇到过CentOS 7.9内核太老,驱动编译不过去的情况。解决办法是升级内核,或者手动指定驱动版本。

3.3 配置RuntimeClass

GPU Operator装好了,但Pod怎么知道要用GPU呢?

这里就需要RuntimeClass了。RuntimeClass告诉容器运行时:这个Pod需要特殊处理,比如挂载GPU设备、设置CUDA环境变量。

检查一下Operator是否自动创建了RuntimeClass:

kubectl get runtimeclass

输出应该包含:

NAME                   HANDLER               AGE
nvidia                 nvidia                10m

如果没有,可以手动创建。我个人习惯用YAML定义,清晰明了:

cat << EOF | kubectl apply -f -
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: nvidia
handler: nvidia
EOF

这个RuntimeClass的handler名字是nvidia,对应容器运行时里的配置。Operator安装时已经帮我们把containerd的配置改好了,所以直接用就行。

注意:RuntimeClass的名字必须和容器运行时里的handler名字一致。如果你改了handler名字,Pod就找不到对应的运行时了。我曾经手贱改过一次,结果Pod一直Pending,查了半天才发现是名字没对上。

3.4 验证GPU可调度性

组件都就位了,我们来验证一下GPU能不能被调度。

先看看节点上的GPU资源:

kubectl describe node <node-name> | grep -A 10 "Capacity"

你应该能看到类似:

nvidia.com/gpu:     1
nvidia.com/gpu.memory:     8192
nvidia.com/gpu.family:     ampere

这说明Device Plugin已经成功注册了GPU资源。

接下来,跑一个测试Pod:

cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: gpu-test
spec:
  runtimeClassName: nvidia
  containers:
  - name: cuda-container
    image: nvidia/cuda:12.2.0-base-ubuntu22.04
    command: ["nvidia-smi"]
    resources:
      limits:
        nvidia.com/gpu: 1
  restartPolicy: Never
EOF

注意几个关键点:

  • runtimeClassName: nvidia:指定使用NVIDIA RuntimeClass
  • resources.limits.nvidia.com/gpu: 1:申请1个GPU
  • 镜像用nvidia/cuda,里面自带nvidia-smi

查看Pod日志:

kubectl logs gpu-test

如果输出类似:

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 535.154.05   Driver Version: 535.154.05   CUDA Version: 12.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla T4            Off  | 00000000:00:1E.0 Off |                    0 |
| N/A   45C    P0    28W /  70W |      0MiB / 15360MiB |      0%      Default |
|+-------------------------------+----------------------+----------------------+

恭喜!GPU已经可以被Kubernetes调度了。

验证要点:Pod能跑nvidia-smi,说明GPU设备挂载成功、驱动正常、CUDA运行时可用。这是最直接的验证方式。

3.5 常见问题与排查

部署过程中,我遇到过几个典型问题,分享出来供你参考:

问题现象 可能原因 解决办法
Pod一直Pending 节点没有GPU资源,或RuntimeClass未配置 检查kubectl describe node是否有nvidia.com/gpu;检查RuntimeClass是否存在
Pod启动报错"cannot find device" 容器运行时未正确配置NVIDIA runtime 检查containerd配置中是否包含nvidia runtime;重启containerd
nvidia-smi报错"driver not loaded" 驱动安装失败或版本不匹配 查看nvidia-driver-daemonset日志;检查内核版本
GPU Operator Pod CrashLoopBackOff 配置参数错误或依赖组件缺失 查看Operator日志;检查values文件中的参数

嗯,这里要特别提一下:如果你用的是Kubernetes 1.27及以上版本,注意检查kubelet--runtime-request-timeout参数。默认是2分钟,如果驱动安装时间较长,可能会超时。我建议调大到5分钟。

3.6 本章小结

这一章我们完成了三件事:

  • 用Helm部署了NVIDIA GPU Operator
  • 配置了RuntimeClass,让Pod能使用GPU
  • 跑了一个测试Pod,验证了GPU可调度性

说白了,现在你的Kubernetes集群已经具备了GPU调度能力。接下来,我们就可以在这个基础上部署NVSHMEM应用了。

不过,在进入下一章之前,我建议你多做几个实验:试试申请多个GPU、试试不同镜像、试试MIG配置。只有亲手踩过坑,才能真正理解这些组件的工作原理。

个人建议:把GPU Operator的values文件保存到Git仓库里,方便版本管理和回滚。我每次升级Operator之前,都会先备份当前配置,万一出问题能快速恢复。


公众号:蓝海资料掘金营,微信deep3321