4. GPU资源管理与调度
在Kubernetes集群中,GPU是一种“扩展资源”,它不像CPU和内存那样由kubelet原生管理,而是通过设备插件(Device Plugin)机制接入。理解GPU调度的关键,是把它拆成一条从“物理卡被识别”到“容器拿到可用算力”的链路:nvidia-device-plugin负责注册与分配,MIG负责物理切分,时间片负责共享复用,拓扑感知与NUMA绑定负责性能一致性,多卡任务分配则决定一次申请多张卡时如何落到同一台机器上。
一、nvidia-device-plugin:GPU进入调度体系的入口
nvidia-device-plugin以DaemonSet形式运行在每个GPU节点上,它通过NVIDIA驱动和NVML发现节点上的GPU,然后向kubelet的Device Plugin Manager注册资源名,例如nvidia.com/gpu。注册成功后,节点可分配资源中会出现该资源数量,Pod只要在resources.limits中声明nvidia.com/gpu: 1,调度器就会把它当作一种不可压缩资源参与调度。
设备插件的工作可以概括为四步:发现设备、注册资源、上报健康状态、响应分配请求。分配时,kubelet把选中的设备ID通过Allocate接口返回给容器运行时,运行时据此把对应的/dev/nvidia*设备节点和驱动库挂载进容器。需要注意,GPU数量必须写在limits里,requests可以省略;如果只写requests不写limits,调度器不会把它当作GPU请求处理。
apiVersion: v1
kind: Pod
metadata:
name: gpu-demo
spec:
containers:
- name: cuda
image: nvcr.io/nvidia/cuda:12.4.0-base
resources:
limits:
nvidia.com/gpu: 1
二、MIG:把一张物理卡切成多份隔离实例
MIG(Multi-Instance GPU)是A100、H100等卡支持的硬件级切分能力。它把一张GPU的SM、显存、L2缓存和内存带宽切成若干独立实例,每个实例拥有自己的计算单元和显存,彼此之间具有故障隔离和性能隔离。MIG适合“多个小任务共享一张卡,但要求互不干扰”的场景,例如推理服务、小规模微调、开发测试环境。
MIG的配置分两步:先在节点上用nvidia-smi mig创建GI(GPU Instance)和CI(Compute Instance),再让device-plugin以MIG模式暴露资源。此时资源名会变成类似nvidia.com/mig-1g.5gb的形式,调度器按实例规格而不是整卡来分配。MIG的代价是切分粒度固定、实例数量有限,且不是所有GPU型号都支持;一旦切分,整卡就不能再作为完整GPU分配给需要全卡的任务。
三、时间片:让多个容器共享同一张卡
当任务对算力需求不高、但数量较多时,可以用时间片(time-slicing)让多个容器共享同一张物理GPU。它的原理是CUDA上下文在时间维度上轮流占用GPU,每个容器看到的是同一张卡,但实际执行是交替的。时间片不提供显存隔离,一个容器显存溢出可能影响同卡其他容器,因此更适合推理、开发、批处理等对隔离要求不高的场景。
配置方式是在device-plugin的ConfigMap中声明共享策略,例如把nvidia.com/gpu的replicas设为4,表示一张卡可被4个Pod共享。此时节点上报的GPU数量会变成物理卡数乘以副本数,调度器按逻辑副本分配。时间片提升的是并发密度,不是单任务性能;如果多个任务同时打满算力,每个任务的实际吞吐会下降。
四、拓扑感知调度与NUMA绑定
多卡训练中,GPU之间的通信带宽差异很大。同一台服务器内,GPU可能通过NVLink、PCIe Switch或PCIe Root Complex连接,跨NUMA节点的GPU通信延迟明显高于同NUMA节点。拓扑感知调度的目标,是让一次申请的多张GPU尽量落在通信代价最低的拓扑域内,同时让GPU与网卡、CPU、内存保持在同一NUMA节点附近。
在Kubernetes中,这通常由拓扑管理器(Topology Manager)配合CPU Manager、Memory Manager和设备插件共同完成。拓扑管理器策略可设为none、best-effort、restricted或single-numa-node。对于延迟敏感的多卡训练,常用single-numa-node,要求Pod的所有资源都来自同一个NUMA节点;如果无法满足,Pod会进入TopologyAffinityError,调度失败而不是降级运行。
五、多卡任务分配:一次申请多张卡时怎么落
多卡任务在Kubernetes中通过nvidia.com/gpu: N声明。调度器只保证这N张卡在同一节点上,不保证它们之间的拓扑关系。要控制拓扑,需要结合节点标签、污点容忍、拓扑管理器策略,或者使用支持拓扑感知的调度器插件(如Volcano、Koordinator)。
一个常见的做法是给节点打上拓扑标签,例如topology.nvidia.com/nvlink-group=0,再通过nodeAffinity把需要NVLink通信的任务约束到同一组。对于NCCL训练任务,还可以通过环境变量NCCL_TOPO_FILE或NCCL_IB_HCA指定通信路径,让NCCL优先使用NVLink和同NUMA网卡。
nvidia-smi topo -m中GPU之间的连接类型是否为NVLink。如果出现跨NUMA的SYS连接,通信带宽会明显下降。六、选型与组合建议
| 场景 | 推荐机制 | 关键约束 |
|---|---|---|
| 小推理、多租户共享 | 时间片 | 无显存隔离,需限制显存 |
| 多任务强隔离 | MIG | 需A100/H100等支持,切分粒度固定 |
| 单卡训练/推理 | 整卡独占 | 资源名nvidia.com/gpu |
| 多卡训练 | 拓扑感知 + NUMA绑定 | single-numa-node策略,NVLink优先 |
实际落地时,建议先明确任务对隔离、显存、通信带宽的要求,再决定用MIG、时间片还是整卡。MIG和时间片可以共存,但同一张卡不能既切MIG又做时间片。拓扑感知和NUMA绑定属于“性能优化项”,开启后可能降低调度成功率,需要在资源利用率和性能之间做权衡。最后,所有GPU资源都应通过limits声明,并配合节点标签、污点和亲和性,避免普通任务误占GPU节点。