Kubernetes GPU 调度完整详解
核心概念 K8s GPU 调度通过 device plugin 暴露 GPU 资源,实现 GPU 节点的调度分配。
1. 基础前置:K8s 原生不支持GPU,整套调度架构总览
1.1. 核心底层原理
Kubernetes 原生仅管理 CPU/memory 基础资源,GPU属于异构硬件扩展资源,整套调度依赖4套扩展机制协同工作:
- CRI 容器运行时(nvidia-container-runtime):容器内挂载GPU设备、注入CUDA环境变量
- Device Plugin 设备插件(DaemonSet):节点上报GPU数量、分配物理GPU卡号给Pod
- Extended Resource 扩展资源:
nvidia.com/gpu作为可调度整数资源,调度器筛选节点 - 调度增强层(Scheduler Extender / Volcano / DRA):解决分片GPU、多卡绑定、gang批量训练、拓扑亲和、显存细粒度调度
1.2. 完整调度链路(Pod申请GPU全流程)
- 集群节点预装NVIDIA显卡驱动、
nvidia-container-toolkit,配置containerd/docker使用nvidia runtime - 部署
nvidia-device-plugin(DaemonSet),每个GPU节点常驻 - Device Plugin 扫描本机GPU,向kubelet注册扩展资源
nvidia.com/gpu: N,上报节点可用卡数 - 用户创建Pod,在
resources.limits声明nvidia.com/gpu: 1(GPU必须写limits,request默认等于limits) - kube-scheduler 过滤所有节点,筛选剩余
nvidia.com/gpu满足需求的节点,完成节点绑定 - 目标节点kubelet 触发DevicePlugin
Allocate()接口,分配物理GPU卡号(0/1/2…) - DevicePlugin 返回CDI设备配置,kubelet通过CRI将指定GPU设备、驱动库、环境变量注入容器
- Pod内进程仅能看见分配到的GPU卡号,无法访问本机其他显卡
- Pod销毁时,DevicePlugin回收GPU,资源计数恢复,供新Pod调度
1.3. 基础Pod GPU申请标准yaml
apiVersion: v1
kind: Pod
metadata:
name: torch-gpu-pod
spec:
containers:
- name: pytorch
image: pytorch/pytorch:2.4-cuda12.4
command: ["python","-c","import torch; print(torch.cuda.device_count())"]
resources:
limits:
# 核心:申请1张整卡,仅limits生效,request自动对齐
nvidia.com/gpu: 1
# 配套CPU内存约束,防止抢占GPU算力
cpu: "4"
memory: 8Gi
2. 四大核心组件深度拆解
2.1. nvidia-container-runtime(CRI层,容器GPU可见基础)
普通容器无法识别宿主机GPU,该工具链负责:
- 宿主机驱动文件、显卡设备
/dev/nvidia*绑定挂载进容器 - 自动注入环境变量
CUDA_VISIBLE_DEVICES,限制容器仅能使用分配的卡号 - 隔离CUDA运行时,不同Pod驱动版本互不冲突 关键:无该runtime,哪怕分配GPU卡号,容器也识别不到显卡。
2.2. Device Plugin 设备插件(调度核心,NVIDIA GPU Operator统一托管)
2.2.1. 核心职责
- 资源注册:扫描GPU,向kubelet上报可用
nvidia.com/gpu数量;MIG/分时切片模式会上报多份虚拟GPU资源 - 设备分配 Allocate:接收kubelet请求,分配空闲GPU ID,返回CDI配置
- 健康巡检:定时检测GPU故障,故障卡从可调度资源中剔除
- 生命周期回收:Pod删除后释放GPU资源
2.2.2. NVIDIA GPU Operator(生产标准部署方案)
手动部署驱动、runtime、devicePlugin、监控组件极其繁琐,GPU Operator通过CRD一键全托管:
- 自动编译/安装宿主机NVIDIA驱动
- 配置containerd/dockerd nvidia runtime
- 部署device-plugin、DCGM监控、MIG管理组件、分时切片配置
- 统一版本管控、滚动升级、异构节点差异化配置
2.3. Extended Resource 扩展资源(原生调度过滤逻辑)
K8s调度器底层把 nvidia.com/gpu 当作整数离散资源处理,存在3个原生硬限制:
- 仅支持整张卡整数申请:只能写1/2/4,无法申请0.5张、20GB显存
- 无显存/算力隔离:多Pod共享同一张整卡时,互相抢占显存、算力,一个OOM全容器崩溃
- 无GPU拓扑感知:申请多卡时,无法保证分配NVLink高速互联显卡,训练多卡通信性能暴跌
2.4. 调度增强组件(弥补原生调度短板,生产AI集群必备)
分三类方案,覆盖分片、批量训练、拓扑调度:
2.4.1. (1)Scheduler Extender 调度扩展(HAMi/vCUDA,细粒度显存调度)
拦截kube-scheduler调度请求,新增过滤/绑定逻辑:
- 自定义资源:
nvidia.com/gpumem(MB显存)、nvidia.com/gpucores(算力百分比) - 调度时校验节点剩余显存,仅把Pod调度到显存充足节点
- CUDA API劫持实现软件vGPU,容器显存硬隔离,超分配直接OOM,无整卡崩溃风险
代表项目:HAMi(CNCF沙箱,主流私有AI集群vGPU方案)
2.4.2. (2)Volcano 批量调度器(大模型训练、多机多卡gang调度首选)
原生调度器只支持单Pod调度,深度学习训练Job需要同时申请N张GPU,全部到位才启动(gang调度),Volcano核心能力:
- Gang调度(全有或全无):训练任务申请8卡,节点资源不足时不启动部分Pod,避免资源碎片
- 装箱Bin-packing:优先填满已有占用GPU节点,减少碎片,提升显卡利用率
- 任务队列、优先级、抢占、多机分布式训练调度
- GPU拓扑亲和调度,优先分配NVLink互联显卡
2.4.3. (3)DRA(Dynamic Resource Allocation,K8s 1.34+新一代设备调度标准)
下一代替代Device Plugin的官方标准,彻底解决原生GPU调度缺陷:
- 不再把GPU当作纯整数计数,完整上报显卡元数据:显存、算力、NVLink拓扑、MIG配置
- 原生支持单卡多Pod共享、拓扑亲和、多卡绑定、异构显卡筛选
- 资源声明支持连续显存需求,无需自定义扩展资源
3. 四种GPU共享/分片调度方案(利用率优化核心,优缺点对比)
默认模式是一Pod独占一整卡,轻量推理、Agent小模型会造成90%显存闲置,四类分片方案适配不同场景:
3.1. 方案1:NVIDIA MIG 硬件分片(A100/H100/A30专用,生产强隔离首选)
3.1.1. 原理
硬件级切分单张GPU为多个独立MIG实例,每个实例拥有独立显存、算力、硬件故障隔离,互不干扰。
A100 40G最大切8×5G MIG实例;A100 80G切7个实例。
3.1.2. 调度逻辑
device-plugin扫描MIG实例,对外暴露独立可调度资源 nvidia.com/mig-1g.5gb,Pod精准申请对应规格MIG实例:
resources:
limits:
nvidia.com/mig-1g.5gb: 1
3.1.3. 优势
- 硬件强隔离:一个实例OOM、崩溃,不影响同卡其他Pod
- 性能稳定,无软件劫持开销
3.1.4. 短板
- 仅高端数据中心卡支持,消费级3090/4090不支持
- MIG分片规格固定,无法自定义12GB、18GB等弹性显存
3.2. 方案2:GPU Time-Slicing 官方分时切片(任意NVIDIA显卡,开发测试环境)
3.2.1. 原理
GPU Operator配置device-plugin将单卡虚拟为N份分时副本,多Pod共享同一张物理GPU,CUDA上下文快速切换轮转算力。
配置示例(单卡虚拟4份):
sharing:
timeSlicing:
resources:
- name: nvidia.com/gpu
replicas: 4
Pod仍声明 nvidia.com/gpu:1,调度器允许4个Pod调度到同一张卡。
3.2.2. 优势
- 所有NVIDIA显卡通用,无需硬件支持
- 部署简单,仅修改device-plugin配置
3.2.3. 致命短板
无显存/故障隔离:所有Pod共享整张卡显存,一个推理服务显存溢出,同卡全部Pod崩溃;仅适合测试、低并发轻量推理。
3.3. 方案3:HAMi 软件vGPU(通用显卡,线上推理业务主流)
3.3.1. 原理
三层协同:MutatingWebhook + Scheduler Extender + DevicePlugin + CUDA劫持库libvgpu.so
- Pod声明细粒度资源:
nvidia.com/gpumem: 10240(10GB显存) - 调度扩展过滤节点剩余显存,只调度到满足节点
- 容器内劫持CUDA调用,硬限制Pod可用显存,超出直接返回OOM,不影响其他容器
3.3.2. 优势
- 全系列NVIDIA显卡兼容,无需A100
- 弹性自定义显存需求(3G/10G/16G),细粒度资源调度
- 软件显存隔离,单Pod OOM不崩溃整卡
3.3.3. 短板
存在少量CUDA调用劫持性能损耗(5%以内)
3.4. 方案4:CUDA MPS 多进程服务(单Pod内多模型,不跨Pod共享)
仅允许同一个Pod内部多个进程共享GPU,无法实现多个Pod共享同卡,多用于单容器多推理模型场景,不用于集群调度。
3.5. 四种分片方案选型对照表
| | | | | |
|---|---|---|---|---|
|方案|隔离等级|支持显卡|自定义显存|生产适用场景|
|MIG硬件分片|硬件强隔离|A100/H100|固定规格|线上稳定推理、大模型微调|
|Time-Slicing分时|无隔离|全NVIDIA|不可自定义|开发测试、低负载演示|
|HAMi软件vGPU|软件显存隔离|全NVIDIA|任意MB|线上轻量推理、Agent服务集群|
|CUDA MPS|Pod内共享|全NVIDIA|无跨Pod共享|单容器多模型推理|
4. 高阶调度能力(大模型训练/分布式Agent必备)
4.1. 多卡绑定 & NVLink拓扑亲和
原生kube-scheduler缺陷:申请nvidia.com/gpu:4仅随机分配4张卡,不保证NVLink高速互联,多卡训练通信瓶颈。
解决手段:
- Volcano调度器:节点打GPU拓扑标签,调度时优先筛选同NVSwitch/NVLink节点,绑定高速互联显卡
- DRA新一代调度:原生上报显卡互联拓扑,自动匹配多卡训练需求
- 节点自定义标签:
gpu-topology=nvlink4,Pod节点亲和筛选对应节点
4.2. Gang 批量调度(分布式训练刚需)
大模型训练、多机分布式Agent训练需要一次性占用多张GPU,原生调度会出现“碎片资源卡死任务”:
集群剩余3张、3张空闲,任务需要4卡,原生会拆分占用导致永远无法凑齐。
Volcano Gang调度规则:
- 任务声明总GPU数量,必须节点池凑齐全部资源才创建Pod组
- 资源不足时任务进入队列等待,不抢占碎片化资源
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
spec:
minAvailable: 8 # 必须8个Pod全部调度成功才启动
tasks:
- replicas: 8
template:
spec:
containers:
- resources:
limits:
nvidia.com/gpu: 1
4.3. GPU 资源碎片优化
AI集群常见浪费:节点剩余1张卡,新任务需要2卡,资源永久闲置。优化策略:
- Volcano bin-packing装箱算法:优先填充已占用GPU节点,空节点预留给大卡需求任务
- vGPU/HAMi细粒度调度:拆分整卡为小显存资源,充分利用剩余显存
- 任务优先级抢占:低优先级推理任务释放GPU,供给高优先级训练任务
4.4. 异构GPU调度(混合3090/A100/H100集群)
原生调度无法区分显卡型号,容易把A100高规格卡分配给轻量任务,造成成本浪费。
解决方案:
- DevicePlugin自动给节点打标签
nvidia.com/gpu.product=A100-SXM4-80GB - Pod使用
nodeSelector/nodeAffinity筛选指定显卡型号:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nvidia.com/gpu.product
operator: In
values: ["A100-SXM4-80GB"]
5. 完整生产部署链路(GPU集群落地步骤)
- 服务器BIOS开启GPU虚拟化、SR-IOV(MIG场景)
- 宿主机安装匹配内核的NVIDIA驱动
- 部署nvidia-container-toolkit,修改containerd配置启用nvidia runtime
- Helm部署NVIDIA GPU Operator,自动管理device-plugin、DCGM监控、MIG/分时配置
- 按需部署调度增强组件:
- 推理轻量分片:HAMi vGPU
- 分布式训练、批量任务:Volcano
- 配置监控:DCGM Exporter采集GPU温度、显存、利用率,对接Prometheus告警
- 业务Pod规范:声明GPU资源、绑定对应显卡节点亲和、配置CPU内存配额
6. 高频生产踩坑与约束
- GPU资源只能写limits,request不生效
K8s扩展资源强制约束,不写limits会直接忽略GPU分配,Pod无法识别显卡。 - 容器CUDA_VISIBLE_DEVICES由device-plugin自动注入,手动覆盖会导致设备错乱。
- 不开启分片时,一张GPU只能被一个Pod占用,资源利用率极低。
- MIG切换模式需要重启GPU节点,线上业务滚动切换成本高。
- 多卡训练不做拓扑亲和,NVLink缺失会导致训练速度下降50%以上。
- 普通分时Time-Slicing无隔离,线上推理业务禁止单独使用,必须搭配HAMi/MIG。
- 批量训练任务不用Volcano Gang调度,极易产生GPU资源碎片,大任务长期排队。
- 未部署DCGM监控无法识别GPU硬件故障,故障卡持续调度Pod导致任务崩溃。
7. 结合你Agent/深度学习开发的落地价值
- 单机多Agent推理服务:使用HAMi vGPU拆分单卡给多个Agent,降低硬件成本
- 大模型微调分布式训练:Volcano Gang调度多机多卡,保障训练资源一次性到位
- 混合集群异构调度:推理用3090,训练用A100,通过节点亲和自动分流任务
- 时序异常/LLM Agent线上服务:MIG硬件分片保障多Agent服务故障隔离,互不影响
- 监控联动:DCGM采集GPU指标,搭配psutil、pandas做集群资源利用率报表分析
关联文档