K8s集群GPU算力池化:从零搭建共享调度环境
把多台服务器上的GPU卡统一放进K8s集群调度,核心是让Kubernetes知道节点上有多少张GPU、每张卡能否被容器安全共享。
实现路径通常是:安装驱动和容器运行时、部署NVIDIA设备插件、在Pod里声明GPU资源、最后验证调度结果。
下面按这个顺序展开。
哪些场景需要GPU算力池化
如果你遇到下面几种情况,就适合用K8s做GPU池化:
- 多张GPU卡分散在不同机器上,手动分配效率低,经常出现一张卡跑满、其他卡空闲。
- 训练任务和推理任务混跑,需要按优先级或队列分配算力。
- 多人共用几台GPU服务器,希望用命名空间和资源配额隔离使用量。
有一点要额外留意,池化不等于把多张卡的显存合并成一块。
默认调度下,一个Pod占用整张GPU卡;
如果需要显存切分或多Pod共享单卡,要额外引入MIG、时间片或第三方方案。
动手前的环境确认
池化的前提是每台GPU节点的底层环境一致。
建议先逐台检查:
- 操作系统版本和内核版本尽量统一,避免驱动编译差异。
- 已安装与GPU型号匹配的NVIDIA驱动,执行
nvidia-smi能看到显卡列表。 - 已安装
nvidia-container-toolkit,并配置给容器运行时(containerd或Docker)。 - K8s集群节点处于Ready状态,
kubectl get nodes可正常返回。
检查驱动是否就绪:
nvidia-smi
如果这条命令报错,先解决驱动问题,不要继续往下走。
配置容器运行时识别GPU
以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"
改完后重启containerd:
systemctl restart containerd
这一步的作用是让容器启动时能挂载GPU设备文件。
如果跳过,后面设备插件会报找不到设备。
部署NVIDIA设备插件
设备插件负责把节点上的GPU数量上报给K8s。
用官方DaemonSet部署:
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/main/deployments/static/nvidia-device-plugin.yml
部署后检查Pod是否运行:
kubectl get pods -n kube-system | grep nvidia
预期每个GPU节点上有一个Running的插件Pod。
然后查看节点可分配资源:
kubectl describe node <节点名> | grep nvidia.com/gpu
如果输出类似 nvidia.com/gpu: 4,说明该节点已上报4张GPU。
没有这一行,说明插件没识别到设备,需要回看驱动和运行时配置。
在Pod中申请GPU资源
资源上报成功后,在容器里声明GPU数量即可:
apiVersion: v1
kind: Pod
metadata:
name: gpu-test
spec:
containers:
- name: cuda
image: nvidia/cuda:12.2.0-base-ubuntu22.04
command: ["nvidia-smi"]
resources:
limits:
nvidia.com/gpu: 1
应用并查看日志:
kubectl apply -f gpu-test.yaml
kubectl logs gpu-test
日志里能打印出GPU信息,就说明池化调度链路已经通了。
容易踩的几个坑
- 只写了
requests没写limits:GPU资源必须放在limits里,否则调度不会生效。 - 节点驱动版本不一致:设备插件在不同节点上报的数量可能对不上,建议统一驱动版本。
- 忘记给容器运行时打标签:如果集群有多个RuntimeClass,Pod要指定
runtimeClassName: nvidia。 - 误以为一张卡能跑多个Pod:默认情况下整卡独占,多Pod共享需要额外配置MIG或时间片方案。
如何验证池化是否真正生效
除了看日志,还可以做两个检查:
- 连续提交两个各申请1张GPU的Pod,观察是否被调度到不同节点或不同卡上。
- 用
kubectl describe pod查看Events,确认没有Insufficient nvidia.com/gpu报错。
如果两个Pod都Pending,先确认节点上报的GPU数量是否大于0,再检查是否有其他Pod占满了卡。
常见疑问
Q:没有GPU的节点会不会被调度到?
不会。没有 nvidia.com/gpu 资源的节点在调度时会被自动过滤,除非你手动指定了节点亲和性。
Q:GPU算力池化后能按显存切分吗?
默认不能。K8s原生只支持整卡分配,显存切分需要MIG(部分卡支持)或第三方共享方案,配置复杂度会明显上升。
Q:设备插件Pod一直CrashLoopBackOff怎么办?
先看 kubectl logs 报错内容。常见原因是驱动未安装、容器运行时没配nvidia-runtime,或节点上存在旧版插件冲突。
Q:集群里同时有不同型号的GPU卡,能混用吗?
可以上报,但调度时K8s不区分型号。如果你的任务对卡型号有要求,需要用节点标签加亲和性来限制。
池化的本质是把GPU从“单机手工作业”变成“集群统一调度”。
只要驱动、运行时、设备插件三层都对齐,后续扩节点或加卡只需要重复同样的配置流程即可。