3、GPU节点驱动与容器运行时:NVIDIA驱动版本检查、nvidia-docker与containerd配置、nvidia-smi在Pod内的验证
好,咱们直接进入正题。GPU节点能不能用,说白了就三件事:驱动对不对、运行时通不通、Pod里能不能跑。这三步但凡有一个掉链子,你的推理服务就别想起来。我这些年排查过的故障,十有八九都卡在这几个环节上。
3.1 先摸清家底:NVIDIA驱动版本检查
你想想看,K8s调度GPU靠的是什么?靠的是节点上报的 nvidia.com/gpu 资源。如果驱动没装或者版本不对,节点根本认不出GPU。我个人习惯,拿到一台新机器,第一件事就是跑 nvidia-smi。
# 检查驱动版本和GPU状态
nvidia-smi
# 输出示例(关键看Driver Version和CUDA Version)
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 535.129.03 Driver Version: 535.129.03 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 NVIDIA A100 80GB On | 00000000:00:04.0 Off | 0 |
| 0% 35C P0 45W / 300W| 0MiB / 81920MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
这里有个坑,我踩过好几次。驱动版本和CUDA版本不是一回事。驱动版本决定了你能装什么版本的CUDA Toolkit。比如驱动是535,那CUDA 12.x基本都能用。但如果你驱动是470,硬要上CUDA 12,那肯定报错。
还有一个容易忽略的点——nvidia-persistenced 服务。这个服务如果不启动,GPU可能会在空闲时进入低功耗模式,导致首次调用时延迟很高。我建议你把它设为开机自启:
# 启动持久化服务
sudo systemctl enable nvidia-persistenced
sudo systemctl start nvidia-persistenced
3.2 容器运行时配置:nvidia-docker与containerd
驱动装好了,接下来就是让容器能访问GPU。这里分两种情况:Docker和containerd。K8s 1.24之后默认用containerd,但很多老集群还在用Docker。
3.2.1 Docker环境下的配置
如果你用的是Docker,需要安装 nvidia-container-toolkit。这个工具说白了就是个插件,让Docker能调用NVIDIA驱动。
# 安装nvidia-container-toolkit
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
# 重启Docker服务
sudo systemctl restart docker
安装完后,验证一下:
# 测试GPU是否能在容器内识别
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi
如果能看到GPU信息,说明Docker这边通了。我曾经遇到过一个情况,--gpus all 参数死活不生效,最后发现是Docker的运行时配置里没加上 nvidia 运行时。你可以在 /etc/docker/daemon.json 里检查:
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
}
}
3.2.2 containerd环境下的配置
现在新集群基本都是containerd了。配置方式略有不同,但原理一样。
# 配置containerd使用nvidia运行时
sudo nvidia-ctk runtime configure --runtime=containerd
# 重启containerd
sudo systemctl restart containerd
配置完成后,检查 /etc/containerd/config.toml,确保有类似下面的内容:
[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"
crictl info 命令检查运行时是否生效。如果输出里能看到 nvidia 运行时,那就对了。
3.3 Pod内验证:nvidia-smi能不能跑起来
节点配置好了,最后一步就是在Pod里验证。这一步最容易出问题,因为K8s的调度策略和容器运行时配置都可能影响结果。
先创建一个测试Pod:
apiVersion: v1
kind: Pod
metadata:
name: gpu-test
spec:
containers:
- name: cuda-container
image: nvidia/cuda:12.2.0-base-ubuntu22.04
command: ["nvidia-smi"]
resources:
limits:
nvidia.com/gpu: 1
restartPolicy: Never
部署并查看日志:
kubectl apply -f gpu-test.yaml
kubectl logs gpu-test
如果看到GPU信息,恭喜你,通了。如果报错,常见原因有这几个:
- Pod一直Pending:说明节点没有上报GPU资源。检查
kubectl describe node看nvidia.com/gpu的容量。 - Pod启动后CrashLoopBackOff:大概率是容器内找不到驱动。检查镜像是否包含CUDA驱动,或者节点驱动版本是否兼容。
- nvidia-smi报错"Failed to initialize NVML":这是经典问题。通常是容器运行时没配置好,或者驱动版本不匹配。
nvidia-smi 只是第一步。对于vLLM,你还需要验证CUDA版本是否满足要求。建议在Pod内跑 python -c "import torch; print(torch.cuda.is_available())",如果返回True,那才算真正准备好。
3.4 知识体系总览
下面这张图,是我自己总结的GPU节点排查流程。你照着这个顺序走,基本不会漏掉什么。
嗯,这张图基本把排查思路串起来了。你照着这个流程走,大部分问题都能定位到。我个人习惯,每部署一个新节点,都会跑一遍这个流程,确保万无一失。
nvidia-smi 正常,但Pod里就是识别不到GPU。查了半天,发现是K8s的 device-plugin 没启动。记得检查 kubectl get pods -n kube-system | grep nvidia,确保 nvidia-device-plugin 在运行。
好了,这一章的内容就这些。驱动检查、运行时配置、Pod验证,三步走完,GPU节点基本就稳了。下一章我们聊聊vLLM的镜像构建和部署策略,到时候见。