想象一座超级枢纽机场。老塔台只关心一位旅客有没有过安检,然后放他登机;它完全不看这架航班一共有多少人。于是只来了两位旅客的航班也可能被放行,到了跑道上发现机组不齐,只能又滑回去。AI 集群里的默认 Kubernetes 调度器就有点像这个老塔台:它一次只调度一个 Pod,并不关心这批 Pod 是不是同一个任务的一部分。Volcano 就是一座更聪明的新塔台——它把一批 Pod 看成“一个航班”,只在全体乘客都到齐时才放行,同时用队列公平保障不同航司不被挤兑。这篇文章会用“航班与塔台”的比喻,带你从零看懂 Volcano 如何实现批调度、Gang 调度和队列公平,以及如何在 Kubernetes 上落地。

岗位关联

学会 Volcano,你就能在 Kubernetes 上高效运行分布式训练和大数据任务,成为团队里既懂资源调度、又懂用户体验的 AI 平台工程师。

目录
  1. 可视化演示
  2. 调度器定位:新塔台接管旧流程
  3. 核心对象:登机名单、航班时刻表与候机楼
  4. Gang 调度:全员到齐才起飞
  5. 队列公平:候机楼按配额分流
  6. 插件机制:塔台岗位流水线
  7. 配置实践:把航班计划写进 YAML
  8. AI 训练应用:让集群飞得更满
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示Volcano批调度核心机制:Gang调度演示All-or-Nothing的Pod组同时调度;四层架构展示调度器/动作/插件/缓存的分层协作;队列管理展示DRF公平调度与资源分配。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Gang调度机制 All-or-Nothing→Pod组同时调度 Gang minAvailable满足时Pod组原子调度

调度器定位:新塔台接管旧流程

想象一座超级枢纽机场。老塔台只关心每一位旅客是否通过安检,然后放他上飞机,完全不看这架航班一共有多少人。于是只来了两位旅客的航班也可能被放行,结果到了跑道发现机组不齐,只能又滑回去。AI 集群里的默认 kube-scheduler 就有点像这个老塔台:它一次只调度一个 Pod,并不知道这个 Pod 和哪个兄弟 Pod 属于同一个训练任务。

Volcano 就是那个新塔台。它并不是要拆掉机场,而是给 Kubernetes 装上更聪明的调度系统。当你把任务交给 Volcano 时,它会把一批 Pod 看成“一个航班”,统一决定是否放行。这特别适合 AI 训练、大数据分析和 HPC 场景——这些任务有一个共同点:要么一组计算节点一起到位,效率才最高;单个 Pod 先到只会空等,浪费资源还容易超时。

技术上讲,Volcano 是 Kubernetes 原生批处理调度器。它通过自定义资源对象(CRD)描述任务和队列,用 “actions + plugins“ 的模式来调度。简单说,action 定义”处理流程“,plugin 定义”每一步怎么判断“。所以 Volcano 的调度决策可以抽象成:输入航班计划、候机区和跑道资源,输出”放行“或”等待”。

这座新塔台并不是万能的,它把规则开放给了我们:你可以决定放行流程、队列权重和最少登机人数。接下来我们就去看看这些规则分别是什么。

Schedule(PodGroup,Queue,R)→{allocated,pending}\displaystyle \text{Schedule}(\text{PodGroup}, \text{Queue}, R) \to \{\text{allocated}, \text{pending}\}
公式的意思是:调度器像塔台,输入一组 Pod、一个队列和集群资源,最终只会给出两个答案——放行或等待,不会出现“放行一半”。
  1. 输入对象PodGroup 描述一组需要一起调度的 Pod,Queue 描述它们属于哪个候机区,R 表示集群当前可用资源。
    input=(G,Q,R)\text{input} = (G, Q, R)
  2. 调度约束调度器会检查 Gang 调度、队列公平等约束是否满足,这些约束由插件逐项判断。
    cons(G,Q,R)∈{true,false}\text{cons}(G, Q, R) \in \{\text{true}, \text{false}\}
  3. 输出决策约束全部满足就整体放行,否则整个组保持 Pending。
    result∈{allocated,pending}\text{result} \in \{\text{allocated}, \text{pending}\}

核心对象:登机名单、航班时刻表与候机楼

机场里每个航班都有一张登机名单。名单上的每一位旅客是一个 Pod,整张名单就是一个 PodGroup。如果没有名单,塔台就不知道谁应该跟谁一起走。在 Volcano 中,PodGroup 是调度的最小单位,它把多个 Pod 卷进同一个逻辑组,调度器只对“整组”做决定。

除了 PodGroup,Volcano 向上还定义了 Volcano Job(也叫 vcjob),它像航空公司发布的航班时刻表。vcjob 里面写清楚这趟任务有几个角色,比如 Worker 和 Parameter Server;每个角色要创建多少个副本;以及最少需要同时上线多少人,也就是 minAvailable。调度器收到 vcjob 后,会先把它解析成 PodGroup 和一组 Pod,再交给调度流程。

实际使用时,你会在 vcjob 的 spec 里声明 queue 指向某个队列,声明 schedulerName: volcano 表示交给新塔台,并设置 minAvailable。Volcano 只有当组内 “就绪的 Pod 数量” 不小于 minAvailable 时,才认为这个航班可以安排起飞。这个数字就是班机放行的最低门槛。

登机名单和时刻表只是把“谁和谁一起飞”说清楚了,真正让所有旅客必须同时登机的,是下一节要讲的 Gang 调度。

nready=∑t∈Job1ready(t)⇒nready≥minAvailable\displaystyle n_{\text{ready}} = \sum_{t \in \text{Job}} \mathbb{1}_{\text{ready}}(t) \quad \Rightarrow \quad n_{\text{ready}} \geq \text{minAvailable}
公式表示:先把 Job 中所有状态为 Ready 的 Pod 数加起来,再看这个数是否达到最少放行人数。达不到就整组等待。
  1. 统计就绪成员对 Job 里每个 Pod 做一个“是否就绪”的计数,就绪记 1,不就绪记 0。
    nready=∑t∈Job1ready(t)n_{\text{ready}} = \sum_{t \in \text{Job}} \mathbb{1}_{\text{ready}}(t)
  2. 比较门槛将统计结果与 minAvailable 比较,只有满足大于等于关系才会触发后续调度。
    nready≥minAvailablen_{\text{ready}} \geq \text{minAvailable}

Gang 调度:全员到齐才起飞

为什么一定要全员到齐?想象一架国际航班,如果只登机一半乘客就起飞,到了目的地旅客没有对应的服务和接驳,整趟旅程都会乱套。分布式训练也是这个道理:分布式训练任务通常由多个 Worker 和参数服务器组成,它们必须同时在线,才能开始梯度同步;如果只启动一半,先起来的进程只能空等,甚至卡死在初始化阶段。

Gang 调度(也叫组调度)的核心思想就是“全有或全无”:调度器在同一轮决策里,检查一个 PodGroup 需要的所有资源。如果整个组需要的资源都能满足,就把组内所有 Pod 一次性放行;如果有一个 Pod 的资源不满足,整个组都保持 Pending,绝不放行一半。这个机制把“零零散散”变成了“整整齐齐”。

这里有同学会问:Pending 是不是失败了?不是。Pending 只是“航班在候机楼排队等机组成员到齐”。Volcano 通过 gang 插件实现这种等待逻辑,开启它的钥匙就是 minAvailable。当任务无法一次性满足时,整个 PodGroup 会停留在调度器队列中,直到资源凑齐。

Gang 调度保证了每个航班“整整齐齐起飞”,但机场里有很多航班同时等跑道,该先放行哪一架?这就需要队列公平站出来。

Gang(G)={allocate(G),∑p∈Grequest(p)≤Ravailwait(G),otherwise\displaystyle \text{Gang}(G) =\begin{cases}\text{allocate}(G), & \displaystyle \sum_{p \in G} \text{request}(p) \leq R_{\text{avail}} \\\text{wait}(G), & \text{otherwise}\end{cases}
这段公式是 Gang 调度的灵魂:把组内所有 Pod 的资源请求加起来,跟集群剩余资源比一比,够就整体分配,不够就整体等待。
  1. 累加资源请求把 PodGroup 中每个 Pod 请求的 CPU、内存或 GPU 数量加起来,得到这个航班的总需求。
    RG=∑p∈Grequest(p)R_G = \sum_{p \in G} \text{request}(p)
  2. 比较可用资源将总需求与集群当前可分配资源比较,如果总需求更小,说明跑道够用。
    RG≤Ravail⇒allocate(G)R_G \le R_{\text{avail}} \Rightarrow \text{allocate}(G)
  3. 整体等待否则只要有一个 Pod 的资源不满足,就返回 wait,整组继续排队。
    RG>Ravail⇒wait(G)R_G > R_{\text{avail}} \Rightarrow \text{wait}(G)

队列公平:候机楼按配额分流

机场不可能只有一个航司。不同航司航班量不同,机场会按合同约定给各家分配停机位和登机口,而不是谁嗓门大谁先上。Volcano 的 Queue 就是这个“候机楼”概念:每个任务进入一个队列,队列有自己的权重,多个队列共享同一片集群资源。

队列公平调度由 proportion 插件负责。它不按绝对数量分资源,而是看“已用资源 ÷ 权重”这个比值。比值越低,说明这个队列用得越少,调度器会让它优先获得资源。这就是加权公平排队:权重大的队列能在总量上拿到更多资源,但权重小的队列也不会被饿死。

举个例子:队列 A 权重 2,队列 B 权重 1,总资源 10,那么 A 的公平份额是 6.67,B 是 3.33。如果 B 目前只用了一半份额,A 用了超额资源,那么调度器会先抑制 A 的新任务,把空出来的资源让给 B。你也可以用 capability 给队列设置硬性上限,相当于航司停机位数量封顶,避免一个队伍挤占整座机场。

队列公平让不同团队共享 GPU 时心里有数。但塔台内部到底靠什么完成这些判断?答案是插件机制。

si=min⁡(capi,wi∑jwj×Rtotal)\displaystyle s_i = \min\left( \text{cap}_i, \frac{w_i}{\sum_j w_j} \times R_{\text{total}} \right)
公式表示:一个队列的最终可用份额是“权重占比算出的公平份额”和“队列容量上限 cap”两者中较小的那个。上限保护了全局公平。
  1. 计算总权重把所有队列的权重相加,得到分母,代表所有航司的合同权重总和。
    W=∑jwjW = \sum_j w_j
  2. 计算公平份额用该队列权重除以总权重,再乘总资源,得到理论应得资源。
    fi=wiW×Rtotalf_i = \frac{w_i}{W} \times R_{\text{total}}
  3. 套上容量上限如果理论份额超过该队列的容量上限,则只能取上限值,防止单个队列失控。
    si=min⁡(capi,fi)s_i = \min(\text{cap}_i, f_i)

插件机制:塔台岗位流水线

塔台从来不是一个人,而是一套岗位流水线:广播通知、安检、登机、行李托运、跑道放行,每个岗位负责一个环节。Volcano 也把调度过程拆成了 actions 和 plugins 两个层次。action 是“流程步骤”,plugin 是“每个步骤的详细规则”。

常见的 action 包括:enqueue 把任务放入队列,allocate 尝试为任务分配资源,backfill 用集群剩余的小块资源填补空隙,preempt 在更高优先级任务需要资源时抢占低优先级任务。action 的执行顺序是可配置的,顺序不同,调度结果就可能不同。比如先抢占再分配,还是在分配后再清理超卖资源,行为完全不一样。

插件则是真正的业务规则。gang 插件实现了刚才说的组调度;proportion 插件实现了队列占比公平;priority 插件决定同一队列里谁能插队。可以理解为:action 划定了“塔台从早到晚的工作步骤”,plugin 给每个步骤提供了“该按什么规则办事”的手册。

理解了这套流水线,再看配置文件就不会一头雾水。我们下一节直接看怎么把航班计划写进 YAML。

ActionSequence:enqueue↦allocate↦backfill↦preempt\displaystyle \text{ActionSequence}: \text{enqueue} \mapsto \text{allocate} \mapsto \text{backfill} \mapsto \text{preempt}
这条链表示调度的典型动作顺序:先排队、再分配、再补空、再抢占。你可以通过配置文件调整这个顺序。
  1. 排队enqueue 把 PodGroup 加入对应队列,相当于塔台给航班安排候机区。
    enqueue(PodGroup)\text{enqueue}(\text{PodGroup})
  2. 分配allocate 尝试按 Gang 和 Proportion 等插件规则把资源分给这个组。
    allocate(G,Q,R)\text{allocate}(G, Q, R)
  3. 补空与抢占backfill 把碎片资源填给空闲任务,preempt 在必要时收回低优先进程。
    backfill→preempt\text{backfill} \to \text{preempt}

配置实践:把航班计划写进 YAML

再好的塔台也要落地成规章制度。在集群里部署 Volcano 后,首先要把任务交给它。给任务声明 schedulerName: volcano,就像告诉塔台“这架航班使用新调度系统”;同时声明 queue,相当于告诉塔台“这架航班停靠哪个候机楼”。

队列的 YAML 通常长这样(示意):

这段配置定义了一个叫 ai-team 的队列,权重为 2,最多使用 100 核 CPU 和 512Gi 内存。可以理解为给这个航司批了一组停机位,并且签了合同权重。Job 侧则需要声明 schedulerName: volcano、queue: ai-team 和 minAvailable。

队列与作业都就绪后,Volcano 在调度时会把“队列权重得分”作为重要输入,同时受 capability 限制。这就像塔台不仅要看航司合同,还要看停机位有没有空出来。综合公式就是:先按权重算出应得份额,再取配额上限,保证不会超额占用。

写配置是第一步,跑起分布式训练才是目的。最后我们来看看 Volcano 在真实 AI 场景中带来什么收益。

si=min⁡(capi,wi∑jwj×Rtotal)\displaystyle s_i = \min\left( \text{cap}_i, \frac{w_i}{\sum_j w_j} \times R_{\text{total}} \right)
这里再次用到队列份额公式:它同时受“权重比例”和“容量上限”双重约束,是配置队列时最基本的计算方式。
  1. 声明队列配置 weight 和 capability,分别表示合同权重和容量上限。
    Queuei=(wi,capi)\text{Queue}_i = (w_i, \text{cap}_i)
  2. 计算权重占比当前队列权重除以所有队列权重之和。
    pi=wi∑jwjp_i = \frac{w_i}{\sum_j w_j}
  3. 应用容量约束对理论份额和容量上限取最小值,得到最终可用份额。
    si=min⁡(capi,pi×Rtotal)s_i = \min(\text{cap}_i, p_i \times R_{\text{total}})
yaml9 行
apiVersion: scheduling.volcano.sh/v1beta1kind: Queuemetadata:  name: ai-teamspec:  weight: 2  capability:    cpu: 100    memory: 512Gi

AI 训练应用:让集群飞得更满

机场塔台改得好不好,要看航班准点率;AI 集群调度好不好,要看 GPU 利用率和任务完成时间。用 Volcano 跑分布式训练,最直观的变化是:所有 Worker 不再“陆陆续续起飞”,而是等队伍齐了一次滑出,把等待时间从分钟级压缩到秒级。

具体来说,Volcano 可以和很多常见 Operator 协作。比如 Kubeflow 的 TFJob、PyTorchJob,MPI Operator 驱动的 Horovod 训练任务,甚至 Spark、Flink 这类大数据工作负载。Operator 负责创建 Pod,Volcano 负责决定哪些 Pod 能同时起飞。两者配合,既保留了 Kubernetes 的易用性,又获得了批调度器的高效率。

效果上,集群不再因为某个 Worker 起不来而让其他 Worker 空转烧钱。多个团队共享集群时,队列公平让每个团队都拿到符合预期的资源。最终集群资源利用率会明显提升,训练任务排队时间更短。用公式看,就是“正在运行的任务所占资源”在总资源中的比例变得更高。

从“调度器定位”到“AI 训练应用”,Volcano 带来的核心价值可以用一句话概括:让每一个分布式训练航班都整整齐齐起飞,让每一块 GPU 都物尽其用。

U=∑G∈runningalloc(G)Rtotal\displaystyle U = \frac{\sum_{G \in \text{running}} \text{alloc}(G)}{R_{\text{total}}}
资源利用率 U 等于所有正在运行的 PodGroup 分配到的资源总和除以集群总资源。Volcano 的目标就是让这个比值尽量高,同时保证公平。
  1. 统计运行资源把所有处于 running 状态的 PodGroup 已分配资源相加,得到正在被真正使用的资源。
    Uused=∑G∈runningalloc(G)U_{\text{used}} = \sum_{G \in \text{running}} \text{alloc}(G)
  2. 除以总资源用这个数除以集群总资源,得到资源利用率。
    U=UusedRtotalU = \frac{U_{\text{used}}}{R_{\text{total}}}

AI 应用场景

场景一:PyTorch 分布式训练统一调度

阶段:训练任务调度 / 资源编排

解决的问题:默认 Kubernetes 调度器逐个调度 Pod。分布式训练需要多个 Worker 同时就绪,否则先启动的 Worker 会不断等待甚至超时,浪费 GPU 资源。Volcano 用 Gang 调度把同一任务的所有 Worker 组成 PodGroup,一次性放行。

具体案例:某公司的算法团队在 K8s 上用 PyTorch DDP 跑视觉模型训练,每个任务 4 个 Worker、2 个 Parameter Server。原来任务提交后总有几个 Pod Pending,GPU 被占着却算不动;改用 Volcano 后,所有 Pod 同时创建,训练启动时间明显缩短。

场景二:多团队共享 GPU 集群的配额公平

阶段:资源池管理与配额分配

解决的问题:多个部门共享 GPU 集群时,容易发生某个团队提交大量任务,把资源占满,导致其他团队饿死。Volcano 的队列和 proportion 插件按权重分配资源,限制单个队列的最大能力。

具体案例:某公司有推荐团队和搜索团队,推荐团队权重设为 2,搜索团队权重设为 1。在资源高峰期,两队各自按比例获得 GPU,搜索团队不会完全被挤掉;通过 capability 设置每个队列的 GPU 上限,防止某一方超卖。

场景三:TensorFlow / Horovod 与 Volcano 集成

阶段:作业编排与调度

解决的问题:Kubeflow 的 TFJob 和 PyTorchJob 只负责创建和管理由哪个 Pod,但不管“哪些 Pod 能一起调度”。Volcano 作为底层调度器,补齐了组调度和队列公平能力。

具体案例:NLP 团队用 Horovod 跑 BERT 预训练,通过 MPI Operator 创建 16 个 Worker;Worker 中任何一个资源不满足都会导致集群卡住。接入 Volcano 后,任务被当成一个整体调度,16 个 Worker 同时启动,分布式训练不再因个别 Pod 未调度而 stuck。

Python 演示

python43 行
class GangFairScheduler:    """用 gang + 队列权重做一轮批调度决策"""     def __init__(self, total_resources):        self.total_resources = total_resources        self.jobs = []     def add_job(self, name, min_available, queue_weight):        if min_available < 1 or queue_weight <= 0:            raise ValueError('min_available and queue_weight must be positive')        self.jobs.append({            'name': name,            'min_available': min_available,            'queue_weight': queue_weight,            'status': 'pending',            'allocated': 0        })     def schedule_round(self):        total_weight = sum(j['queue_weight'] for j in self.jobs)        remaining = self.total_resources        sorted_jobs = sorted(self.jobs, key=lambda j: j['queue_weight'], reverse=True)        for job in sorted_jobs:            fair_share = self.total_resources * job['queue_weight'] / total_weight            available = min(fair_share, remaining)            if available >= job['min_available']:                job['allocated'] += job['min_available']                job['status'] = 'running'                remaining -= job['min_available']            else:                job['status'] = 'waiting'        return remaining     def report(self):        for job in self.jobs:            print('{}: {} (allocated={})'.format(job['name'], job['status'], job['allocated'])) if __name__ == '__main__':    s = GangFairScheduler(total_resources=6)    s.add_job('img-train', min_available=3, queue_weight=2)    s.add_job('rec-train', min_available=4, queue_weight=1)    s.schedule_round()    s.report()
目的:模拟 Volcano 在 Kubernetes 中如何用 Gang + 队列公平决定哪些分布式训练任务可以同时开始。总资源 6,任务 A 需要 3 个 Pod,权重 2;任务 B 需要 4 个 Pod,权重 1。A 成功起飞,B 因公平份额不足而整组等待。
  1. s = GangFairScheduler(total_resources=6)建一个只有 6 块 GPU 的“停机坪”。
  2. s.add_job('img-train', min_available=3, queue_weight=2)注册一个至少需要 3 个 Pod 同时上线的训练任务。
  3. fair_share = self.total_resources * job['queue_weight'] / total_weight按权重算出这个队列应得的公平资源份额。
  4. if available >= job['min_available']:这就是 Gang 判断:凑不齐 minAvailable 就整组等待。
  5. remaining -= job['min_available']放行后,整组 Pod 一次性占用资源,不拆散分配。
  6. s.schedule_round()执行一轮塔台调度决策。

常见误区

误区我听说 Volcano 很强大,是不是要把集群里的 Kubernetes 换成 Volcano,然后用它管理所有节点?

正解Volcano 是 Kubernetes 上的原生批处理调度器,不是替代 Kubernetes 的独立平台。它像给机场加装一个新塔台,但机场本身还是 Kubernetes。你不需要替换 kube-apiserver,只需要安装 Volcano 组件,并在任务里声明 schedulerName: volcano。

为何常见:因为 Volcano 的名字和调度界面都太像完整平台,加上很多教程直接讲部署,容易让人误以为它是另一个 Kubernetes。

误区既然要全员到齐,那 Volcano 是不是反复尝试调度 Pod,跑不通就重启,直到成功?

正解不是“见缝插针地重试”,而是把一组 Pod 看成一个整体,在调度器内部做一次性判断。Pod 不会单独被放到节点上再撤回,而是在满足条件之前统一保持 Pending。这就像航班没凑齐人,塔台根本不会安排登机,而不是先把几个人送上飞机再赶下来。

为何常见:初学者容易把 Pending 看成“调度失败重试”,但 Gang 是调度前的整体约束,不是运行时重启逻辑。

误区只要把团队的 Queue 权重设成 100,这个团队就能一直在集群里横着走,把资源全占光。

正解权重决定的是公平份额,而不是抢占优先级。proportion 插件会考虑“已用资源 ÷ 权重”的比值,权重大的队列只是理论份额更大,但如果它已经把资源用超了,调度器会抑制它的新任务,让其他队列补上来。

为何常见:人们天然把“权重”理解为“抢资源能力”,忽略了公平调度中的“当前使用量”回馈机制。

误区Kubernetes 里有 namespace,Volcano 里又有 Queue,它们应该是一回事吧?

正解Namespace 是 Kubernetes 的资源对象隔离边界,而 Queue 是 Volcano 定义的调度资源池。一个 namespace 里可以有多个 Queue,一个 Queue 也可以跨 namespace 被多个任务使用。它们可以配合使用,但不能直接画等号。

为何常见:两者都是“分组”概念,都用来区分不同团队和任务,初学者很容易混淆。

面试题

Q1. Volcano 在 Kubernetes 中通常以什么身份运行?

单选题 · easy

  • A.调度插件← 正确答案
  • B.存储插件
  • C.网络插件
  • D.容器运行时

答案:A。Volcano 是 Kubernetes 的调度插件,负责为批处理任务提供更高级的调度能力。它不负责存储、网络或运行容器,那些由其他组件完成。

Q2. 下面哪个说法最符合 Gang Scheduling 的思想?

单选题 · easy

  • A.全部就绪一起调度← 正确答案
  • B.谁先到谁先飞
  • C.资源不足就杀掉
  • D.随机调度单个Pod

答案:A。Gang Scheduling 是“全有或全无”:一个 PodGroup 里所有 Pod 都满足资源要求时才整体放行,否则整组等待,不会先调度一部分。

Q3. Volcano 中把多个 Pod 组成一个组进行调度的 CRD 是?

单选题 · easy

  • A.PodGroup← 正确答案
  • B.ConfigMap
  • C.Deployment
  • D.Service

答案:A。PodGroup 是 Volcano 定义的核心 CRD,用于描述一组需要一起调度的 Pod,是 Gang 调度最基本的调度单元。

Q4. 队列公平调度主要依赖哪个 Volcano 插件?

单选题 · mid

  • A.proportion插件← 正确答案
  • B.gang调度插件
  • C.nodeorder插件
  • D.memory插件

答案:A。proportion 插件负责根据队列权重和已用资源计算公平份额,让多个队列按比例共享集群资源。

Q5. 一个 Volcano Job 若要使用 Volcano 调度,应设置哪个字段?

单选题 · mid

  • A.schedulerName← 正确答案
  • B.serviceName
  • C.clusterName
  • D.volumeName

答案:A。Kubernetes 中的任务通过 spec.schedulerName 指定使用哪个调度器。设为 volcano 后,该任务才真正交给 Volcano 塔台处理。

Q6. minAvailable 的取值表示什么?

单选题 · mid

  • A.至少可用的Pod数← 正确答案
  • B.最多可创建的Pod数
  • C.队列的最大权重
  • D.节点的GPU数量

答案:A。minAvailable 是组调度触发的门槛:组内 Ready 的 Pod 数达到这个值时,Volcano 才会判定整组可以放行。

Q7. 相比默认 kube-scheduler,Volcano 的典型能力包括?

多选题 · mid

  • A.组调度← 正确答案
  • B.公平队列← 正确答案
  • C.单Pod逐个调度
  • D.插件扩展← 正确答案

答案:ABD。Volcano 支持 Gang 组调度、队列公平和插件扩展,这些都是默认调度器不具备或较弱的。单 Pod 逐个调度是默认 kube-scheduler 的典型行为,不属于 Volcano 的差异化能力。

Q8. 在 Volcano 的配置中,actions 的作用是?

单选题 · hard

  • A.定义调度流程步骤← 正确答案
  • B.定义Pod镜像
  • C.定义网络策略
  • D.定义日志格式

答案:A。actions 定义调度流水线步骤,比如 enqueue、allocate、backfill、preempt。它决定了任务从进入队列到最终分配资源的处理顺序。

Q9. 下面哪些是 Volcano 常见的 Action 名称?

多选题 · hard

  • A.enqueue← 正确答案
  • B.allocate← 正确答案
  • C.backfill← 正确答案
  • D.setAffinity

答案:ABC。enqueue、allocate、backfill 都是 Volcano 调度流程中的常见 action。setAffinity 不是调度 action,而是 Kubernetes Pod 的调度亲和性概念。

Q10. 集群总资源为 10,队列 A 权重为 2,所有队列总权重为 5,队列 A 没有设置容量上限,它的公平份额是?

单选题 · extreme

  • A.公平份额等于4← 正确答案
  • B.公平份额等于3
  • C.公平份额等于5
  • D.公平份额等于6

答案:A。公平份额 = 权重占比 × 总资源 = (2/5) × 10 = 4。没有容量上限时,最终份额就是 4。如果设置了上限小于 4,则取上限值。