简介
Volcano 是一个用于高性能计算(HPC)和大数据应用的 Kubernetes 调度器。它专为需要复杂调度策略的工作负载设计,如机器学习、深度学习、批处理作业等。
Volcano 的架构由多个组件组成,每个组件负责不同的功能模块。其中Scheduler是负责Pod调度的组件,它由一系列action和插件组成。action定义了调度各环节中需要执行的动作;插件根据不同场景提供了action 中算法的具体实现细节。
本文详细解读Scheduler中插件,包括插件如何注册,一些常用的插件,以及插件如何实现。
action&plugin的注册
由于Volcano scheduler采用了组合模式的设计,它具有高度的扩展性。用户可以根据个人需要决定使用哪些action和plugin,也可以根据action和plugin的 接口自定义实现。scheduler的配置位于名为volcano-scheduler-configmap的configmap内,该configmap被作为volume挂载在容器的/volcano.scheduler 路径下。
在代码实现上,我们需要关注的是OpenSession函数,首先
ssn := openSession(cache)
然后遍历plugins,执行 plugin.OnSessionOpen(ssn)
在每个插件中,OnSessionOpen会向ssn中注册各种函数,比如priority插件
ssn.AddTaskOrderFn([pp.Name], taskOrderFn)
ssn.AddJobOrderFn([pp.Name], jobOrderFn)
AddJobOrderFn函数在scheduler/framework/session_plugins里面
func (ssn *Session) AddJobOrderFn(name string, cf api.CompareFn) {
ssn.jobOrderFns[name] = cf
}
而jobOrderFns的定义在scheduler/framework/session.go里面
type Session struct {
这里包含了所有的Fns和其他信息
常见的插件
gang
gang plugin认为未处于ready状态(包括Binding、Bound、Running、Allocated、Succeed、Pipelined)的任务具有更高的优先级。它会检查假如驱逐某 些任务回收队列部分应得资源后,该任务所属的Job中任务的运行数量是否满足minAvailable的要求,以决定是否执行驱逐动作。
conformance
conformance plugin认为命名空间kube-system下的任务具有更高的优先级。这些任务不能被抢占。
DRF
DRF plugin认为占用资源较少的任务具有更高的优先级。它会尝试计算已分配给抢占者和被抢占者的资源总量,并在抢占者资源资源份额更少时触发抢占行为。
nodeorder
nodeorder plugin通过一系列维度的打分算法,算出针对某个任务时所有的节点的得分情况。得分最高的节点被认为是针对该任务最合适的节点。
predicates
predictions plugin通过一系列维度的评估算法,决定某个任务是否适合被绑定到某个节点。
priority
priority plugin用于比较两个job或任务的优先级。它通过比较job.spec.priorityClassName来决定哪个job的优先级更高。对于两个任务,它会依次比较 task.priorityClassName、task.createTime、task.id in order来决定谁的优先级更高。
插件的实现
插件主要是实现了在action中注册的各个函数。这里我们以JobEnqueueable函数为例。
JobEnqueueable函数的逻辑是,遍历每一层,如果有反对,则不可入。没有反对,有至少一个插件支持,可入。否则进入下一层。如果没有触发任何逻辑,默认可入。
实现该函数的插件包括
-
extender
-
overcommit
-
proportion
-
resourcequota
-
sla
这里我们具体介绍下overcommit和proportion两个插件对JobEnqueueable函数的实现。overcommit
如果没有资源要求,返回permit
如果资源要求小于当前系统idle,返回permint,否则 reject
注意这里:op.idleResource = op.totalResource.Clone().Multi(op.overCommitFactor).SubWithoutAssert(used)
即这是可以超卖的,空闲资源=总体资源 * 超卖因子 - 已使用资源
超卖因子overCommitFactor默认为1.2
proportion
如果队列没有设置实际的资源能力(realCapability
),则允许作业进入队列(返回 util.Permit
)。
如果作业没有定义最小资源请求(MinResources
),也允许作业进入队列。
计算作业的资源需求加上队列已分配的资源和队列中的资源,然后减去弹性资源。判断计算后的资源需求是否小于或等于队列的实际能力。如果满足,permit。不满足,reject
这里 realCapability := pp.totalResource.Clone().Sub(pp.totalGuarantee).Add(attr.guarantee) • attr.realCapability
: 实际能力,计算方式是总资源减去总保证资源再加上该队列的资源保证。
这种分配算法试图根据队列的权重公平地分配资源,同时考虑队列的实际能力上限、资源请求和资源保证
overcommit查看的是整个系统的资源,proportion查看的是队列资源分配