K8s集群GPU算力Deployment运维:从驱动准备到调度验证
在Kubernetes集群里跑GPU任务,不是装好驱动就能直接调度。
你需要让节点上的GPU被kubelet识别为可分配资源,再通过Deployment声明nvidia.com/gpu,Pod才能落到有GPU的节点上。
下面按顺序说明从环境检查到运行验证的完整操作。
先确认节点和驱动是否就绪
登录每台准备提供GPU算力的节点,检查显卡是否被系统识别:
nvidia-smi
预期能看到驱动版本、CUDA版本和GPU列表。
如果命令不存在或报错,先安装与显卡型号匹配的NVIDIA驱动,装完重启节点。
接着确认容器运行时。
Kubernetes从1.24起默认使用containerd,需要把containerd配置为使用NVIDIA容器运行时。
检查/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"
改完执行systemctl restart containerd,并确认nvidia-container-runtime已安装。
部署NVIDIA Device Plugin
Device Plugin负责把节点上的GPU数量上报给kubelet。
官方推荐用DaemonSet方式部署:
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/main/deployments/static/nvidia-device-plugin.yml
如果集群无法访问外网,先下载该YAML文件,检查镜像地址是否可拉取,再通过内网仓库替换后apply。
部署完成后查看Pod状态:
kubectl get pods -n kube-system | grep nvidia
预期每个GPU节点上有一个Running状态的Pod。
随后确认节点资源已上报:
kubectl describe node <节点名> | grep nvidia.com/gpu
如果输出nvidia.com/gpu: 2这类数字,说明GPU已被正确识别。
若显示为0或没有该字段,优先检查Device Plugin的日志:
kubectl logs -n kube-system
常见原因是容器运行时未配置nvidia runtime,或驱动版本与容器内CUDA版本不兼容。
用Deployment申请GPU资源
下面是一个最小可用的Deployment示例,申请1块GPU:
apiVersion: apps/v1
kind: Deployment
metadata:
name: gpu-demo
spec:
replicas: 1
selector:
matchLabels:
app: gpu-demo
template:
metadata:
labels:
app: gpu-demo
spec:
containers:
- name: cuda
image: nvcr.io/nvidia/cuda:12.2.0-base-ubuntu22.04
command: ["nvidia-smi"]
resources:
limits:
nvidia.com/gpu: 1
保存为gpu-demo.yaml后执行:
kubectl apply -f gpu-demo.yaml
kubectl get pods -l app=gpu-demo
Pod进入Running后查看日志:
kubectl logs -l app=gpu-demo
能输出nvidia-smi信息就说明容器内已挂载GPU。
注意:GPU资源只能写在limits里,不能只写requests。 如果只写requests不写limits,调度器不会把GPU作为可分配资源处理。
另外,GPU是不可压缩资源,多个Pod不能共享同一块卡,除非使用MIG或时间片方案。
调度不成功时的排查顺序
Pod一直Pending,先看事件:
kubectl describe pod
常见事件和对应处理:
Insufficient nvidia.com/gpu:节点GPU已被其他Pod占用,或Device Plugin未上报资源,检查kubectl describe node中的可分配数量。0/3 nodes are available:节点没有打上GPU标签,或没有配置nodeSelector。可以给GPU节点打标签:
kubectl label nodes <节点名> gpu=true
然后在Deployment中加入:
nodeSelector:
gpu: "true"
- 镜像拉取失败:确认节点能访问镜像仓库,或提前把镜像导入本地。
- Pod启动后立即退出:查看日志,常见是CUDA版本与驱动不匹配,或容器内没有正确挂载设备。
验证与日常维护要点
部署完成后,建议做三件事:
- 用
kubectl get pods -o wide确认Pod落在预期的GPU节点上。 - 进入容器执行
nvidia-smi,确认看到的GPU编号和宿主机一致。 - 记录节点GPU总数和已分配数量,避免多个Deployment争抢同一张卡。
日常运维中,驱动升级、containerd重启、Device Plugin更新都可能影响GPU上报。
升级前先在单节点验证,确认nvidia-smi和kubectl describe node都正常后,再滚动到其他节点。
如果集群规模较大,建议给GPU节点单独打标签和污点,避免普通工作负载占用GPU节点的CPU和内存资源。
常见疑问
GPU节点上还能跑普通Pod吗?
可以。只要普通Pod不申请nvidia.com/gpu,调度器会按CPU和内存正常调度。但GPU节点通常配置较高,建议用污点限制普通负载,把资源留给算力任务。
一个Pod能申请多块GPU吗?
可以,把nvidia.com/gpu的值改成2或更多即可,前提是单节点上有足够数量的空闲GPU。
Device Plugin必须用DaemonSet部署吗?
官方提供的部署方式就是DaemonSet,它确保每个GPU节点上都运行一个插件实例。手动部署到单个节点也可以,但节点扩容后需要重复操作。
没有GPU的节点会受影响吗?
不会。Device Plugin的DaemonSet只会调度到有对应标签或污点容忍的节点上,普通节点不会运行该插件。