gpu-computing

Kubernetes GPU 调度完整详解

·17 分钟阅读·6707 字

Kubernetes GPU 调度完整详解 的详细笔记

📋 目录

Kubernetes GPU 调度完整详解

核心概念 K8s GPU 调度通过 device plugin 暴露 GPU 资源,实现 GPU 节点的调度分配。

1. 基础前置:K8s 原生不支持GPU,整套调度架构总览

1.1. 核心底层原理

Kubernetes 原生仅管理 CPU/memory 基础资源,GPU属于异构硬件扩展资源,整套调度依赖4套扩展机制协同工作:

  1. CRI 容器运行时(nvidia-container-runtime):容器内挂载GPU设备、注入CUDA环境变量
  2. Device Plugin 设备插件(DaemonSet):节点上报GPU数量、分配物理GPU卡号给Pod
  3. Extended Resource 扩展资源nvidia.com/gpu 作为可调度整数资源,调度器筛选节点
  4. 调度增强层(Scheduler Extender / Volcano / DRA):解决分片GPU、多卡绑定、gang批量训练、拓扑亲和、显存细粒度调度

1.2. 完整调度链路(Pod申请GPU全流程)

  1. 集群节点预装NVIDIA显卡驱动、nvidia-container-toolkit,配置containerd/docker使用nvidia runtime
  2. 部署 nvidia-device-plugin(DaemonSet),每个GPU节点常驻
  3. Device Plugin 扫描本机GPU,向kubelet注册扩展资源 nvidia.com/gpu: N,上报节点可用卡数
  4. 用户创建Pod,在 resources.limits 声明 nvidia.com/gpu: 1GPU必须写limits,request默认等于limits
  5. kube-scheduler 过滤所有节点,筛选剩余 nvidia.com/gpu 满足需求的节点,完成节点绑定
  6. 目标节点kubelet 触发DevicePlugin Allocate() 接口,分配物理GPU卡号(0/1/2…)
  7. DevicePlugin 返回CDI设备配置,kubelet通过CRI将指定GPU设备、驱动库、环境变量注入容器
  8. Pod内进程仅能看见分配到的GPU卡号,无法访问本机其他显卡
  9. 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. 核心职责

  1. 资源注册:扫描GPU,向kubelet上报可用 nvidia.com/gpu 数量;MIG/分时切片模式会上报多份虚拟GPU资源
  2. 设备分配 Allocate:接收kubelet请求,分配空闲GPU ID,返回CDI配置
  3. 健康巡检:定时检测GPU故障,故障卡从可调度资源中剔除
  4. 生命周期回收: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. 仅支持整张卡整数申请:只能写1/2/4,无法申请0.5张、20GB显存
  2. 无显存/算力隔离:多Pod共享同一张整卡时,互相抢占显存、算力,一个OOM全容器崩溃
  3. 无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核心能力:

  1. Gang调度(全有或全无):训练任务申请8卡,节点资源不足时不启动部分Pod,避免资源碎片
  2. 装箱Bin-packing:优先填满已有占用GPU节点,减少碎片,提升显卡利用率
  3. 任务队列、优先级、抢占、多机分布式训练调度
  4. 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. 优势

  1. 硬件强隔离:一个实例OOM、崩溃,不影响同卡其他Pod
  2. 性能稳定,无软件劫持开销

3.1.4. 短板

  1. 仅高端数据中心卡支持,消费级3090/4090不支持
  2. 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. 优势

  1. 所有NVIDIA显卡通用,无需硬件支持
  2. 部署简单,仅修改device-plugin配置

3.2.3. 致命短板

无显存/故障隔离:所有Pod共享整张卡显存,一个推理服务显存溢出,同卡全部Pod崩溃;仅适合测试、低并发轻量推理。

3.3. 方案3:HAMi 软件vGPU(通用显卡,线上推理业务主流)

3.3.1. 原理

三层协同:MutatingWebhook + Scheduler Extender + DevicePlugin + CUDA劫持库libvgpu.so

  1. Pod声明细粒度资源:nvidia.com/gpumem: 10240(10GB显存)
  2. 调度扩展过滤节点剩余显存,只调度到满足节点
  3. 容器内劫持CUDA调用,硬限制Pod可用显存,超出直接返回OOM,不影响其他容器

3.3.2. 优势

  1. 全系列NVIDIA显卡兼容,无需A100
  2. 弹性自定义显存需求(3G/10G/16G),细粒度资源调度
  3. 软件显存隔离,单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高速互联,多卡训练通信瓶颈。

解决手段:

  1. Volcano调度器:节点打GPU拓扑标签,调度时优先筛选同NVSwitch/NVLink节点,绑定高速互联显卡
  2. DRA新一代调度:原生上报显卡互联拓扑,自动匹配多卡训练需求
  3. 节点自定义标签: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卡,资源永久闲置。优化策略:

  1. Volcano bin-packing装箱算法:优先填充已占用GPU节点,空节点预留给大卡需求任务
  2. vGPU/HAMi细粒度调度:拆分整卡为小显存资源,充分利用剩余显存
  3. 任务优先级抢占:低优先级推理任务释放GPU,供给高优先级训练任务

4.4. 异构GPU调度(混合3090/A100/H100集群)

原生调度无法区分显卡型号,容易把A100高规格卡分配给轻量任务,造成成本浪费。

解决方案:

  1. DevicePlugin自动给节点打标签 nvidia.com/gpu.product=A100-SXM4-80GB
  2. Pod使用 nodeSelector/nodeAffinity 筛选指定显卡型号:

affinity:

  nodeAffinity:

    requiredDuringSchedulingIgnoredDuringExecution:

      nodeSelectorTerms:

      - matchExpressions:

        - key: nvidia.com/gpu.product

          operator: In

          values: ["A100-SXM4-80GB"]

5. 完整生产部署链路(GPU集群落地步骤)

  1. 服务器BIOS开启GPU虚拟化、SR-IOV(MIG场景)
  2. 宿主机安装匹配内核的NVIDIA驱动
  3. 部署nvidia-container-toolkit,修改containerd配置启用nvidia runtime
  4. Helm部署NVIDIA GPU Operator,自动管理device-plugin、DCGM监控、MIG/分时配置
  5. 按需部署调度增强组件:
  • 推理轻量分片:HAMi vGPU
  • 分布式训练、批量任务:Volcano
  1. 配置监控:DCGM Exporter采集GPU温度、显存、利用率,对接Prometheus告警
  2. 业务Pod规范:声明GPU资源、绑定对应显卡节点亲和、配置CPU内存配额

6. 高频生产踩坑与约束

  1. GPU资源只能写limits,request不生效
    K8s扩展资源强制约束,不写limits会直接忽略GPU分配,Pod无法识别显卡。
  2. 容器CUDA_VISIBLE_DEVICES由device-plugin自动注入,手动覆盖会导致设备错乱。
  3. 不开启分片时,一张GPU只能被一个Pod占用,资源利用率极低。
  4. MIG切换模式需要重启GPU节点,线上业务滚动切换成本高。
  5. 多卡训练不做拓扑亲和,NVLink缺失会导致训练速度下降50%以上。
  6. 普通分时Time-Slicing无隔离,线上推理业务禁止单独使用,必须搭配HAMi/MIG。
  7. 批量训练任务不用Volcano Gang调度,极易产生GPU资源碎片,大任务长期排队。
  8. 未部署DCGM监控无法识别GPU硬件故障,故障卡持续调度Pod导致任务崩溃。

7. 结合你Agent/深度学习开发的落地价值

  1. 单机多Agent推理服务:使用HAMi vGPU拆分单卡给多个Agent,降低硬件成本
  2. 大模型微调分布式训练:Volcano Gang调度多机多卡,保障训练资源一次性到位
  3. 混合集群异构调度:推理用3090,训练用A100,通过节点亲和自动分流任务
  4. 时序异常/LLM Agent线上服务:MIG硬件分片保障多Agent服务故障隔离,互不影响
  5. 监控联动:DCGM采集GPU指标,搭配psutil、pandas做集群资源利用率报表分析

关联文档

Yanche Blog

记录云原生、Linux、数据库等技术领域的学习心得,以及日常生活的思考与感悟。

© 2026 Yanche Blog. All rights reserved.

Powered by Astro