Volcano vGPU 调度实战:HAMI-core 与 Dynamic MIG 双模式 GPU 共享方案详解
2026/9/17 14:38:50 网站建设 项目流程

Volcano vGPU 调度实战:HAMI-core 与 Dynamic MIG 双模式 GPU 共享方案详解

【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano

本文以 Volcano 官方用户指南docs/user-guide/how_to_use_volcano_vgpu.md为核心,系统讲解 Volcano vGPU(虚拟 GPU)调度的两种共享模式——HAMI-core 软件切片与 Dynamic MIG 硬件切片的完整落地方案。读完后你将掌握:vGPU 调度环境的安装与校验方法、deviceshare调度插件的全部关键参数、volcano.sh/vgpu-*系列资源与注解的使用方式,以及 PodGroup 设备打散、按 UUID 选卡、GPU 独占等进阶策略在调度器源码中的真实实现机制。

两种 vGPU 共享模式:HAMI-core 与 Dynamic MIG

Volcano 为虚拟 GPU(vGPU)调度提供两种 GPU 共享模式,两者在隔离层级与适用场景上差异明显:

1. HAMI-core(软件级 vGPU)

通过VCUDA(CUDA API 劫持)技术强制限制 GPU 核心与显存用量,实现软件层面的虚拟 GPU 切片。适用于需要细粒度 GPU 共享的环境,兼容所有 GPU 型号。

2. Dynamic MIG(硬件级 GPU 切片)

利用 NVIDIAMIG(Multi-Instance GPU)技术,将物理 GPU 切分为多个隔离实例,提供硬件级的性能保障。适用于性能敏感型负载,要求 GPU 支持 MIG(如 A100、H100)。

GPU 共享模式是节点级配置。Volcano 支持异构集群——即一部分节点使用 HAMI-core,另一部分节点使用 Dynamic MIG。节点模式的声明与 MIG geometry 配置由外部组件volcano-vgpu-device-plugin(Project-HAMi 生态项目)负责,本文聚焦 Volcano 调度器侧的实现。

从源码结构看,调度器通过注册表机制为不同模式装配不同的“共享处理器”:sharing_factory.go 定义了SharingFactory接口(TryAddPod/AddPod/SubPod),各模式通过init()中的RegisterFactory(mode, factory)注册;模式常量(hami-coremigmps)定义在 type.go 中。

安装与部署

通用前提条件

启用 vGPU 调度需满足以下环境前提(以官方文档为准):

  • NVIDIA 驱动 > 440
  • nvidia-docker > 2.0
  • Docker 配置nvidia为默认 runtime
  • Kubernetes >= 1.16
  • Volcano >= 1.9

部署步骤:

  1. 按照 Volcano 安装指南部署 Volcano 各组件;
  2. 部署volcano-vgpu-device-pluginDevice Plugin——该组件的 YAML 同时包含Node GPU 模式MIG geometry的配置项,配置细节见该项目的 config 文档;
  3. 校验节点可分配资源:
kubectl get node {node-name} -o yaml

节点 Allocatable 中应出现如下 vGPU 资源:

volcano.sh/vgpu-memory: "89424" volcano.sh/vgpu-number: "8"

源码佐证:调度器侧 device_info.go 的NewGPUDevices正是依赖这两个信号识别节点——它首先检查节点注解volcano.sh/node-vgpu-register(设备信息注册数据),然后要求volcano.sh/vgpu-numbervolcano.sh/vgpu-coresvolcano.sh/vgpu-memory三类可分配资源均存在且非零,任一缺失则该节点不注册 vGPU 设备。资源名常量集中定义在 config/vgpu.go。

更新调度器配置

编辑volcano-scheduler-configmap,启用deviceshare插件的 vGPU 能力:

kind: ConfigMap apiVersion: v1 metadata: name: volcano-scheduler-configmap namespace: volcano-system data: volcano-scheduler.conf: | actions: "enqueue, allocate, backfill" tiers: - plugins: - name: predicates - name: deviceshare arguments: deviceshare.VGPUEnable: true # 启用 vgpu 插件 deviceshare.SchedulePolicy: binpack # 调度策略:binpack / spread

deviceshare插件支持的全部 arguments 在 deviceshare.go 中定义,整理如下:

参数类型说明
deviceshare.VGPUEnablebool启用 vGPU(HAMi vGPU)调度,本文主题参数
deviceshare.SchedulePolicystring设备级调度策略,binpackspread
deviceshare.ScheduleWeightint设备打分在节点排序中的权重,>0 时生效
deviceshare.GPUExclusiveRules[]labelsGPU 独占规则,见后文“GPU 独占”一节
deviceshare.KnownGeometriesCMNamestringMIG geometry ConfigMap 名,默认volcano-vgpu-device-config
deviceshare.KnownGeometriesCMNamespacestring该 ConfigMap 所在命名空间,默认kube-system
deviceshare.GPUSharingEnable/deviceshare.GPUNumberEnable/deviceshare.NodeLockEnablebool与旧版 GPU 共享、GPU 整卡模式或节点锁相关的开关

源码中的关键校验逻辑(deviceshare.go 的enablePredicate):

  • 若同时启用GPUSharingEnableGPUNumberEnable,调度器直接klog.Fatal——两者互斥;
  • GPUSharingEnable/GPUNumberEnableVGPUEnable同时为 true,调度器同样直接退出:gpushare(旧版整卡共享)与 vgpu 不能混用,升级 vGPU 方案前务必清理旧配置;
  • VGPUEnable为 true 时,注册设备名为hamivgpu的设备(type.go 中DeviceName = "hamivgpu"),MIG geometry 默认从kube-system命名空间的volcano-vgpu-device-configConfigMap 读取(该 ConfigMap 由 volcano-vgpu-device-plugin 生成初始值,可自定义)。

HAMI-core 模式使用

在 Pod 中通过注解显式声明 HAMI-core 模式,并在resources.limits中申请 vGPU 资源:

metadata: name: hami-pod annotations: volcano.sh/vgpu-mode: "hami-core" spec: schedulerName: volcano containers: - name: cuda-container image: nvidia/cuda:9.0-devel resources: limits: volcano.sh/vgpu-number: 1 # 申请 1 张(虚拟)GPU 卡 volcano.sh/vgpu-cores: 50 # (可选)每块 vGPU 使用 50% 算力 volcano.sh/vgpu-memory: 3000 # (可选)每块 vGPU 使用 3GB 显存

vGPU 资源项语义(常量见 config/vgpu.go):

资源名含义说明
volcano.sh/vgpu-number虚拟 GPU 卡数量必选
volcano.sh/vgpu-memory每张 vGPU 的显存上限(MB)可选,不指定时按设备插件配置中的defaultMemory处理
volcano.sh/vgpu-cores每张 vGPU 的算力百分比(0–100)可选
volcano.sh/vgpu-memory-percentage显存百分比形式源码中另支持的百分比写法

分配成功后,调度器会向 Pod 注入一组绑定注解(device_info.go 的Allocate):volcano.sh/vgpu-ids-new(实际分配的设备 UUID 列表)、volcano.sh/vgpu-nodevolcano.sh/vgpu-timevolcano.sh/devices-to-allocatevolcano.sh/bind-phase等。这些注解随 Binding 请求由 apiserver 与节点分配原子合并,供设备插件在 bind 阶段完成容器级注入;回滚路径(UnAllocate)时Release会清理这些注解,但若bind-phase已为success则交给设备插件接管,调度器不再重复清理。

Dynamic MIG 模式使用

启用 MIG

在 GPU 节点上执行:

sudo nvidia-smi -mig 1

Geometry 配置(可选)

volcano-vgpu-device-plugin会自动生成初始 MIG 配置,写入kube-system命名空间的volcano-vgpu-device-configConfigMap,可按需修改。该 ConfigMap 中的数据结构在调度器侧对应 config/vgpu.go:AllowedMigGeometries(按 GPU 型号列出allowedGeometries)、Geometry(一个分组内的geometries实例列表)、MigTemplate(如1g.10gb及其显存与数量)。

Pod 示例

metadata: name: mig-pod annotations: volcano.sh/vgpu-mode: "mig" spec: schedulerName: volcano containers: - name: cuda-container image: nvidia/cuda:9.0-devel resources: limits: volcano.sh/vgpu-number: 1 volcano.sh/vgpu-memory: 3000

注意:实际分配的显存取决于 best-fit 命中的 MIG 切片规格(例如申请 3GB 可能命中 5GB 的切片)。

源码佐证:MIG 模式由 mig.go 中的MIGFactory实现。TryAddPod先按GPUMemoryFactor放大请求显存(默认 1 时不放大),再调用findMatch在该卡的MigTemplate/MigUsage中做 best-fit 匹配;命中后按切片实际显存更新UsedNum/UsedMem。这与文档“3GB 请求 → 5GB 切片”的行为完全对应。

进阶调度策略

PodGroup 设备打散(Spread)

为防止同一 PodGroup 内的两个 Pod 挤在同一块 vGPU 上,可为 Pod 添加注解volcano.sh/vgpu-podgroup-policy: spread;未加注解的 Pod 仍走默认 binpack 行为。

metadata: name: spread-pod annotations: volcano.sh/vgpu-podgroup-policy: "spread"

注解常量定义在 type.go,判断逻辑在 utils.go:当注解值等于spread时启用组内打散;集成测试见 spread_integration_test.go。

按 UUID 选择物理 GPU

  • volcano.sh/vgpu-use-gpuuuid:物理 GPU UUID 的白名单,逗号分隔;
  • volcano.sh/vgpu-nouse-gpuuuid黑名单
metadata: annotations: volcano.sh/vgpu-use-gpuuuid: "GPU-03f69c50-207a-2038-9b45-23cac89cb67d"
metadata: annotations: volcano.sh/vgpu-nouse-gpuuuid: "GPU-03f69c50-207a-2038-9b45-23cac89cb67d"

匹配语义(utils.go 的parseGPUUUIDList):UUID 去除首尾空白后精确匹配;若白名单中没有任何设备能满足请求,Pod 将保持不可调度;同一 UUID 同时出现在两个注解中时,黑名单优先。边界行为(空串、连续逗号、非法 UUID 报错等)由 utils_test.go 的单测覆盖。

GPU 独占(仅 HAMI-core 节点)

GPU 独占保证:匹配配置标签规则的 Pod 获得独占的物理 GPU——其他匹配规则的 Pod 不能与其共享同一块卡;不匹配规则的 Pod 仍可正常共享 GPU。该特性仅作用于 hami-core 节点:Dynamic MIG 节点本身已有硬件隔离,源码会直接跳过(gpuexclusive.go 中仅当Mode为空或hami-core时才包装)。

它与spread调度策略正交,可以叠加使用:spread跨节点的负载均衡(把 Pod 分散到不同节点),而 GPU 独占是单节点内 GPU 设备粒度的互斥。若某节点所有 GPU 均被其他规则匹配 Pod 预留,该 Pod 会在此节点FilterNode 失败并保持 Pending,直到出现有空闲独占 GPU 的节点。

配置方式——在 deviceshare 插件参数中加入deviceshare.GPUExclusiveRules

- name: deviceshare arguments: deviceshare.VGPUEnable: true deviceshare.GPUExclusiveRules: - workloadType: training - workloadType: batch priority: high

每条规则是一组 label 键值对,Pod 必须同时匹配规则内全部标签才获得独占权;独占性只在同一条规则内部强制——匹配不同规则的 Pod 之间仍可共享 GPU。

Pod 示例:

metadata: name: training-job labels: workloadType: training spec: schedulerName: volcano containers: - name: trainer image: nvidia/cuda:12.0-base resources: limits: volcano.sh/vgpu-number: "4" volcano.sh/vgpu-memory: "16384"

源码机制(gpuexclusive.go):

  • loadGPUExclusiveConfig+parseExclusiveRules将 YAML 规则解析为exclusiveRule{labels}切片;matchingRules按“全标签匹配”返回命中的规则下标;
  • 每个调度会话开始时,wrapGPUDevicesForExclusivity把各节点的*vgpu.GPUDevices包装为exclusiveGPUDevices,并从三个来源重建“规则 → 已占 GPU”映射:设备 PodMap、Pod 的分配注解、上一调度周期的持久化状态(persistedGPUs/persistedPodRules跨会话保存,保证独占状态不因调度轮次结束丢失);
  • 核心手法是capGPUs:临时将被规则预留的 GPU 的Number置为UsedNum(即“剩余虚拟卡数为 0”),使底层 vGPU 分配器自然跳过这些卡,调用结束后再由restoreGPUs还原——FilterNodeAllocate两个阶段均采用该机制,从而在不改动底层分配器的前提下实现设备级互斥。

调度器模式选择与调用链

显式模式与自动模式

  • 显式模式:通过注解volcano.sh/vgpu-mode(取值hami-core/mig)强制指定模式;
  • 自动模式:注解缺省时,调度器基于资源适配度与策略自动选择模式;
  • 调度策略binpack倾向“剩余显存越少越好”(聚合碎片),spread倾向“空闲卡优先于共享卡”,两者均影响节点/设备打分(策略常量与语义见 type.go)。

调度器侧调用链

从 deviceshare.go 的OnSessionOpen可以还原完整调用链:

  1. wrapGPUDevicesForExclusivity:若配置了独占规则,先对节点设备做独占包装(必须早于后续注册,保证整轮调度使用包装后的设备);
  2. 注册PredicateFn:对每个请求了 vGPU 的 Task 调用dev.FilterNode(task.Pod, schedulePolicy)(内部即 device_info.go 的checkNodeGPUSharingPredicateAndScore),不满足设备容量/模式/UUID 约束的节点直接淘汰;
  3. 注册NodeOrderFn:当deviceshare.ScheduleWeight > 0时,用 Filter 阶段缓存的设备打分(ScoreNode直接返回缓存值以避免重复计算)参与节点排序;
  4. Allocate阶段再次执行设备校验并写分配注解,随 Binding 下发。

模式对比与监控

模式对比总表

模式隔离级别是否要求 MIG GPU是否需要注解核心/显存控制推荐场景
HAMI-core软件(VCUDA)否(可选)通用负载
Dynamic MIG硬件由 MIG 切片决定性能敏感型作业

监控

  • 调度器指标:
curl http://<volcano-scheduler-ip>:8080/metrics
  • 设备插件指标:
curl http://<plugin-pod-ip>:9394/metrics

指标涵盖 GPU 利用率、Pod 显存用量与上限等;调度器侧的指标埋点在 metrics.go 中,随AddPod/SubPod逐卡更新。

延伸阅读

  • 插件实现入口:deviceshare.go、GPU 独占:gpuexclusive.go
  • vGPU 设备模型:device_info.go、资源与注解常量:type.go、MIG 分配逻辑:mig.go
  • MIG geometry 配置结构:config/vgpu.go
  • 相关测试:deviceshare_test.go、gpuexclusive_test.go、spread_integration_test.go、mig_test.go
  • 设备插件侧(节点模式与 MIG geometry 配置)请参考volcano-vgpu-device-plugin项目的安装与配置文档

【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询