lolspider / notes
Clipping · 4 分钟

Volcano 调度框架深度解读

Volcano 调度框架深度解读

调研日期: 2026-07-01 | 版本: v1.15.0 (2026-06) | 置信度: 全部 findings 经 3-vote 对抗验证,均 High confidence 官方站点: volcano.sh | GitHub: volcano-sh/volcano

一、项目概览与 CNCF 状态

Volcano 是 CNCF 孵化项目(2022-03-21 从 Sandbox 升级至 Incubator,截至 v1.15.0 尚未毕业)。其调度器基于 kube-batch 构建——后者已归档并由 Volcano 接续演进。架构上与默认 kube-scheduler 完全独立,是专为批处理工作负载设计的独立调度框架。

核心定位: 为 AI/ML 训练、大数据等批处理场景提供 Kubernetes 原生的 gang scheduling、层级队列管理和可扩展调度能力。

三大组件部署(volcano-system namespace):

  • volcano-admission — webhook 准入控制
  • volcano-controllers — CRD 控制器(Job、PodGroup、Queue)
  • volcano-scheduler — 批调度器核心

🔗 Sources: CNCF Projects, CNCF Blog 2022, GitHub README


二、调度架构:Action × Plugin 可扩展框架

Volcano 调度器将 Action(定义调度流程步骤)与 Plugin(提供算法决策逻辑)分离,两者均可通过注册接口自定义实现(RegisterAction、RegisterPluginBuilder)。

graph TD
    subgraph Actions["Actions - 调度流程步骤"]
        A1[enqueue] --> A2[allocate]
        A2 --> A3[preempt] --> A4[reclaim] --> A5[backfill]
        A3a[gangpreempt]
        A4a[gangreclaim]
        A5a[shuffle]
    end
    subgraph Plugins["Plugins - 算法决策逻辑"]
        P1[DRF]
        P2[Gang]
        P3[Priority]
        P4[QueueOrder]
        P5[NodeOrder]
        P6[Predicate]
        P7[Proportion]
    end
    Actions -.-> Plugins

⚠️ 验证修正: 官方设计文档早期仅描述 4 个 action(allocate, preempt, reclaim, backfill),但当前源码 pkg/scheduler/actions/factory.go 注册了 8 个 action: enqueue, allocate, backfill, preempt, reclaim, gangpreempt, gangreclaim, shuffle。5 个核心 action 按顺序执行:enqueue → allocate → preempt → reclaim → backfill。

核心概念:

  • Action: 定义每一步"做什么"(如 enqueue 将 Job 放入 Queue,allocate 绑定 Pod 到 Node)
  • Plugin: 定义每一步"怎么做"(如 Gang plugin 提供 PreemptableFn 判断驱逐是否安全)

调度 Session 生命周期:

  1. OnSessionOpen — 初始化 plugin 状态
  2. 依次执行各 action(action 调用 plugin 注册的函数)
  3. OnSessionClose — 清理 session

🔗 Sources: Scheduler Plugins Docs, Interface.go, Plugins.go


三、PodGroup — Gang Scheduling 的实现

3.1 CRD 定义

PodGroup 是 scheduling.volcano.sh/v1beta1 API 组下的 CRD,是实现 gang scheduling 的核心机制。

yaml
apiVersion: scheduling.volcano.sh/v1beta1
kind: PodGroup
spec:
  minMember: 4          # 最少需同时运行的 Pod 数
  priorityClassName: "" # PodGroup 优先级排序
  queue: default        # 所属队列

3.2 Gang Scheduling 语义

All-or-Nothing: 如果集群资源无法同时容纳至少 minMember 个 Pod,则该 PodGroup 中的 所有 Pod 都不会被调度。这避免了批处理任务的部分执行(如分布式训练仅启动部分 worker)。

flowchart LR
    A["PodGroup 提交"] --> B{"集群资源 >= minMember?"}
    B -->|Yes| C["全部 Pod 度启动"]
    B -->|No| D["全部 Pod 等待"]
    C --> E{"运行 Pod >= minAvailable?"}
    E -->|Yes| F["正常运行"]
    E -->|No 抢占或故障| G["Job 标记 Inqueue 等待资源恢复"]

3.3 优先级与抢占保护

  • priorityClassName 字段在 Queue 内对 PodGroup 排序,用于抢占优先级调度
  • 保留值 system-node-critical 和 system-cluster-critical 代表最高优先级
  • Gang 抢占保护: Gang plugin 的 PreemptableFn 会阻止驱逐导致运行 Pod 数低于 minAvailable 的任务

🔗 Sources: PodGroup Docs, CRD YAML, Types.go


四、队列管理 — 层级公平分配

4.1 权重公平分配公式

Volcano 使用基于权重的公平资源分配:

deserved=weighttotal_weight×total_resource\text{deserved} = \frac{\text{weight}}{\text{total\_weight}} \times \text{total\_resource}

4.2 三级资源模型

每个 Queue 有三个资源层级配置:

层级 含义 特性
guarantee 保留资源 独享,不借出
deserved 软配额 可借出,但当需求上升时可 reclaim 回来
capability 硬上限 Queue 不可超过此上限

推荐顺序: guarantee ≤ deserved ≤ capability

4.3 Reclaimable 与超额惩罚

  • reclaimable=false: 阻止其他 Queue reclaim 该 Queue 的超额资源
  • 超额惩罚: Queue 的 Allocated > Deserved 时,失去对其他 Queue 的 reclaim 权利(AddPreemptiveFn 检查 Queue.Allocated >= Queue.Deserved 阻止 reclaim;AddReclaimableFn 选择 victim 时优先选 queue.Allocated > Queue.Deserved 的任务)
flowchart TB
    Total["总资源: 20 CPU"] --> QA["Queue A weight=30<br>guarantee=2 / deserved=6 / cap=10<br>allocated=8 超额 无reclaim权"]
    Total --> QB["Queue B weight=70<br>guarantee=4 / deserved=14 / cap=20<br>allocated=10 可reclaim A超额"]

🔗 Sources: Queue Docs, Queue Resource Management, Capacity Scheduling Design


五、Reclaim vs Preempt — 双轨抢占机制

Volcano 明确区分两种抢占,源码级强制隔离:

维度 Reclaim Preempt
范围 跨队列(cross-queue) 同队列内(intra-queue)
触发 Queue 的 allocated 超过 deserved 时 高优先级 Job 需要资源时
victim 选择 j.Queue != job.Queue job.Queue == preemptorJob.Queue
考虑因素 超额程度 + 队列/Job 优先级 Job 优先级 + Task 优先级
flowchart LR
    subgraph Reclaim["Reclaim - 跨队列"]
        R1["Queue B 不足"] --> R2["选择 Queue A 中 allocated > deserved 的任务"] --> R3["驱逐后资源归还 Queue B"]
    end
    subgraph Preempt["Preempt - 同队列内"]
        P1["高优先级 Job 入队"] --> P2["选择同 Queue 内低优先级 Job 的任务"] --> P3["驱逐后资源给高优先级 Job"]
    end

🔗 Sources: Queue Resource Management Docs, reclaim.go, preempt.go


六、Gang-Aware Preemption — v1.15.0 关键演进

6.1 问题:默认抢占是 Gang-Blind 的

Volcano 的默认抢占策略是 node-first(先选 Node,再选驱逐哪些 Task),不考虑 gang/PodGroup 边界。结果是:

  • 驱逐 victims 可能跨越多个 Job
  • Gang plugin 只充当"护栏"(threshold check),而非 gang-aware 的 victim 选择策略
  • 对 AI/ML 工作负载尤其不利——分布式训练的部分 Pod 驱逐可能导致整个 Job 回退

6.2 PR #4637 — 三种 Gang-Aware 模式

v1.15.0 合入的 PR #4637 通过 volcano-scheduler-configmap 引入三种可配置模式:

模式 常量 行为
off (默认) GPModeOff 保持当前 node-first 行为,向后兼容
minimal GPModeMinimal 按 gang 分组 preemptable tasks per node,偏好单 gang fit
atomic GPModeAtomic 集群级 gang 驱逐——选中 victim gang 时,跨所有 Node 驱逐该 gang 的全部 tasks
yaml
# volcano-scheduler-configmap 配置示例
apiVersion: v1
kind: ConfigMap
data:
  volcano-scheduler.conf: |
    actions: "enqueue, allocate, preempt, reclaim, backfill"
    tiers:
    - plugins:
      - name: gang
        arguments:
          gangPreemptionMode: minimal  # off | minimal | atomic

⚠️ 重要: gang-aware 模式需要显式配置启用,默认仍为 node-first。AI/ML 场景建议启用 minimal 或 atomic 模式。

🔗 Sources: PR #4637, Preempt-action Design Doc, preempt.go


七、与默认 kube-scheduler 的对比

维度 kube-scheduler Volcano
调度粒度 单 Pod PodGroup (gang)
队列 PriorityClass + Namespace 层级 Queue + 权重公平分配
抢占 单 Pod preempt reclaim (跨队列) + preempt (同队列) + gang-aware
扩展方式 Scheduler Framework (Extender) Action + Plugin 注册
批处理支持 无原生 gang scheduling PodGroup CRD 全有全无
资源公平性 PriorityClass 粗粒度 DRF/Proportion 权重公平
适用场景 通用微服务 AI/ML 训练、大数据、批处理

八、实际应用场景

AI/ML 训练

  • 分布式训练: PodGroup gang scheduling 确保 all-or-nothing,避免部分 worker 启动浪费 GPU
  • GPU 共享: 配合 HAMi(CNCF Sandbox)实现多厂商 GPU 切分,Volcano 负责 batch 层调度
  • KServe + Volcano: Kserve LLM 路由场景中,Volcano 作为 batch 层调度器

大数据

  • Spark on Volcano: 社区有成熟的 Spark 集成方案,PodGroup 保证 Executor 全部启动
  • Flink on Volcano: 类似 gang scheduling 保证

其他

  • MPI/HPC: gang scheduling 天然适配 MPI 任务的 all-or-nothing 需求
  • CI/CD batch: Queue 权重分配确保不同团队的构建公平性

九、关键 CRD 速查

CRD API Group 核心字段
PodGroup scheduling.volcano.sh/v1beta1 minMember, priorityClassName, queue, minAvailable
Queue batch.volcano.sh/v1beta1 weight, guarantee, deserved, capability, reclaimable
Job (VCJob) batch.volcano.sh/v1beta1 tasks[], minAvailable, schedulerName, priorityClassName

十、相关生态与延伸阅读


📋 调研方法: deep-research 工作流 — 5 角度并行搜索 → 15+ 源抓取 → 6 falsifiable claims → 每 claim 3-vote 对抗验证(≥2/3 refutes 即 kill)→ 最终 6/6 claims 全部 High confidence 存活