3. Volcano核心概念与API对象

Volcano 的调度能力并不是直接作用在单个 Pod 上,而是通过一组自定义资源(CRD)把“批量作业”的语义显式建模出来。理解 Queue、PodGroup、Job、JobFlow 这四类对象,以及它们之间的引用关系和生命周期,是后续做队列配额、gang 调度、作业编排和故障排查的基础。可以把它们理解为四个层次:Queue 管资源池与配额,PodGroup 管一组 Pod 的调度单元与 gang 约束,Job 管一类批处理作业的完整生命周期,JobFlow 管多个 Job 之间的依赖与编排。

Queue:资源池、配额与调度优先级

Queue 是 Volcano 中的资源队列,属于集群级资源(cluster-scoped)。它把一个物理集群划分成多个逻辑资源池,每个队列可以设置权重、资源上限和应得资源。调度器在为 PodGroup 分配资源时,会先看它属于哪个 Queue,再在该 Queue 的配额范围内做分配。Queue 的核心字段包括:

  • spec.weight:队列权重,用于在多个队列竞争空闲资源时按比例分配,权重越大分到的资源越多。
  • spec.capability:队列可使用的资源上限,例如 cpu: 20、memory: 40Gi,超过上限的 PodGroup 不会被调度。
  • spec.guarantee:队列的保障资源,即无论其他队列如何竞争,该队列至少能拿到的资源量。
  • spec.deserved:应得资源,通常由权重和总资源计算得出,用于描述队列“理论上应分到多少”。
  • status.state:队列状态,常见为 Open、Closed、Unknown;Closed 时不再接受新的 PodGroup 入队。

Queue 的生命周期相对简单:创建后处于 Open 状态,可被 PodGroup 引用;当管理员将其置为 Closed 时,已有作业继续运行,但新作业无法入队;删除 Queue 前需要确保没有 PodGroup 仍在引用它,否则相关作业会因找不到队列而无法调度。

PodGroup:调度的最小单元与 gang 约束

PodGroup 是 Volcano 调度的核心对象,它把一组需要“同生共死”的 Pod 聚合为一个调度单元。PodGroup 通常由 Job 控制器自动创建,也可以手动创建。它的关键字段包括:

  • spec.minMember:最小成员数,即 gang 调度要求同时满足的最少 Pod 数量。只有可调度的 Pod 数达到 minMember,整组才会被调度,否则全部等待。
  • spec.minTaskMember:按任务类型细分的最小成员数,用于多角色作业(如 master/worker)分别约束。
  • spec.queue:指定该 PodGroup 所属的 Queue 名称,决定它使用哪个资源池和配额。
  • spec.priorityClassName:优先级类,影响抢占和调度顺序。
  • status.phase:PodGroup 阶段,常见为 Pending、Running、Completed、Failed。
  • status.running / status.succeeded / status.failed:各状态下的 Pod 计数。

PodGroup 的生命周期与 gang 调度强相关:创建后进入 Pending,调度器持续尝试凑齐 minMember;一旦满足,整组进入 Running;当所有 Pod 成功结束,PodGroup 变为 Completed;若有 Pod 失败且无法恢复,则变为 Failed。理解 minMember 与 status.running 的差值,是判断“作业为什么一直不启动”的关键。

Job:面向批处理作业的控制器对象

Volcano 的 Job 是一种批处理作业抽象,它负责创建和管理一组 Pod,并自动生成对应的 PodGroup。Job 的字段设计围绕“作业完成”展开:

  • spec.schedulerName:必须指定为 volcano,否则 Pod 不会被 Volcano 调度。
  • spec.minAvailable:作业可运行所需的最小可用副本数,直接映射到 PodGroup 的 minMember。
  • spec.parallelism:允许同时运行的 Pod 数量上限,用于控制并发度。
  • spec.completions:作业成功完成所需的 Pod 总数。
  • spec.tasks:任务模板列表,每个任务可指定副本数、模板、策略等,支持多角色作业。
  • spec.policies:生命周期策略,例如 Event: PodFailed, Action: AbortJob,用于定义失败时的处理动作。
  • status.state:作业状态,常见为 Pending、Running、Completed、Failed、Aborted。

Job 的生命周期可以概括为:提交后创建 PodGroup 并进入 Pending;调度器满足 minAvailable 后转为 Running;当成功完成的 Pod 数达到 completions 时转为 Completed;若触发失败策略或超过重试上限,则转为 Failed 或 Aborted。Job 控制器会持续同步 Pod 状态到 Job 的 status 中,因此排查时应同时查看 Job 与 PodGroup 的状态。

JobFlow:多 Job 依赖编排

JobFlow 用于描述多个 Job 之间的依赖关系,适合流水线式批处理场景。它通过 spec.flows 定义一组 Job 模板及其依赖,通过 spec.jobRetainPolicy 控制 Job 完成后是否保留。JobFlow 会按依赖顺序依次创建和运行 Job,前序 Job 成功后才触发后续 Job。其状态字段 status.state 反映整体流程进展,常见为 Running、Completed、Failed。JobFlow 的价值在于把“作业之间的先后依赖”从人工脚本提升为平台级编排对象。

Volcano 核心对象:引用关系与生命周期 Queue weight / capability guarantee / deserved state: Open / Closed PodGroup minMember / queue priorityClassName phase: Pending→Running Job minAvailable / tasks completions / policies state: Pending→Completed spec.queue 引用 自动创建 / 管理 JobFlow spec.flows 依赖定义 jobRetainPolicy state: Running→Completed 编排多个 Job 典型生命周期(以 Job + PodGroup 为例) 提交 Pending Running Completed 满足 minMember 才进入 Running; 成功数达到 completions 才 Completed。

四类对象的协作关系与排查要点

从引用关系看,Job 通过 spec.minAvailable 和 spec.tasks 生成 PodGroup,PodGroup 通过 spec.queue 绑定 Queue,JobFlow 则通过 spec.flows 编排多个 Job。调度器只认 PodGroup 和 Queue,因此当作业不调度时,排查顺序建议是:先看 Job 的 status.state 是否 Pending,再看 PodGroup 的 status.running 是否达到 minMember,最后看 Queue 的 capability 是否已被占满或 state 是否为 Closed。下面给出一个可直接参考的 Job 示例片段:

apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: demo-job
spec:
  schedulerName: volcano
  minAvailable: 2
  queue: research
  tasks:
    - replicas: 2
      name: worker
      template:
        spec:
          containers:
            - name: c
              image: busybox
              command: ["sh", "-c", "echo hello && sleep 30"]
  policies:
    - event: PodFailed
      action: AbortJob

该示例中,minAvailable: 2 表示至少 2 个 Pod 同时可调度才会启动,queue: research 表示使用 research 队列的配额,policies 表示任一 Pod 失败即中止整个作业。提交后可用 kubectl get podgroup 观察 PodGroup 的 phase 与 running 计数,用 kubectl get queue research -o yaml 查看队列的 capability 与 deserved 是否满足需求。若 PodGroup 长期 Pending 且 running 为 0,通常说明队列配额不足或 minMember 设置过大;若 running 达到 minMember 但 Job 仍不 Running,则应检查 Pod 模板本身是否可调度。

Queue 是集群级对象,PodGroup 和 Job 是命名空间级对象;JobFlow 也是命名空间级对象。跨命名空间引用 Queue 时,只需写队列名,不需要命名空间前缀。