Kubernetes 异构算力调度与虚拟化实战:Volcano + HAMi 在昇腾 NPU 集群的落地
Kubernetes 异构算力调度与虚拟化实战:Volcano + HAMi 在昇腾 NPU 集群的落地
摘要:整卡独占部署的 NPU 集群利用率低、小任务没地方跑,是昇腾集群运维的普遍痛点。本文介绍两条互补的解决路径:用 Volcano(CNCF 批量调度系统)解决"任务怎么排队、怎么整体调度",用 HAMi(CNCF 孵化项目,异构 AI 计算虚拟化中间件)解决"一张卡怎么切开给多个任务"。含项目定位、部署步骤、昇腾 NPU 切分示例、Volcano+HAMi 协同配置与踩坑记录。
一、背景:整卡独占的算力浪费
在昇腾 910B/910C 集群上部署多模态模型(详见本系列部署篇)时,采用的原则是"每个模型单实例、整卡/多卡独占"。这套方案稳定、排障简单,但问题也很明显:
- 大模型吃不满整卡:推理场景下 NPU 利用率往往只有 20%-50%,显存还有大量余量;
- 小任务无卡可用:一个只需要 2GB 显存的小任务,也得等一整张 910B 空闲才能跑;
- 多任务排队靠人工:没有队列和优先级机制,多个训练/推理任务只能运维手动协调。
要解决这个问题,需要从两个层面同时下手:
| 层面 | 解决的问题 | 代表组件 |
|---|---|---|
| 调度层 | 任务排队、优先级、公平调度、Gang 全有或全无、队列配额 | Volcano |
| 设备层 | 单卡显存/算力切分、多任务共享、资源隔离 | HAMi |
两个组件各管一段、天然互补,这也是当前昇腾/信创集群资源池化的主流组合。
二、Volcano 与 HAMi 项目定位
2.1 Volcano:Kubernetes 原生批量调度系统
| 项目 | 说明 |
|---|---|
| 项目地址 | https://github.com/volcano-sh/volcano |
| 社区地位 | CNCF 项目(2019 年上海 KubeCon 开源,2020 年 4 月进入 CNCF,2022 年 4 月进入 Incubating);已从"批量调度"演进为 AI 原生统一调度平台 |
| 最新版本 | v1.15.0(2026-05),支持 Kubernetes 1.35 |
| 核心能力 | 多层级队列管理与配额、优先级/抢占、公平调度(DRF)、Gang Scheduling(PodGroup 全有或全无)、异构设备(GPU/NPU)调度、网络拓扑感知 |
| 生态事实 | Apache Spark 3.3 起将 Volcano 作为 Kubernetes 默认批量调度器;支持 PyTorch/TF/Ray/Flink 等框架 |
核心组件:volcano-scheduler(调度器)、volcano-controller(控制器,管理 Job/PodGroup)、vcctl(命令行工具)。
2.2 HAMi:异构 AI 计算虚拟化中间件
| 项目 | 说明 |
|---|---|
| 项目地址 | https://github.com/Project-HAMi/HAMi |
| 社区地位 | 前身为 4paradigm 的 k8s-device-plugin;2024 年 8 月进入 CNCF Sandbox,2026 年 7 月晋升 CNCF Incubating |
| 最新版本 | v2.10.0(2026-08) |
| 支持硬件 | NVIDIA GPU、昇腾 Ascend(910A / 910B2 / 910B3 / 310P)、海光 DCU、寒武纪 MLU 等 |
| 昇腾能力 | v2.9.0 引入 HAMi-core 模式:用户态拦截 ACL(Ascend Computing Language)调用,实现 MB 级显存 + 百分比级算力的细粒度软切分,单张 910C 可同时服务多个任务;v2.10.0 支持 vNPU 硬切分 + 软切分自动选择 |
2.3 两者的分工
应用层:Volcano Job / PodGroup / 普通 Pod(schedulerName: volcano)
│
调度层:Volcano Scheduler ── 队列 / 优先级 / Gang / 公平调度
│ └── deviceshare 插件 ── 设备切分决策(HAMi vGPU / Ascend vNPU)
│
设备层:节点上的 HAMi device plugin(或 volcano-vgpu-device-plugin)
│ ├── vNPU 硬切分:按卡模板切分,隔离强
│ └── HAMi-core 软切分:用户态拦截,粒度细
│
硬件层:昇腾 910B / 910C / NVIDIA GPU / 海光 DCU 等
一句话总结:Volcano 管"哪些任务一起跑、按什么顺序跑、占多少配额",HAMi 管"一张卡切成几份、每份多少显存和算力、互相不干扰"。
三、Volcano 部署与核心概念
3.1 安装 Volcano
# 方式一:Helm(推荐)
helm repo add volcano-sh https://volcano-sh.github.io/helm-charts
helm repo update
helm install volcano volcano-sh/volcano -n volcano-system --create-namespace
# 方式二:官方 Installer YAML(指定版本)
kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.15.0/installer/volcano-development.yaml
# 验证
kubectl get pods -n volcano-system
# 预期:volcano-scheduler-xxx、volcano-controller-xxx 均为 Running
注意:Volcano 安装后,还需要给命名空间打标签,让 Volcano 管理该命名空间的 Pod(否则调度器不接管):
kubectl label ns <your-namespace> volcano.sh/enable="true"
3.2 核心概念
| 概念 | API | 作用 |
|---|---|---|
| Queue | scheduling.volcano.sh/v1beta1 | 资源配额容器,支持多层级队列、权重、抢占策略 |
| PodGroup | scheduling.volcano.sh/v1beta1 | Gang 调度单元,minMember 个 Pod 全部满足才调度(全有或全无) |
| Job | batch.volcano.sh/v1alpha1 | Volcano 批量作业,含 task 模板、minAvailable、队列归属 |
| vcctl | - | 命令行工具,vcctl queue create 等 |
3.3 示例:队列 + Volcano Job(昇腾 NPU)
创建队列:
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
name: train-queue
spec:
weight: 1
reclaimable: false
policy: besteffort
capability: # 队列资源配额
cpu: "64"
memory: 256Gi
huawei.com/Ascend910: "8"
创建批量训练作业:
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: npu-train-job
spec:
schedulerName: volcano # 关键:走 Volcano 调度
minAvailable: 2 # Gang 调度,2 个 worker 全部就绪才启动
queue: train-queue
policies:
- event: PodFailed
action: RestartJob
tasks:
- name: worker
replicas: 2
template:
spec:
containers:
- name: train
image: ascend-pytorch:24.0.RC1
command: ["bash", "-c", "python train.py"]
resources:
limits:
huawei.com/Ascend910: "1"
restartPolicy: Never
提交并观察:
kubectl apply -f queue.yaml -f job.yaml
vcctl job list
kubectl get podgroup
kubectl get pods -o wide | grep npu-train
四、HAMi 部署与昇腾 NPU 切分
4.1 安装 HAMi
# 1) 给被管理的节点打标签(HAMi 只管理打了标签的节点)
kubectl label nodes <node-name> gpu=on
# 2) 添加 Helm 仓库并安装
helm repo add hami-charts https://project-hami.github.io/HAMi/
helm repo update
helm install hami hami-charts/hami -n kube-system
# 3) 验证 scheduler 和 device plugin 都正常
kubectl get pods -n kube-system | grep hami
4.2 昇腾的两种切分模式
| 模式 | 原理 | 粒度 | 适用 |
|---|---|---|---|
| vNPU 硬切分 | 按设备模板(vir02/vir04/vir08/vir16 等)把整卡物理切分 | 显存按模板固定(如 910B 模板 2184/4369/8738/17476 MB),AI Core 按比例 | 需要强隔离、稳定的生产推理 |
| HAMi-core 软切分 | 用户态拦截 ACL 调用,纯软件虚拟化,无需改应用代码 | MB 级显存 + 百分比级算力,最细粒度 | 多任务共享一张卡、最大化利用率 |
v2.10.0 起:不带 huawei.com/vnpu-mode 注解的 Pod 落到模板节点走 vNPU 硬切分、落到 hami-core 节点走软切分;带显式注解则按注解走。
注意(官方 FAQ):昇腾 npu=1 时不支持拆分,整卡独占;拆分粒度取决于卡类型模板(910A / 910B2 / 910B3 / 310P 各不相同)。
4.3 资源申请示例
软切分(HAMi-core):申请 1 张 910B 的 4GB 显存
apiVersion: v1
kind: Pod
metadata:
name: npu-share-test
spec:
containers:
- name: test
image: ascend-pytorch:24.0.RC1
command: ["bash", "-c", "sleep 86400"]
resources:
limits:
huawei.com/Ascend910B: "1" # 请求 1 张 910B
huawei.com/Ascend910B-memory: "4096" # 请求 4096MB 显存(不指定则整卡)
按算力申请(910B3):1 张卡 + 40% 算力
resources:
limits:
huawei.com/Ascend910B3: "1"
huawei.com/Ascend910B3-memory: "28672"
huawei.com/Ascend910B3-core: "40" # 请求 40% 的 AI Core 算力
910 系列(910A/910B 通用名)
resources:
limits:
huawei.com/Ascend910: "1" # 请求 1 个 NPU
huawei.com/Ascend910-memory: "2000" # 请求 2000m 设备内存
提示:
Ascend910-memory同时限定了算力配额——请求的显存占整卡的比例即算力比例。910B 推理场景单卡 64GB,若任务只用 8GB,即可在一张卡上切 8 个实例。
4.4 验证切分效果
# 看 Pod 被分配到哪张卡
kubectl get pod npu-share-test -o jsonpath='{.status.containerStatuses[0].deviceIDs}'
# 节点上确认容器可见的设备
kubectl exec -it npu-share-test -- npu-smi info
五、Volcano + HAMi 协同:调度层 × 设备层
单装 HAMi 解决"怎么切",单装 Volcano 解决"怎么排",两者配合才能真正把 NPU 池化用起来。官方提供两条集成路径:
5.1 路径一:Volcano vGPU(NVIDIA 场景)
使用 volcano-vgpu-device-plugin(基于 NVIDIA Device Plugin + HAMi-core 硬隔离),此时无需再装完整 HAMi。需要 Volcano > 1.9:
# volcano-scheduler-configmap 中启用 vGPU
conf: |
actions: "enqueue, allocate, backfill"
tiers:
- plugins:
- name: priority
- name: gang
- name: conformance
- plugins:
- name: drf
- name: deviceshare
arguments:
deviceshare.VGPUEnable: true # 启用 vGPU
deviceshare.SchedulePolicy: binpack # binpack / spread
- name: predicates
- name: proportion
Pod 侧启用软切分(HAMi-core 模式):
apiVersion: v1
kind: Pod
metadata:
annotations:
volcano.sh/vgpu-mode: "hami-core"
spec:
schedulerName: volcano
containers:
- name: cuda-container
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpu-mem: "4096" # 4GB 显存
nvidia.com/gpucores: "50" # 50% 算力
5.2 路径二:Ascend vNPU(昇腾场景)
Volcano 调度器启用 deviceshare 插件 + HAMi 的昇腾 vNPU 能力:
# volcano-scheduler-configmap 中启用 Ascend vNPU
conf: |
actions: "enqueue, allocate, backfill"
tiers:
- plugins:
- name: priority
- name: gang
- name: conformance
- plugins:
- name: drf
- name: predicates
- name: deviceshare
arguments:
deviceshare.AscendHAMiVNPUEnable: true # 启用昇腾 vNPU
deviceshare.SchedulePolicy: binpack
deviceshare.KnownGeometriesCMNamespace: kube-system
deviceshare.KnownGeometriesCMName: hami-scheduler-device
然后按第四节的方式申请 huawei.com/Ascend910B-memory 等资源,Volcano 会结合队列配额与 HAMi 上报的设备切分信息完成调度。
5.3 协同后的典型效果
- 多租户队列:A 团队训练队列、B 团队推理队列,各自配额互不抢占;
- Gang 调度:8 卡分布式训练任务,8 个 worker 全部就绪才启动,避免部分卡空转等待;
- 卡级共享:一张 910B(64GB)按 8GB/份切给 8 个推理任务,利用率从 30% 提升到 80%+;
- 优先级抢占:高优任务入队时,可回收低优任务占用的设备资源。
六、踩坑记录
以下问题来自官方文档与社区实践,部署前建议逐条核对:
| 坑点 | 现象 | 处理 |
|---|---|---|
| 官方 ascend-device-plugin 与 HAMi 同时部署 | 节点资源名冲突、Pod 调度错乱 | 二选一:用 HAMi 就别再装华为官方 device plugin(CANN 侧只保留一个上报通道) |
节点未打 gpu=on 标签 | HAMi 不管理该节点,申请切分资源永远 Pending | 检查 kubectl get nodes --show-labels,补齐标签 |
| npu=1 想拆分 | 分配失败或整卡独占 | 官方 FAQ 明确 npu=1 不支持拆分;小任务先申请 -memory 再验证模板 |
| 切分粒度与卡型号不匹配 | 910A/910B2/910B3 模板不同,申请的资源名写错直接调度失败 | 先查 HAMi 官方设备模板,按实际卡型号写 huawei.com/Ascend910B3 等精确资源名 |
| Gang 调度任务一直 Pending | PodGroup minMember/minAvailable 不满足(如资源不够凑齐全部 worker) | 检查队列配额和节点剩余资源;临时调小 minAvailable 验证 |
| Volcano 版本过旧 | vGPU/昇腾 vNPU 特性不生效 | volcano-vgpu 需要 Volcano > 1.9;昇腾 vNPU 协同建议用较新版本(1.15+) |
| HAMi-core 软切分与 CANN 版本兼容 | 部分算子运行异常 | 软切分依赖 ACL 用户态拦截,上线前用代表性算子/模型做一轮回归 |
| Helm/镜像拉取慢(内网环境) | 安装卡住 | 配置代理,或提前拉取镜像离线导入;helm 仓库也可镜像到内网 |
| 队列 capability 资源名不一致 | 配额不生效 | Queue 里写的资源名必须与 HAMi 上报一致(huawei.com/Ascend910 系列) |
| 与存量"整卡独占"部署冲突 | 已运行的服务占着整卡,切分任务无卡可切 | 先停掉独占服务或规划专用节点,再逐步过渡到共享池 |
七、总结与后续
Volcano + HAMi 的组合,把昇腾集群从"一模型一集群"的粗放模式,升级为"队列配额 + 卡级共享 + Gang 调度"的资源池模式:
- Volcano:批量调度的事实标准,队列/优先级/Gang/公平调度一站式解决;
- HAMi:异构虚拟化中间件,一张昇腾卡切成多个细粒度实例,多芯适配(昇腾/海光/寒武纪)贴合信创诉求;
- 两者互补:调度层决策"往哪跑",设备层解决"怎么共享",是昇腾 NPU 集群资源池化的成熟路径。
后续可以继续展开的方向:
- 多芯异构统一池:同一集群纳管昇腾 + 海光 + NVIDIA,用统一资源名做跨芯调度;
- 任务队列治理:结合公司多租户场景设计队列层级与配额模型。
参考资料:
- Volcano 官网与文档:https://volcano.sh
- Volcano GitHub:https://github.com/volcano-sh/volcano
- HAMi 官网与文档:https://project-hami.io
- HAMi GitHub:https://github.com/Project-HAMi/HAMi
- 昇腾社区 NPU 虚拟化参考实践:https://www.hiascend.com
更多推荐




所有评论(0)