服务器K8s集群GPU故障排查:从节点掉卡到Pod异常的定位思路
K8s集群里GPU出问题,通常不是单一原因,而是节点、驱动、插件、调度四层里某一层断了。
排查时建议按“先看节点识别、再看驱动状态、再看Device Plugin、最后看Pod事件”的顺序走,避免一上来就重装驱动。
先确认故障范围
登录集群任意管理节点,先看GPU节点是否Ready,以及GPU资源是否被上报。
kubectl get nodes -o wide
kubectl describe node | grep -A5 "Capacity"
kubectl get pods -A -o wide | grep -i gpu
如果 Capacity 里没有 nvidia.com/gpu,说明K8s层面根本没识别到GPU,问题多半在节点侧。
如果节点Ready但GPU数量为0,优先查驱动和Device Plugin。
节点侧检查驱动与设备文件
通过SSH登录GPU节点,依次执行:
nvidia-smi
ls -l /dev/nvidia*
systemctl status nvidia-persistenced
nvidia-smi 报“No devices were found”或直接卡住,常见原因是驱动未加载、GPU被其他进程占用、或虚拟机直通配置异常。
检查内核模块:
lsmod | grep nvidia
dmesg | grep -i nvidia | tail -50
如果 lsmod 没有输出,尝试加载模块:
modprobe nvidia
modprobe nvidia_uvm
加载失败时,dmesg 里通常会有版本不匹配或Secure Boot拦截的提示。
Device Plugin没起来会怎样
K8s不直接管理GPU,而是通过 nvidia-device-plugin 把GPU数量上报给kubelet。
检查:
kubectl get pods -n kube-system | grep nvidia
kubectl logs -n kube-system
常见日志关键词:Failed to initialize NVML、no devices found、incompatible driver。
如果是DaemonSet方式部署,确认目标节点没有被污点或标签排除:
kubectl describe node | grep -i taint
kubectl get ds -n kube-system nvidia-device-plugin -o yaml | grep -A10 tolerations
插件恢复后,回到管理节点执行 kubectl describe node ,确认 nvidia.com/gpu 数量已恢复。
Pod调度失败怎么读事件
GPU Pod一直Pending时,不要只看Pod状态,重点看Events:
kubectl describe pod -n
常见事件与对应原因:
0/3 nodes are available: 3 Insufficient nvidia.com/gpu:节点GPU资源未上报或被占满。no nodes available to schedule pods:节点标签、污点与Pod的nodeSelector/tolerations不匹配。failed to allocate device:Device Plugin分配异常,需重启插件Pod。
如果是运行中Pod突然报CUDA错误,先确认节点上是否有人手动占用了GPU:
nvidia-smi
fuser -v /dev/nvidia*
避坑与验证
不要直接重装驱动,先确认是驱动层还是调度层问题,否则可能把正常节点搞挂。
修改内核模块或重启kubelet前,先确认该节点上没有不可中断的训练任务。
恢复后做一次完整验证:
kubectl run gpu-test --image=nvidia/cuda:12.2.0-base-ubuntu22.04 --restart=Never --command -- nvidia-smi
kubectl logs gpu-test
kubectl delete pod gpu-test
能正常输出GPU信息,说明从节点到调度的链路已通。
若仍失败,回到 dmesg 和Device Plugin日志继续缩小范围。
常见疑问
GPU节点重启后GPU数量变成0,通常是Device Plugin还没重新注册。
等待1到2分钟后检查插件Pod日志,多数会自动恢复。
同一节点上多个Pod争抢GPU导致OOM,需要在Pod里限制显存或使用MIG切分,不能只靠K8s的资源声明解决。
驱动版本和CUDA镜像版本不匹配时,Pod可能启动成功但运行时报错,建议节点驱动版本不低于镜像要求的CUDA版本。