volcano调度器源代码走读actions篇

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

volcano调度器源代码⾛读actions篇
Enqueue
Queues
QueueMap
jobsMap
//扫描⼀遍job,初始化上⾯三个数据结构
For job in ssn.Jobs
//过滤1
found := ssn.Queues[job.Queue]
existed := queueMap[queue.UID]
//过滤2
if job.PodGroup.Status.Phase == scheduling.PodGroupPending
found := jobsMap[job.Queue];
/*更新node资源使⽤情况*/
For node in ssn
Update Total_nodes
Update Used_nodes
/*反复enqueue操作*/
While(!queues.Empty()){
/*资源不⾜结束enqueue操作*/
if idle.IsEmpty() break
//deal with target job , if exists , judege whether it can be
minReq <--- job
idle <--- node资源
if node资源⾜够
inqueue := true;
if inqueue
inqueue
Queues.push(queue)
}
逻辑
筛选符合要求的任务进⼊待调度队列。

过滤条件主要是对应任务再QueueMap是否存在,node是否满⾜任务的最⼩资源需求量minReq。

场景
任务调度的准备过程,符合要求可以被调度的任务inqueue。

任务状态由pending变为inqueue
Allocate
step1. pick a namespace named N (using spaceOrderFn)
step2. pick a queue named Q from N (using ssn.QueueOrderFn)
step3. pick a job named J from Q (using ssn.JobOrderFn)
step4. pick a task T from J (using ssn.TaskOrderFn)
step5. use predicateFn to filter out node that T can not be allocated on.
step6. use ssn.NodeOrderFn to judge the best node and assign it to T
逻辑
<task,node>的绑定⼯作,包含预选和优选过程。

使⽤predicateFn来过滤不能分配的node,使⽤NodeOrderFn打分来找到最好的node。

场景
allocate从namespce层次开始遍历,不同的namespace可以代表不同业务的任务集合,这将有助于处理多类型的复杂业务场景的资源分配功能。

不同的业务场景可以注册合适的调度算法(plugins中实现了多种具体的调度策略)
Preempt
//Queue内Jobs之间的抢占
For queue in queues //枚举queue
若⼲抢占条件的过滤
//job内task的抢占
For job in range underRequest
若⼲抢占条件过滤
这⾥抢占分为两个粒度,能够看到必须是同⼀个Queue下的job抢占,或者同⼀job下的task抢占。

场景
Queue的粒度:相似的场景下发的任务进⼊到⼀个Queue中,多个Queue之间不存在资源的抢占。

多个Queue之间对集群资源进⾏⽐例分配。

在很多复杂的调度场景,按照业务对基本资源(cpu、磁盘、GPU、内存、⽹络带宽)的需求进⾏分类分组:计算密集的场景如AI、⾼性能科学计算所对应的Queue的资源划分cpu、GPU、内存等计算资源需求⾼;spark框架等⼤数据场景磁盘需求⾼,等等。

不同的Queue对资源的分配虽然是共享的,但如果AI场景抢占了所有的cpu资源,会导致别的场景对应的Queue中的任务饿死。

因此分配基于Queue的粒度,就是为了保证资源的业务吞吐量。

job的粒度:同⼀job的task进⾏抢占,能够保证某些特定业务下特定功能的⾼实时性要求。

例如spark⼤数据场景,针对⼀些批处理的功能,实时性要求不⾼;针对实时数据流的CRUD业务,需要快速反馈结果。

此时就需要job内部进⾏抢占。

Reclaim
输出正在调度的Jobs和Quenes的数量(reclaim针对的对象)
For job in ssn(查⼀下ssn的含义,这⾥其实迭代的是ssn.Jobs
(job.PodGroup.Status.Phase == scheduling.PodGroupPending的具体含义要搞清楚等待调度?Elect中有⼀样的代码回收正在调度的代码,等待调度的continue掉。


1.等待调度的job拒绝reclaim
2.拒绝被reclaim的情况(有效job),具体的原因和信息抽象掉了
3.Job的对应Queue found异常,不需要recliam
ADD⼀个Queue
更新queueMap
更新queues
4. //既然没有交互信息姑且理解为这个循环的主要过程筛选[符合要求的Job]
更新preemptorsMap(下⾯的迭代会⽤)
更新preemptorTasks
While(!Queues.Empty())
Queue = Queues.pop()//出队⼀个元素
If Overused --> continue
Found high priority job
Found high priority task to reclaim others
If found:= preemptorTasks[job.UID] 判断task是否在抢占映射job-Task中。

没有发现 ==> high priority task ==> 不进⾏操作continue;
For n in ssn.Nodes://开始操作资源层的节点
If predicates fialed -> continue
//predicates基于task - n的预判函数predicateFn
//开始考察在n上所有的Task(是否reclaim)
For task on n
Non running task -> continue;
[Job , Task] not found -> continue;
//clone task to avoid modify Task ‘s status on node n
Update reclainmees
确定牺牲品victims(reclaim的对象)
Start to Reclaim...
逻辑
当新的任务进⼊等待调度队列,集群资源⽆法满⾜,进⾏资源回收。

相对于preempt主动强占,这是⼀种被迫触发的抢占。

场景
当任务负载超过系统资源量时,例如双⼗⼀秒杀、红包⾬等访问量骤升的场景,需要关注reclaim的配置,具体⽽⾔和preempt是很相似的过程。

Elect
//select the target job which is of the highest priority and waits for the longest time
For job in ssn.Jobs
If job.PodGroup.status.phase == scheduling.podGroupPending
pendingJobs <---- this job
Print these jobs which have been elected
逻辑
⾮常抽象的Job选取⼯作,给出ssn.jobs,当job满⾜某个状态条件的时候,直接就可以把这个job加⼊到pendingJobs这个数据结构中。

注释中提到需要highest priority 、wait for longest time,但是这⾥没有提到具体如何实现。

这个模块提供了选择⾼优先、长等待的job,属于进⾏调度之前的预选⼯作,适宜在各种调度场景(分配、抢占、预留等)之前的模块。

Reserve
//select a node which is not locked and has the most idle resoure
targetJob(if there is not a targetJob return)
if target job has not been scheduled, select a locked node for it
else reset target job and locked nodes
逻辑
job,node进⾏绑定。

抽象了ReserveNodes。

与elect和plugins中的reservation⼀起组成了资源预留机制。

场景
和preempt抢占模块类似,最终是需要处理job和node绑定关系。

⽤于资源预留,进⾏调度前的准备⼯作。

相关文档
最新文档