前言:

       为什么要部署volcano?因为kubernetes默认的scheduler支持调度的方式有限,默认只支持以CPU/内存资源、节点标签选择、节点亲和/反亲和、污点与容忍、Pod 优先,而无法做到批量调度方面以及Pod组调度,VGPU/MIG形式的精细化调度。

       Volcano是什么?volcano主要用于高性能计算场景。它提供了Kubernetes目前缺 少的一套机制,这些机制通常是机器学习大数据应用、科学计算、特效渲染等多种高性能工作负载所需的。作为一个通用批处理平台,Volcano与几乎所有的主流计算框 架无缝对接,如SparkTensorFlowPyTorchFlinkArgoMindSporePaddlePaddleRay等。它还提供了包括异构设备调度,网络拓扑感知调度,多集群调度,在离线混部调度等多种调度能力。

       总结就是Volcano具备了在Ai领域所有调度方式的一个插件,来提升集群整体的资源利用率。并为各种 AI/ML 工作负载提供了更大的灵活性。

快速入门

我司现在集群160张卡,没有做虚拟化导致多数服务在申请的时候以整张卡为单位,导致158张卡被申请了158张,但实际158张的利用率不到20%,所以对现有集群进行改造,通过Volcano-vgpu-device-plugin的形式对集群加速卡进行虚拟化。

虚拟化的方式,可以分为三类方式:

  1. 时间分片(Time Slicing)

  2. 空间切分(MIG、SR-IOV 等)

  3. 混合增强技术(MPS、HAMI、动态 MIG)

比较:时间分片和多实例 GPU和HAMI-core(基于软件的vGPU)

MIG 硬件级切分,提供真正的内存和故障隔离,每个MIG实例像一个"小GPU",独立的显存,计算核心,错误隔离。但限定卡的类型

分时分片技术通过调度在时间维度上轮流分配GPU,牺牲隔离性,换取更高的GPU共享利用率,可应用于老一代GPU()

HAMI-core利用VCUDA(一种 CUDA API 劫持技术)来强制执行 GPU 核心和内存使用限制。可以对计算核心比例和显存上限做限制,实现软件级虚拟 GPU 切片。适用于需要细粒度 GPU共享的环境。且兼容所有 GPU 类型。

模式 隔离 需要 MIG GPU 注解 核心/内存控制 推荐用途
HAMI核心 软件(VCUDA) 是的 一般工作负荷
动态 MIG 硬件 是的 是的 MIG控制 对绩效敏感的工作

一、Volcano vGPU技术架构

Volcano提供了两种不同层级的GPU虚拟化方案,满足不同场景下的需求:

  1. HAMI-core模式(软件虚拟化) 技术原理: 基于VCUDA技术实现,通过拦截CUDA API调用实现资源限制。这种方案在驱动层对GPU计算核心和显存进行虚拟划分,无需硬件支持。

核心特点:

兼容所有NVIDIA GPU型号 支持显存和计算核心的百分比分配 资源隔离依赖软件调度 典型场景:

开发测试环境 对GPU利用率要求不高的常规训练任务 需要同时运行多个轻量级AI服务的场景

  1. Dynamic MIG模式(硬件虚拟化) 技术原理: 利用NVIDIA Ampere架构及以上GPU的MIG(Multi-Instance GPU)技术,在硬件层面将物理GPU划分为多个独立实例。

核心特点:

需要A100/H100等支持MIG的GPU 硬件级性能隔离保障 资源划分遵循MIG的固定几何规格 显存分配自动匹配最接近的MIG规格 典型场景:

生产环境关键任务 对延迟敏感的推理服务 需要确定性能保障的分布式训练

安装:

一、部署方案概览

前提条件

确保满足以下要求:

  • NVIDIA 驱动版本 > 440

  • nvidia-docker (建议使用 nvidia-docker2) 版本 > 2.0,且 Docker 默认 runtime 设置为 nvidia 

  • Kubernetes 版本 ≥ 1.16

  • 已安装 Volcano,版本 ≥ 1.9

二、详细部署步骤
1. GPU 节点准备

在每个 GPU 节点上执行:

# 安装 NVIDIA Docker 2

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-docker2
sudo systemctl restart docker

配置 Docker 默认 runtime 为 nvidia(/etc/docker/daemon.json):

{
  "default-runtime": "nvidia",
  "runtimes": {
    "nvidia": {
      "path": "/usr/bin/nvidia-container-runtime",
      "runtimeArgs": []
    }
  }
}

重启 Docker 后生效

2. 配置 Volcano 调度器支持 vGPU

在安装好 Volcano 后,启用 vGPU 支持。编辑 configmap:

kubectl edit cm -n volcano-system volcano-scheduler-configmap

内容示例如下,启用 deviceshare 插件,开启 vGPU 功能:

data:
  volcano-scheduler.conf: |
    actions: "enqueue, allocate, backfill"
    tiers:
    - plugins:
      - name: priority
      - name: gang
      - name: conformance
    - plugins:
      - name: drf
      - name: deviceshare
        arguments:
          deviceshare.VGPUEnable: true
          deviceshare.SchedulePolicy: binpack    # 可选:binpack 或 spread
      - name: predicates
      - name: proportion
      - name: nodeorder
      - name: binpack
3. 部署 Volcano-vgpu-device-plugin(DaemonSet)

使用以下命令一键部署:

kubectl create -f https://raw.githubusercontent.com/Project-HAMi/volcano-vgpu-device-plugin/main/volcano-vgpu-device-plugin.yml   
#默认在kube-system名称空间下

这个插件会注册 vGPU 资源(如 volcano.sh/vgpu-number、volcano.sh/vgpu-memory 等)到 Kubernetes 节点上,供调度器和 Pod 使用

4.编辑 Volcano-vgpu-device-plugin的configmap

编辑volcano-vgpu-node-config

kubectl edit cm -n kube-system volcano-vgpu-device-config

内容示例如下,用于告诉插件 如何在物理 GPU 上划分虚拟 GPU(vGPU)资源

apiVersion: v1
data:
  device-config.yaml: |-
    nvidia:
      #以下三行的作用是当 Pod 请求 vGPU 时,这些字段对应 resources.limits 或 resources.requests。
      resourceCountName: volcano.sh/vgpu-number
      resourceMemoryName: volcano.sh/vgpu-memory
      resourceCoreName: volcano.sh/vgpu-cores
      resourceMemoryPercentageName: volcano.sh/vgpu-memory-percentage
      overwriteEnv: false     #是否覆盖容器内环境变量
      defaultMemory: 0        #没有指定时的默认 vGPU 显存、核心和数量
      defaultCores: 0
      defaultGPUNum: 1
      deviceSplitCount: 10    #物理 GPU 最大可被切分成多少 vGPU
      #以下三行的作用是HAMI-core 内部用来计算虚拟 GPU 的比例系数
      deviceMemoryScaling: 256
      deviceCoreScaling: 1
      gpuMemoryFactor: 1
      knownMigGeometries:         #动态MIG切分方案      
        - models: [ "A800-SXM4-80GB" ]
          allowedGeometries:      #允许的 vGPU 切分方案
            - group: "group1"     #配置分组
              geometries:
                - name: 1g.10gb   #vGPU 标识
                  memory: 10240   #每个 vGPU 的显存大小(MB)
                  count: 7        #可用数量
            - group: "group2"
              geometries:
                - name: 2g.20gb
                  memory: 20480
                  count: 3
                - name: 1g.10gb
                  memory: 10240
                  count: 1
            - group: "group3"
              geometries:
                - name: 3g.40gb
                  memory: 40960
                  count: 2
            - group: "group4"
              geometries:
                - name: 7g.79gb
                  memory: 80896
                  count: 1
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"device-config.yaml":"nvidia:\n  resourceCountName: volcano.sh/vgpu-number\n  resourceMemoryName: volcano.sh/vgpu-memory\n  resourceMemoryPercentageName: volcano.sh/vgpu-memory-percentage\n  resourceCoreName: volcano.sh/vgpu-cores\n  overwriteEnv: false\n  defaultMemory: 0\n  defaultCores: 0\n  defaultGPUNum: 1\n  deviceSplitCount: 10\n  deviceMemoryScaling: 256\n  deviceCoreScaling: 1\n  gpuMemoryFactor: 1\n  knownMigGeometries:\n    - models: [ \"A800-SXM4-80GB\" ]\n      allowedGeometries:\n        - group: \"group1\"\n          geometries:\n            - name: 1g.10gb\n              memory: 10240\n              count: 7\n        - group: \"group2\"\n          geometries:\n            - name: 2g.20gb\n              memory: 20480\n              count: 3\n            - name: 1g.10gb\n              memory: 10240\n              count: 1\n        - group: \"group3\"\n          geometries:\n            - name: 3g.40gb\n              memory: 40960\n              count: 2\n        - group: \"group4\"\n          geometries:\n            - name: 7g.79gb\n              memory: 80896\n              count: 1"},"kind":"ConfigMap","metadata":{"annotations":{},"labels":{"app.kubernetes.io/component":"volcano-vgpu-device-plugin"},"name":"volcano-vgpu-device-config","namespace":"kube-system"}}
  labels:
    app.kubernetes.io/component: volcano-vgpu-device-plugin
  name: volcano-vgpu-device-config
  namespace: kube-system

HAMI-core 会根据这个配置把物理 GPU 切分成多个虚拟 GPU,供 Pod 按需使用。

  • 1g.10gb → 1 个 slice,10GB 显存

  • 2g.20gb → 3个slice, 20GB 显存

  • 3g.40gb → 3 个 slice,40GB 显存

  • 7g.80gb → 1个slice, 80GB 显存

  1. 注册 vGPU 资源到 Kubernetes 节点

    • Device Plugin 读取 ConfigMap,把 volcano.sh/vgpu-number、volcano.sh/vgpu-memory 等资源注册到 kubelet 上。

  2. 定义物理 GPU 如何被切分

    • HAMI-core 根据 knownMigGeometries + deviceSplitCount 切分物理 GPU。

5.编辑volcano-vgpu-node-config

kubectl edit cm -n kube-system volcano-vgpu-node-config

内容示例如下,它和之前的 volcano-vgpu-device-config 配置是配套的,但作用更侧重于 节点层面的 vGPU 策略

{
  "nodeconfig": [   #节点配置列表,每个对象对应一个 GPU 节点
    {
      "name": "ser-nettrix-02",       #节点名,必须和 Kubernetes 中 Node 的 metadata.name 一致
      "operatingmode": "hami-core",   #GPU 虚拟化模式
      "devicememoryscaling": 256,     #显存缩放因子,HAMI-core 内部用来计算每个 slice 的实际显存
      "devicesplitcount": 10,         #每张物理 GPU 可切分的虚拟 GPU 数量
      "migstrategy": "none",          #MIG 策略,这里 "none" 表示不使用 MIG
      "filterdevices": {              #可选择性过滤 GPU
        "uuid": [],                   #为空表示全选
        "index": []                   ##为空表示全选
      }
    }
  ]
}

配合 Device Plugin 的全局配置

  1. 告诉 Node Plugin 如何在该节点上启用 HAMI-core vGPU

    • 对应 Pod 的 volcano.sh/vgpu-* 请求,Node Plugin 会根据这个配置切分 GPU

  2. 控制节点层面的切分策略

    • devicesplitcount + devicememoryscaling 决定物理 GPU 如何被分割

    • 允许在单节点上灵活调整 vGPU 数量和大小

  3. 支持 GPU 过滤

    • 如果节点上有多块 GPU,只想虚拟化部分 GPU,可以用 filterdevices

    • 当前为空,表示节点所有 GPU 都会被 HAMI-core 管理

  4. 配合 Device Plugin 的全局配置

    • 之前的 volcano-vgpu-device-config 决定 vGPU 的全局几何和资源名

    • 这个 Node Plugin Config 决定 具体节点如何切分、哪些 GPU 可用

调度程序模式选择

  • 显式模式

    • 使用注释volcano.sh/vgpu-mode强制使用 hami-core 或 MIG 模式。

    • 如果没有注释,调度程序将根据资源适合度和策略选择模式。

  • 调度策略

    • 模式类似binpackspread影响节点选择。

6. 验证节点是否就绪

检查节点状态,确保 allocatable 中包含以下资源项:

kubectl get nodes set-nettrix -oyaml

Addresses:
  InternalIP:  10.0.14.144
  Hostname:    ser-nettrix
Capacity:
  cpu:                     128
  ephemeral-storage:       824646552Ki
  hugepages-1Gi:           0
  hugepages-2Mi:           0
  memory:                  1056477052Ki
  nvidia.com/gpu:          8
  pods:                    520
  volcano.sh/vgpu-cores:   800
  volcano.sh/vgpu-memory:  65536
  volcano.sh/vgpu-number:  80
Allocatable:
  cpu:                     127600m
  ephemeral-storage:       824646552Ki
  hugepages-1Gi:           0
  hugepages-2Mi:           0
  memory:                  1027216587380
  nvidia.com/gpu:          8
  pods:                    520
  volcano.sh/vgpu-cores:   800
  volcano.sh/vgpu-memory:  65536
  volcano.sh/vgpu-number:  80
7. 提交 HAMI-core 模式的 vGPU 作业示例

创建一个 Pod,使用 hami-core 模式,指定 vGPU 数量、显存和核比例:

root@ser-compute-06:~# cat vgpu-request-test.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: test2
spec:
  restartPolicy: OnFailure
  schedulerName: volcano       #执行通过Volcano调度器调度
  containers:
  - name: pod1-ctr
    image: ubuntu:24.04
    command: ["sleep", "1000"]
    resources:
      limits:
        volcano.sh/vgpu-memory: 512
        volcano.sh/vgpu-number: 1
        volcano.sh/vgpu-cores: 10
      requests:
        volcano.sh/vgpu-cores: 10
        volcano.sh/vgpu-memory: 512
        volcano.sh/vgpu-number: 1

提交:

kubectl apply -f  vgpu-request-test.yaml 

验证:

root@ser-compute-06:~# kubectl describe nodes ser-nettrix-02    #查看Allocated resouces
  Resource                Requests           Limits
  --------                --------           ------
  cpu                     98177m (76%)       148850m (116%)
  memory                  392285714Ki (39%)  984098Mi (100%)
  ephemeral-storage       5170Mi (0%)        31Gi (3%)
  hugepages-1Gi           0 (0%)             0 (0%)
  hugepages-2Mi           0 (0%)             0 (0%)
  nvidia.com/gpu          8                  8
  volcano.sh/vgpu-cores   10                 10
  volcano.sh/vgpu-memory  512                512
  volcano.sh/vgpu-number  1                  1
​
root@ser-compute-06:~# kubectl exec test2 bash -- nvidia-smi
[HAMI-core Msg(13:139957801031488:libvgpu.c:838)]: Initializing.....
Thu Sep  4 07:17:03 2025       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.60.13    Driver Version: 525.60.13    CUDA Version: 12.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA A800-SXM...  On   | 00000000:D3:00.0 Off |                    0 |
| N/A   28C    P0    60W / 400W |      0MiB /  5120MiB |      0%      Default |
|                               |                      |             Disabled |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
[HAMI-core Msg(13:139957801031488:multiprocess_memory_limit.c:499)]: Calling exit handler 13
root@ser-compute-06:~# 

二、监控

  • 调度程序指标

    curl http://<volcano-scheduler-ip>:8080/metrics
    
  • 设备插件指标

    curl http://<plugin-pod-ip>:9394/metrics
    

指标包括 GPU 利用率、pod 内存使用率和限制。

三、问题:

描述节点时获取 volcano.sh/gpu-memory:0

Allocatable:
  cpu:                     127600m
  ephemeral-storage:       824646552Ki
  hugepages-1Gi:           0
  hugepages-2Mi:           0
  memory:                  1027216587380
  nvidia.com/gpu:          8
  pods:                    520
  volcano.sh/vgpu-cores:   800
  volcano.sh/vgpu-memory:  0
  volcano.sh/vgpu-number:  80

相关描述

可以发现Allocatable中的  volcano.sh/vgpu-memory: 0,通过查看node节点的kubelet日志发现是因为Volcano device plugin读取了GPU显存,核数;Device Plugin的pod正常识别调用卡通过GRPC上报kubelet失败,因为默认kubelet的GRPC协议最大接受大小为4MB

简而言之就是超过阈值的显存就会报错,导致 DevicePlugin 无法正常上报,因此显示为 0。

解决方案:需要在启动时设置参数--gpu-memory-factor=10,将最小的显存块从默认 1MB 改成 10MB,就像这样:

containers:
- image: docker.io/projecthami/volcano-vgpu-device-plugin:v1.10.0
  args:["--device-split-count=10","--gpu-memory-factor=10"]
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐