Volcano 部署与基础功能测试:VolcanoJob、Gang Scheduling、Queue 与 Deployment 调度验证
一、Volcano 简介
Volcano 是一个 Kubernetes 原生的批调度系统,主要面向 AI 训练、大数据计算、HPC、高性能批处理等场景。
相比 Kubernetes 默认调度器,Volcano 更关注“成组任务”的调度语义。例如分布式训练中的多个 worker、parameter server、MPI 任务等,这类任务往往不是单个 Pod 能独立完成的,而是需要一组 Pod 同时满足资源条件后才具备运行意义。
在普通 Kubernetes 调度中,Pod 通常是以单个对象为单位进行调度;而在分布式训练场景中,如果只启动其中一部分 Pod,任务可能无法正常运行,同时还会占用集群资源。Volcano 的 Gang Scheduling 就是为了解决这类问题。
Volcano 的核心能力主要包括:
-
VolcanoJob:Volcano 提供的批任务 CRD;
-
PodGroup:一组成组调度 Pod 的抽象;
-
Gang Scheduling:成组调度能力;
-
Queue:队列资源管理能力;
-
多种调度插件:如 gang、priority、drf、predicates、proportion、capacity、nodeorder、binpack 等。
Volcano 不会替换 Kubernetes 默认调度器。只有在 Pod 模板中显式指定:
schedulerName: volcano
该 Pod 才会交给 Volcano Scheduler 调度。没有指定该字段的普通工作负载,仍然会使用 Kubernetes 默认调度器。
二、Volcano 部署
Volcano 官方文档提供了 YAML、源码和 Helm 等部署方式。实验环境中建议使用 Helm 部署,后续升级和卸载都比较方便。
1. 添加 Helm 仓库
helm repo add volcano-sh https://volcano-sh.github.io/helm-charts
helm repo update
2. 安装 Volcano
官方 Helm 安装命令如下:
helm install volcano volcano-sh/volcano \
-n volcano-system \
--create-namespace
如果希望避免镜像被频繁拉取,也可以增加镜像拉取策略参数:
helm install volcano volcano-sh/volcano \
-n volcano-system \
--create-namespace \
--set basic.image_pull_policy=IfNotPresent
其中:
--set basic.image_pull_policy=IfNotPresent
不是必需参数,主要用于实验环境中减少重复拉取镜像。
3. 查看 Volcano 组件状态
kubectl get pod -n volcano-system
实际输出如下:
NAME READY STATUS RESTARTS AGE
volcano-admission-cf4d8dd5c-dshz9 1/1 Running 1 (11m ago) 22h
volcano-controllers-5b976c6d4b-6s92b 1/1 Running 1 (11m ago) 22h
volcano-scheduler-549f77db69-whptp 1/1 Running 1 (11m ago) 21h
这三个核心组件的作用如下:
| 组件 | 作用 |
|---|---|
| volcano-scheduler | Volcano 调度器,负责 PodGroup、VolcanoJob 等资源的调度 |
| volcano-controllers | Volcano 控制器,负责 VolcanoJob、PodGroup、Queue 等资源的生命周期管理 |
| volcano-admission | Admission 组件,负责资源校验、默认值处理等 |
只要这几个组件正常 Running,说明 Volcano 基础组件已经启动成功。
三、测试一:VolcanoJob 基础运行
1. 测试目标
该测试用于验证 Volcano 的基础功能是否正常,包括:
-
VolcanoJob CRD 是否可用;
-
Volcano Controller 是否能够创建对应 Pod;
-
Volcano Scheduler 是否能够调度 Pod;
-
VolcanoJob 是否会自动关联 PodGroup;
-
TaskCompleted -> CompleteJob生命周期策略是否生效。
VolcanoJob 是 Volcano 提供的 CRD,和 Kubernetes 原生 Job 不是同一个资源。VolcanoJob 更适合批处理、AI 训练、MPI、大数据计算等场景,因为它天然集成了 Queue、PodGroup、Gang Scheduling 等能力。
2. YAML 示例
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: vcjob-basic
namespace: volcano-demo
spec:
schedulerName: volcano
queue: default
minAvailable: 1
maxRetry: 1
tasks:
- name: basic-task
replicas: 1
policies:
- event: TaskCompleted
action: CompleteJob
template:
spec:
restartPolicy: Never
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
echo "Volcano job is running"
sleep 20
echo "Volcano job completed"
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "100m"
memory: "64Mi"
3. 验证结果
查看 VolcanoJob:
kubectl -n volcano-demo get vcjob
输出如下:
NAME STATUS MINAVAILABLE RUNNINGS AGE
vcjob-basic Running 1 1 13s
查看 PodGroup:
kubectl -n volcano-demo get podgroup
输出如下:
NAME STATUS MINMEMBER RUNNINGS AGE
vcjob-basic-90ac694a-9eae-4cfb-aef2-e14c7ef7cd5a Running 1 1 20s
查看 Pod:
kubectl -n volcano-demo get pod
输出如下:
NAME READY STATUS RESTARTS AGE
vcjob-basic-basic-task-0 0/1 Completed 0 23s
4. 结果分析
这个测试中,vcjob-basic 的 minAvailable 为 1,task 副本数也是 1,因此只要这个 Pod 能够被调度,整个 Job 就满足最小运行条件。从 PodGroup 可以看到:
STATUS Running
MINMEMBER 1
RUNNINGS 1
说明 Volcano 已经为该 VolcanoJob 创建了对应的 PodGroup,并且 PodGroup 当前满足最小成员数要求。Pod 最终变成:
STATUS Completed
这是正常现象。因为 busybox 容器执行完 echo 和 sleep 20 后会正常退出,restartPolicy: Never 表示容器退出后不会重启,所以 Pod 状态会变成 Completed。
需要注意的是,kubectl get vcjob 中 Job 状态从 Running 变为 Completed 可能会有一个短暂的 controller 同步延迟。只要 Pod 已经 Completed,并且配置了:
policies:
- event: TaskCompleted
action: CompleteJob
Volcano Controller 后续会根据 task 完成状态把 VolcanoJob 标记为 Completed。
5. 字段说明
schedulerName: volcano
表示该 Job 创建出来的 Pod 使用 Volcano Scheduler 调度。
queue: default
表示该 Job 使用 Volcano 默认队列。Volcano 启动后会自动创建 default queue,未显式指定队列的 VolcanoJob 会进入默认队列。
minAvailable: 1
表示该 Job 至少需要 1 个 Pod 满足调度条件,Job 才能进入运行状态。
tasks:
- name: basic-task
replicas: 1
表示该 Job 中包含一个名为 basic-task 的 task,副本数量为 1。
policies:
- event: TaskCompleted
action: CompleteJob
表示当该 task 内的 Pod 成功完成后,将整个 VolcanoJob 标记为完成。TaskCompleted 用于判断某个 task 是否完成,CompleteJob 用于将 Job 置为完成状态,并处理未完成的 Pod。
四、测试二:Gang Scheduling 成功场景
1. 测试目标
该测试用于验证 Volcano 的 Gang Scheduling 能力。
Gang Scheduling 的核心语义是:一组 Pod 必须作为整体满足调度条件。如果最小成员数不满足,则该组 Pod 不应被部分调度。
在分布式训练场景中,假设一个任务需要 2 个 worker 同时启动,如果资源只允许启动其中 1 个 worker,那么任务实际上无法正常工作。Gang Scheduling 的作用就是避免这种“部分启动、整体不可用”的情况。
2. YAML 示例
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: vcjob-gang-success
namespace: volcano-demo
spec:
schedulerName: volcano
queue: default
minAvailable: 2
maxRetry: 1
tasks:
- name: worker
replicas: 2
policies:
- event: TaskCompleted
action: CompleteJob
template:
spec:
restartPolicy: Never
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
echo "gang worker started: $(hostname)"
sleep 60
echo "gang worker finished"
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "100m"
memory: "64Mi"
3. 验证结果
查看 VolcanoJob:
kubectl -n volcano-demo get vcjob
输出如下:
NAME STATUS MINAVAILABLE RUNNINGS AGE
vcjob-gang-success Running 2 2 15s
查看 Pod:
kubectl -n volcano-demo get pod
输出如下:
NAME READY STATUS RESTARTS AGE
vcjob-gang-success-worker-0 1/1 Running 0 17s
vcjob-gang-success-worker-1 1/1 Running 0 17s
查看 PodGroup:
kubectl -n volcano-demo get podgroup
输出如下:
NAME STATUS MINMEMBER RUNNINGS AGE
vcjob-gang-success-b731581b-ea2f-4d6b-b936-35bbb842b5f5 Running 2 2 23s
4. 结果分析
该 Job 的核心配置是:
minAvailable: 2
tasks:
- name: worker
replicas: 2
这表示该 Job 需要创建 2 个 worker Pod,并且至少要有 2 个 Pod 同时满足调度条件后,Volcano 才会放行。
从实验结果可以看到:
MINAVAILABLE 2
RUNNINGS 2
同时 PodGroup 中也显示:
MINMEMBER 2
RUNNINGS 2
这说明 Volcano 已经将该 Job 转换为一个 PodGroup 进行调度,并且当前集群资源满足该 PodGroup 的最小运行要求。因此两个 worker Pod 被一起调度成功。
这里的重点不是“创建了两个 Pod”,而是 Volcano 在调度前确认了这两个 Pod 作为一个整体满足最小运行条件。
五、测试三:Gang Scheduling 失败场景
1. 测试目标
该测试用于验证资源不足时,Volcano 是否会阻止 PodGroup 被部分调度。
为了便于观察效果,下面示例故意让每个 Pod 申请较大的内存。我的测试环境是 32Gi 内存的单节点 Kubernetes 集群,每个 Pod 申请 20Gi 内存,两个 Pod 总共需要 40Gi 内存,因此无法同时满足 minAvailable: 2 的要求。
如果测试节点内存更大,可以将 20Gi 调整为更高值,例如 100Gi 或 200Gi,确保资源不足。
2. YAML 示例
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: vcjob-gang-pending
namespace: volcano-demo
spec:
schedulerName: volcano
queue: default
minAvailable: 2
maxRetry: 1
tasks:
- name: worker
replicas: 2
template:
spec:
restartPolicy: Never
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
echo "should-not-start"
sleep 3600
resources:
requests:
cpu: "100m"
memory: "20Gi"
limits:
cpu: "100m"
memory: "20Gi"
3. 验证结果
查看 VolcanoJob:
kubectl -n volcano-demo get vcjob
输出如下:
NAME STATUS MINAVAILABLE RUNNINGS AGE
vcjob-gang-pending Pending 2 13s
查看 PodGroup:
kubectl -n volcano-demo get podgroup
输出如下:
NAME STATUS MINMEMBER RUNNINGS AGE
vcjob-gang-pending-5fbf33e1-39c5-4938-af57-88bb2c9f8b2e Pending 2 17s
查看 PodGroup 事件:
kubectl -n volcano-demo describe podgroup vcjob-gang-pending-5fbf33e1-39c5-4938-af57-88bb2c9f8b2e
输出如下:
Status:
Phase: Pending
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Unschedulable 8s (x25 over 33s) volcano resource in cluster is overused: overused memory
Warning Unschedulable 8s (x25 over 33s) volcano 0/0 tasks in gang unschedulable: pod group is not ready, 2 minAvailable
4. 结果分析
该测试的核心配置是:
minAvailable: 2
replicas: 2
同时,每个 Pod 的内存请求为:
requests:
memory: "20Gi"
两个 Pod 总共需要 40Gi 内存,而测试节点只有 32Gi 内存,无法同时满足两个 Pod 的资源请求。因此 Volcano 将该 Job 保持在 Pending 状态。
PodGroup 事件中最关键的信息是:
resource in cluster is overused: overused memory
这说明当前集群内存资源无法满足该 PodGroup 的最小运行需求。
另一条事件:
pod group is not ready, 2 minAvailable
说明 Volcano 当前没有满足 minAvailable=2 的条件,因此不会放行这组 Pod。
这里需要注意:不要只看 0/0 tasks in gang unschedulable 这一段。真正的根因要结合上面的事件一起看。本例中根因是内存资源不足,也就是:
overused memory
这正是 Gang Scheduling 的核心效果:当两个 Pod 不能同时满足调度条件时,Volcano 不会只启动其中一个 Pod,而是让整个 PodGroup 等待资源满足。
六、测试四:Queue 队列资源限制
1. 测试目标
该测试用于验证 Volcano Queue 的资源管理能力。
Queue 是 Volcano 中用于组织 PodGroup 的队列资源,可以作为多租户、团队隔离、资源分配的基础对象。本测试重点验证 Queue 的 capability 字段。
capability 表示该 Queue 可使用资源的上限,属于硬约束。也就是说,如果一个 PodGroup 的资源需求超过 Queue 的 capability,该 PodGroup 不应被正常调度。
需要注意:Queue 的资源控制依赖 Volcano Scheduler 中启用的队列相关插件,例如 proportion 或 capacity。如果手动修改过 volcano-scheduler-configmap,需要确认队列插件没有被关闭。
2. 创建 small-queue
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
name: small-queue
spec:
weight: 1
reclaimable: false
capability:
cpu: "500m"
memory: "512Mi"
查看 Queue:
kubectl get queue
输出如下:
NAME PARENT
default root
root
small-queue root
查看 small-queue 详情:
kubectl describe queue small-queue
输出如下:
Name: small-queue
API Version: scheduling.volcano.sh/v1beta1
Kind: Queue
Spec:
Capability:
Cpu: 500m
Memory: 512Mi
Dequeue Strategy: traverse
Parent: root
Reclaimable: false
Weight: 1
Status:
Allocated:
Cpu: 0
Memory: 0
Reservation:
State: Open
Events: <none>
3. Queue 结果分析
从输出可以看到:
State: Open
表示 small-queue 当前处于可用状态,可以接收新的 PodGroup。
Allocated:
Cpu: 0
Memory: 0
表示当前该 Queue 已经分配出去的资源为 0。也就是说,此时还没有运行中的 PodGroup 占用该 Queue 的资源。
Capability:
Cpu: 500m
Memory: 512Mi
表示该 Queue 最多只能使用 500m CPU 和 512Mi 内存。后续提交到该 Queue 的 Job,资源使用量不能超过这个上限。
4. 创建未超过 Queue capability 的 Job
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: vcjob-small-queue-ok
namespace: volcano-demo
spec:
schedulerName: volcano
queue: small-queue
minAvailable: 1
tasks:
- name: worker
replicas: 1
policies:
- event: TaskCompleted
action: CompleteJob
template:
spec:
restartPolicy: Never
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
echo "queue-ok"
sleep 6000
resources:
requests:
cpu: "200m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "128Mi"
该 Job 申请的资源为:
cpu: "200m"
memory: "128Mi"
而 small-queue 的资源上限为:
cpu: "500m"
memory: "512Mi"
因此该 Job 没有超过 Queue 的 capability,应能够正常调度。验证结果如下:
kubectl get pod -n volcano-demo
NAME READY STATUS RESTARTS AGE
vcjob-small-queue-ok-worker-0 1/1 Running 0 7s
查看 PodGroup:
kubectl get podgroup -n volcano-demo
NAME STATUS MINMEMBER RUNNINGS
vcjob-small-queue-ok-b0b82002-a693-4c89-98a6-23d1fa43e0ba Running 1 1
查看 VolcanoJob:
kubectl get vcjob -n volcano-demo
NAME STATUS MINAVAILABLE RUNNINGS AGE
vcjob-small-queue-ok Running 1 1 29s
5. 结果分析
该 Job 使用的是:
queue: small-queue
并且 minAvailable 为 1,task 副本数也为 1。
从实验结果可以看到,PodGroup 状态为 Running,MINMEMBER=1,RUNNINGS=1,说明该 PodGroup 已经满足最小运行条件,并且没有超过 Queue 的 capability 限制。
这个实验说明:当 Job 的资源请求没有超过 Queue 的资源上限时,Volcano 可以正常调度该 Job。
6. 创建超过 Queue capability 的 Job
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: vcjob-small-queue-over
namespace: volcano-demo
spec:
schedulerName: volcano
queue: small-queue
minAvailable: 1
tasks:
- name: worker
replicas: 1
template:
spec:
restartPolicy: Never
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
echo "queue-over"
sleep 3600
resources:
requests:
cpu: "1"
memory: "128Mi"
limits:
cpu: "1"
memory: "128Mi"
该 Job 申请的资源为:
cpu: "1"
memory: "128Mi"
而 small-queue 的 CPU 上限只有:
cpu: "500m"
因此该 Job 的 CPU 请求超过了 Queue 的 capability。验证结果如下:
kubectl get vcjob -n volcano-demo
NAME STATUS MINAVAILABLE RUNNINGS AGE
vcjob-small-queue-over Pending 1 5s
查看 PodGroup:
kubectl get podgroup -n volcano-demo
NAME STATUS MINMEMBER RUNNINGS AGE
vcjob-small-queue-over-89a74ecf-2cca-4eff-afec-2d5570a77db7 Pending 1 9s
查看 PodGroup 事件:
kubectl describe podgroup vcjob-small-queue-over-89a74ecf-2cca-4eff-afec-2d5570a77db7 -n volcano-demo
输出如下:
Status:
Phase: Pending
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Unschedulable 21s (x25 over 45s) volcano queue resource quota insufficient: insufficient cpu
Warning Unschedulable 21s (x25 over 45s) volcano 0/0 tasks in gang unschedulable: pod group is not ready, 1 minAvailable
7. 结果分析
该实验中最关键的事件是:
queue resource quota insufficient: insufficient cpu
这句话表示不是节点 CPU 一定不足,而是 Queue 的资源额度不足。
也就是说,当前 PodGroup 所属的 small-queue 只有 500m CPU capability,而 Job 申请了 1 核 CPU,超过了该 Queue 的资源上限。因此 Volcano 不会调度该 PodGroup。
这里要区分两类资源不足:
第一类是集群资源不足,例如前面 Gang Scheduling 失败场景中的:
resource in cluster is overused: overused memory
这表示集群维度资源不够。
第二类是队列资源额度不足,例如本测试中的:
queue resource quota insufficient: insufficient cpu
这表示 Queue 维度资源额度不够,即使集群整体可能还有资源,也不能突破该 Queue 的 capability 上限。
8. Queue 字段说明
weight: 1
表示队列权重。使用 proportion 插件时,Volcano 会根据所有队列的 weight 计算队列应得资源比例。weight 是软约束,不是硬限制。
reclaimable: false
表示当该队列使用了超过自身应得资源的部分时,是否允许其他队列回收这部分超额资源。
设置为 false 后,其他队列不能回收该队列已经占用的超额资源。实验环境中设置为 false,主要是为了减少资源回收带来的干扰。
capability:
cpu: "500m"
memory: "512Mi"
表示该队列可使用资源的上限。capability 是硬约束,超过该上限的 PodGroup 不应被调度运行。
七、测试五:普通 Deployment 使用 Volcano 调度
1. 测试目标
Volcano 不只支持 VolcanoJob,也可以调度 Kubernetes 原生工作负载,例如 Deployment、StatefulSet、Kubernetes Job 等。
对于普通工作负载,如果希望使用 Volcano 的 Gang Scheduling,需要同时满足两个条件:
第一,在工作负载上层资源中配置:
scheduling.volcano.sh/group-min-member: "2"
第二,在 Pod 模板中指定:
schedulerName: volcano
这两个配置缺一不可。
group-min-member 用于告诉 Volcano:这个工作负载最少需要多少个 Pod 作为一组满足调度条件。
schedulerName: volcano 用于告诉 Kubernetes:这个工作负载创建出来的 Pod 要交给 Volcano Scheduler 调度。
如果只写 group-min-member,但没有写 schedulerName: volcano,Pod 仍然会走默认调度器,不会真正使用 Volcano 的调度能力。
如果只写 schedulerName: volcano,但没有写 group-min-member,Pod 可以交给 Volcano 调度,但普通工作负载不会体现指定最小成员数的 Gang Scheduling 效果。
2. YAML 示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: volcano-deploy-gang
namespace: volcano-demo
annotations:
scheduling.volcano.sh/group-min-member: "2"
spec:
replicas: 2
selector:
matchLabels:
app: volcano-deploy-gang
template:
metadata:
labels:
app: volcano-deploy-gang
annotations:
scheduling.volcano.sh/queue-name: "default"
spec:
schedulerName: volcano
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
echo "deployment gang pod started: $(hostname)"
sleep 3600
resources:
requests:
cpu: "100m"
memory: "20Gi"
limits:
cpu: "100m"
memory: "20Gi"
3. 验证结果
查看 Pod:
kubectl -n volcano-demo get pod
输出如下:
NAME READY STATUS RESTARTS AGE
volcano-deploy-gang-5dc6b66cfc-4b597 0/1 Pending 0 7s
volcano-deploy-gang-5dc6b66cfc-tsfnh 0/1 Pending 0 7s
查看 PodGroup:
kubectl -n volcano-demo get podgroup
输出如下:
NAME STATUS MINMEMBER RUNNINGS AGE
podgroup-89bcd154-6137-49f5-9eb6-aaa0f39023fc Pending 2 15s
查看其中一个 Pod:
kubectl -n volcano-demo describe pod volcano-deploy-gang-5dc6b66cfc-4b597
关键输出如下:
Name: volcano-deploy-gang-5dc6b66cfc-4b597
Namespace: volcano-demo
Node: <none>
Labels: app=volcano-deploy-gang
pod-template-hash=5dc6b66cfc
Annotations: scheduling.k8s.io/group-name: podgroup-89bcd154-6137-49f5-9eb6-aaa0f39023fc
Status: Pending
Controlled By: ReplicaSet/volcano-deploy-gang-5dc6b66cfc
Containers:
busybox:
Image: busybox:latest
Limits:
cpu: 100m
memory: 20Gi
Requests:
cpu: 100m
memory: 20Gi
Conditions:
Type Status
PodScheduled False
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 58s volcano pod group is not ready, 2 Pending, 2 minAvailable; Pending: 2 Unschedulable
4. 结果分析
从 Pod 输出可以看到,两个 Deployment Pod 都处于 Pending:
STATUS Pending
该 Deployment 配置了 2 个副本,每个 Pod 申请 20Gi 内存,总共需要 40Gi 内存,而测试环境是 32Gi 单节点集群,无法同时满足两个 Pod 的资源需求。从 PodGroup 输出可以看到:
STATUS Pending
MINMEMBER 2
RUNNINGS
这说明 Volcano 已经为这个 Deployment 自动创建了 PodGroup,并且该 PodGroup 的最小成员数是 2。但是当前没有 Pod 被成功调度,所以 RUNNINGS 为空。
Pod 的 annotation 中有:
scheduling.k8s.io/group-name: podgroup-89bcd154-6137-49f5-9eb6-aaa0f39023fc
这说明该 Pod 已经被 Volcano 关联到了对应的 PodGroup。也就是说,这个 Deployment 创建出来的 Pod 已经不再是单独按普通 Pod 进行调度,而是被纳入 PodGroup 的 Gang Scheduling 逻辑中。
5. 关键字段说明
metadata:
annotations:
scheduling.volcano.sh/group-min-member: "2"
该注解写在 Deployment 的 metadata.annotations 下,用于声明该 Deployment 至少需要 2 个 Pod 作为一组满足调度条件。
普通 Deployment 本身不是 VolcanoJob,因此需要通过这个注解告诉 Volcano:这个普通工作负载也需要按 PodGroup 方式进行成组调度。
spec:
template:
metadata:
annotations:
scheduling.volcano.sh/queue-name: "default"
该注解写在 Pod template 下,用于指定 PodGroup 所属队列。最终创建出来的 Pod 会携带该注解,Volcano 在创建 PodGroup 时会根据该信息设置 queue。
spec:
template:
spec:
schedulerName: volcano
该字段必须写在 Pod 模板中。Deployment 本身不会直接被调度,真正被调度的是 Deployment 创建出来的 Pod。因此,schedulerName: volcano 必须出现在 spec.template.spec 下。
6. 普通 Deployment 的 PodGroup 创建逻辑
普通 Deployment 使用 Volcano Gang Scheduling 的大致流程如下:
Deployment
|
v
ReplicaSet
|
v
Pod
|
v
Volcano PodGroup Controller
|
v
自动创建或更新 PodGroup
|
v
Volcano Scheduler 按 PodGroup 调度
Deployment 并不会直接变成 VolcanoJob。它仍然是 Kubernetes 原生 Deployment。
真正发生的是:
-
Deployment 创建 ReplicaSet;
-
ReplicaSet 创建 Pod;
-
Pod 模板中指定了
schedulerName: volcano; -
Deployment 上配置了
scheduling.volcano.sh/group-min-member; -
Volcano Controller 根据这些信息自动创建 PodGroup;
-
Volcano Scheduler 根据 PodGroup 的
minMember和资源需求进行调度; -
调度成功后,Pod 会绑定到节点;资源不足时,PodGroup 保持 Pending。
从实验中的 Pod annotation 可以看到:
scheduling.k8s.io/group-name: podgroup-89bcd154-6137-49f5-9eb6-aaa0f39023fc
这就是 Volcano 将 Pod 关联到 PodGroup 的结果。
同时,Pod 的 Controlled By 字段显示:
Controlled By: ReplicaSet/volcano-deploy-gang-5dc6b66cfc
说明这个 Pod 的上层控制器仍然是 ReplicaSet。也就是说,Deployment 的工作负载控制逻辑仍然由 Kubernetes 原生控制器负责,Volcano 只负责调度层面的成组调度。
八、核心概念补充
1. VolcanoJob 与 Kubernetes Job 的区别
VolcanoJob 是 Volcano 自定义资源:
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
Kubernetes 原生 Job 是:
apiVersion: batch/v1
kind: Job
两者不是同一种资源。
查看 VolcanoJob:
kubectl get vcjob -n volcano-demo
查看 Kubernetes 原生 Job:
kubectl get job -n volcano-demo
VolcanoJob 更适合批计算、AI 训练、MPI、分布式任务等场景,因为它天然集成了 PodGroup、Queue、Gang Scheduling 等能力。
2. minAvailable 与 replicas 的关系
replicas 表示 task 需要创建多少个 Pod。
minAvailable 表示整个 VolcanoJob 至少需要多少个 Pod 同时满足调度条件。
例如:
tasks:
- replicas: 3
minAvailable: 2
表示该 Job 总共期望创建 3 个 Pod,但至少有 2 个 Pod 可以调度时,Job 就可以进入运行状态。
如果希望所有 Pod 都必须同时满足调度条件,应设置:
minAvailable = 所有 task 的 replicas 总数
例如:
tasks:
- replicas: 2
minAvailable: 2
这表示两个 Pod 必须同时满足调度条件。
3. PodGroup 是 Volcano 调度的关键对象
PodGroup 是 Volcano 成组调度的核心对象,用于描述一组 Pod 的最小运行条件。
核心字段包括:
spec:
minMember: 2
queue: default
minResources:
cpu: "200m"
memory: "128Mi"
字段含义如下:
| 字段 | 说明 |
|---|---|
| minMember | PodGroup 中至少需要多少个 Pod 或 task 运行 |
| queue | PodGroup 所属 Queue |
| minResources | PodGroup 满足最小运行条件所需的资源 |
| priorityClassName | PodGroup 的优先级 |
| status.phase | PodGroup 当前状态 |
PodGroup 的常见状态如下:
| 状态 | 含义 |
|---|---|
| Pending | 已被 Volcano 接收,但资源条件尚未满足 |
| Inqueue | 已通过队列校验,等待调度 |
| Running | 至少已有 minMember 数量的 Pod 正在运行 |
| Unknown | 部分 Pod 运行,部分 Pod 未被调度,通常与资源不足有关 |
4. Gang Scheduling 的本质
Gang Scheduling 不是简单地创建多个 Pod,也不是让多个 Pod 的创建时间尽量接近。
它的核心是调度约束:
达到最小成员数,则整体调度;
达不到最小成员数,则整体等待。
例如,一个训练任务需要 2 个 worker:
replicas: 2
minAvailable: 2
如果资源只够启动 1 个 worker,Volcano 不会只启动其中一个,而是让整个 PodGroup 等待资源满足。
5. Queue capability 与 weight 的区别
capability 是硬约束,表示队列最多可以使用多少资源。
capability:
cpu: "500m"
memory: "512Mi"
超过该上限的任务不应被正常调度。
weight 是软约束,主要用于 proportion 插件计算队列之间的资源分配比例。
weight: 1
当集群资源空闲时,某个队列可能临时使用超过其应得值的资源;当其他队列需要资源时,超额使用的资源可能被回收或重新分配。
6. 普通工作负载使用 Volcano 的必要条件
普通 Deployment、StatefulSet、Kubernetes Job 想使用 Volcano 调度,需要满足以下条件:
第一,Pod 模板中必须指定 Volcano 调度器:
spec:
template:
spec:
schedulerName: volcano
第二,如果希望使用 Gang Scheduling,需要在上层工作负载中配置:
metadata:
annotations:
scheduling.volcano.sh/group-min-member: "2"
第三,如果希望指定 Queue,可以在 Pod 模板中配置:
spec:
template:
metadata:
annotations:
scheduling.volcano.sh/queue-name: "default"
其中最容易遗漏的是 schedulerName: volcano。如果不写这个字段,Pod 不会交给 Volcano Scheduler 调度,group-min-member 也就无法真正体现 Volcano 的 Gang Scheduling 效果。
九、总结
本文主要验证了 Volcano 的几个基础能力。
第一,Volcano 可以通过 Helm 快速部署,核心组件包括 volcano-scheduler、volcano-controllers、volcano-admission。
第二,VolcanoJob 使用的是 Volcano 自定义 CRD:
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
它与 Kubernetes 原生 Job 不是同一个资源。
第三,Gang Scheduling 的核心是 PodGroup。对于 VolcanoJob,通常通过 minAvailable 控制最小可运行 Pod 数;对于 PodGroup,则对应 minMember。
第四,Queue 可以用于队列级资源管理。其中 capability 是资源上限,属于硬约束;weight 用于资源比例划分,属于软约束。
第五,普通 Deployment、StatefulSet、Kubernetes Job 也可以使用 Volcano 调度。如果希望普通工作负载使用 Volcano Gang Scheduling,需要同时配置:
scheduling.volcano.sh/group-min-member: "2"
以及:
schedulerName: volcano
其中,group-min-member 用于声明最小成组调度数量,schedulerName: volcano 用于确保 Pod 交给 Volcano Scheduler 调度。两者缺一不可。
整体来看,Volcano 的核心价值不是简单地提供一个新的 Job 类型,而是为 Kubernetes 增强了批处理、成组调度和队列资源管理能力。对于 AI 训练、大数据计算、HPC 等场景,Volcano 能够更好地表达“任务组整体运行”的调度语义,避免只启动部分 Pod 导致任务无法运行和资源浪费。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)