HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于

Volcano:AI 场景的批处理调度器

K8s 原生调度器是为微服务设计的,对 AI 任务支持不好。

Volcano 是华为开源的批处理调度器,专门解决 AI/大数据场景的调度问题。


K8s 原生调度的问题

问题一:没有 Gang Scheduling

分布式训练需要多个 Pod 同时启动:

8 卡训练任务:需要 8 个 Pod 同时运行

K8s 原生调度:
- Pod 1 调度成功 ✓
- Pod 2 调度成功 ✓
- ...
- Pod 5 调度成功 ✓
- Pod 6 调度失败 ✗(没资源了)

结果:5 个 Pod 在跑,等 Pod 6
但 Pod 1-5 没法开始训练,因为差一个
→ 资源浪费

这叫「部分调度」问题。正确的做法是:要么 8 个都能调度,要么一个都不调度。

问题二:没有队列管理

多个团队共享 GPU 集群:

团队A 提交 100 个任务
团队B 提交 100 个任务

K8s 原生:先到先得,谁提交快谁先跑
没有公平性保证,没有优先级控制

问题三:没有抢占策略

低优先级任务占着 GPU,高优先级任务进不来。

K8s 有 PriorityClass,但抢占逻辑对批处理任务不够智能。

问题四:不感知拓扑

分布式训练希望 Pod 在同一节点或同一机架:

8 卡训练最好在同一台机器(走 NVLink)
跨机器通信慢(走网络)

K8s 原生调度不考虑这个

Volcano 是什么

Volcano 是 CNCF 的孵化项目,专门为批处理、AI、大数据设计的调度器。

核心功能:

  • Gang Scheduling(组调度)
  • Queue 管理
  • 公平调度
  • 抢占
  • 拓扑感知
  • 资源预留

安装 Volcano

# 方式一:kubectl
kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development.yaml

# 方式二:Helm
helm repo add volcano-sh https://volcano-sh.github.io/helm-charts
helm install volcano volcano-sh/volcano -n volcano-system --create-namespace

验证

kubectl get pods -n volcano-system

# 应该看到:
# volcano-admission
# volcano-controllers
# volcano-scheduler

核心概念

Job

Volcano 的 Job(不是 K8s 的 Job):

apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: pytorch-job
spec:
  minAvailable: 8  # 最少需要 8 个 Pod 才能开始
  schedulerName: volcano
  queue: default

  tasks:
  - replicas: 8
    name: worker
    template:
      spec:
        containers:
        - name: pytorch
          image: pytorch/pytorch:latest
          resources:
            limits:
              nvidia.com/gpu: 1

关键字段:

  • minAvailable:Gang Scheduling 的核心,必须凑够才能调度
  • schedulerName: volcano:使用 Volcano 调度器
  • queue:提交到哪个队列

Queue

资源队列,用于多租户管理:

apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
  name: team-a
spec:
  weight: 2  # 权重,用于公平调度
  capability:
    cpu: 100
    memory: 200Gi
    nvidia.com/gpu: 16  # 队列最多用 16 张 GPU

PodGroup

一组需要一起调度的 Pod:

apiVersion: scheduling.volcano.sh/v1beta1
kind: PodGroup
metadata:
  name: training-group
spec:
  minMember: 8  # 最少 8 个 Pod
  queue: default

Job 会自动创建 PodGroup,也可以手动创建给普通 Pod 用。


Gang Scheduling

工作原理

提交 8 Pod 的 Job(minAvailable=8)
       ↓
Volcano 检查:能否一次性调度 8 个 Pod?
       ↓
可以 → 全部调度,Job 开始运行
不可以 → 全部不调度,等待资源

配置示例

apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: distributed-training
spec:
  minAvailable: 4  # 至少 4 个 Pod

  policies:
  - event: PodEvicted
    action: RestartJob  # Pod 被驱逐时重启整个 Job

  tasks:
  - replicas: 4
    name: worker
    template:
      spec:
        containers:
        - name: worker
          image: training:latest
          resources:
            limits:
              nvidia.com/gpu: 1

部分调度场景

有时候不需要全部 Pod:

spec:
  minAvailable: 6  # 8 个里面来 6 个就能跑
  tasks:
  - replicas: 8

队列管理

创建队列

apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
  name: high-priority
spec:
  weight: 4
  capability:
    nvidia.com/gpu: 32

---
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
  name: low-priority
spec:
  weight: 1
  capability:
    nvidia.com/gpu: 16

提交到队列

apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: my-job
spec:
  queue: high-priority  # 指定队列
  # ...

队列优先级

权重高的队列优先分配资源:

high-priority (weight=4):分到 80% 资源
low-priority (weight=1):分到 20% 资源

调度策略

Volcano 支持多种调度插件:

Gang

Gang Scheduling 插件,前面讲过。

Priority

按优先级调度:

spec:
  priorityClassName: high-priority

DRF(Dominant Resource Fairness)

公平调度算法,保证各队列公平使用资源。

Binpack

尽量把 Pod 调度到同一节点,提高资源利用率。

Nodeorder

考虑节点拓扑,优先调度到更近的节点。

配置调度策略

# volcano-scheduler-configmap
apiVersion: v1
kind: ConfigMap
metadata:
  name: volcano-scheduler-configmap
  namespace: volcano-system
data:
  volcano-scheduler.conf: |
    actions: "enqueue, allocate, backfill"
    tiers:
    - plugins:
      - name: priority
      - name: gang
      - name: conformance
    - plugins:
      - name: drf
      - name: predicates
      - name: nodeorder
      - name: binpack

抢占

配置抢占

apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: urgent-job
spec:
  priorityClassName: high-priority
  preemptable: false  # 不可被抢占

  tasks:
  - replicas: 4
    name: worker
    # ...

抢占策略

# 被抢占时的行为
policies:
- event: PodEvicted
  action: RestartJob  # 重启整个 Job
  # 或 action: AbortJob  # 终止 Job

与训练框架集成

PyTorch 分布式训练

apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: pytorch-distributed
spec:
  minAvailable: 4
  schedulerName: volcano
  plugins:
    env: []
    svc: []

  tasks:
  - replicas: 4
    name: worker
    policies:
    - event: TaskCompleted
      action: CompleteJob
    template:
      spec:
        containers:
        - name: pytorch
          image: pytorch/pytorch:latest
          command:
          - python
          - -m
          - torch.distributed.launch
          - --nproc_per_node=1
          - --nnodes=4
          - --node_rank=$(VK_TASK_INDEX)
          - --master_addr=$(MASTER_ADDR)
          - --master_port=23456
          - train.py
          resources:
            limits:
              nvidia.com/gpu: 1

Kubeflow 集成

Volcano 可以作为 Kubeflow Training Operator 的调度器:

# PyTorchJob
apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
  name: pytorch-job
spec:
  pytorchReplicaSpecs:
    Worker:
      replicas: 4
      template:
        spec:
          schedulerName: volcano  # 使用 Volcano
          containers:
          - name: pytorch
            # ...

监控

查看队列状态

kubectl get queue

# NAME           STATE   INQUEUE   PENDING   RUNNING   UNKNOWN
# default        Open    0         0         4         0
# high-priority  Open    2         1         8         0

查看 Job 状态

kubectl get vcjob

# NAME                 STATUS    MINAVAILABLE   RUNNINGS
# pytorch-job          Running   8              8

Prometheus 指标

Volcano 暴露 Prometheus 指标:

volcano_queue_allocated_gpu
volcano_queue_pending_gpu
volcano_job_status_count

小结

Volcano 解决的问题:

问题K8s 原生Volcano
Gang Scheduling不支持支持
队列管理简单完善
公平调度无DRF
抢占简单灵活
拓扑感知无支持

使用场景:

  • 分布式训练
  • 批处理任务
  • 多租户 GPU 集群
  • 需要资源公平的场景

核心概念:

  • Job:批处理任务
  • Queue:资源队列
  • PodGroup:组调度单位
  • minAvailable:Gang Scheduling 的关键

下一篇讲 GPU 切分:MIG、MPS、vGPU。