kube-batch
https://github.com/kubernetes-sigs/kube-batch
一. 做什么的?
官方介紹:
A batch scheduler of kubernetes for high performance workload, e.g. AI/ML, BigData, HPC
二. 使用方式
apiVersion: batch/v1
kind: Job
metadata:
name: qj-1
spec:
backoffLimit: 6 #最大失敗重試次數
completions: 6 #需要成功運行pod的次數
parallelism: 6 #並行運行pod的個數
template:
metadata:
annotations:
scheduling.k8s.io/group-name: qj-1
spec:
containers:
- image: busybox
imagePullPolicy: IfNotPresent
name: busybox
resources:
requests:
cpu: "1"
restartPolicy: Never
schedulerName: kube-batch # 指定調度器是 kube-batch
---
apiVersion: scheduling.incubator.k8s.io/v1alpha1
kind: PodGroup
metadata:
name: qj-1
spec:
minMember: 6 # 最小可用數量,達到這個數量才將任務調度到節點上去
三. 調度的單位
- 一個task對應一個pod
- 一個job對應一個或多個task
- Pod Group 記錄該job內的pod的狀態
- 一個job對應一個pod group
如果Job未聲明一個對應的pod group ,
kube-batch
將會給一個默認的
Pod Group 定義:
{
"metav1.TypeMeta":{},
"metav1.ObjectMeta":{},
"Spec":{
//用來做gang schedule
"MinMember":1,//default 1
"Queue":"",
"PriorityClassName":""
},
"Status":{
"Phase":"",//Pending, Running,Unknown
"Conditions":[],//optional
"Running":0,//正在運行的pod的數量
"Succeeded":0,//已經成功結束的pod的數量
"Failed":0,//失敗的pod的數量
}
}
四. 整體結構
從數據流的角度給出項目框架結構:
主調度流程:
五. 幾個plugin
5.1 DRF (Dominant Resource Fairness)
主要資源(cpu,memory,gpu)的均衡使用算法。
目的: 盡量避免集群內某一類資源 使用比例偏高,而其他類型資源使用比例卻很低的不良狀態
方式: 在調度時,讓具有最低資源占用比例的任務具有高優先級
細節:
DRF計算了每個job的一個share值,share值的計算公式為:
share = Max(someKindOfResource.allocated / totalResourceInTheCluster)
share = 最大的某類資源申請比例
func (drf *drfPlugin) calculateShare(allocated, totalResource *api.Resource) float64 {
res := float64(0)
for _, rn := range totalResource.ResourceNames() {
share := helpers.Share(allocated.Get(rn), totalResource.Get(rn))
if share > res {
res = share
}
}
return res
}
DRF 定義兩個Function ,分別是preemptableFn
和 jobOrderFn
:
jobOrderFn
是job的排序函數,會讓share
值越小的job排在最前面,即擁有最高的優先級,這個是實現DRF算法的關鍵。
preemptableFn
返回可搶占的job列表,job的篩選規則是 :如果待選job的share
值大於將被調度的job的share
值,則選中該待選job。
5.2 Gang
Gang策略要實現的功能: 只有當指定的某幾個pod都分配到資源后,才正在地將pod調度到節點上.
定義的幾個plugin function
preemptableFn
為避免Gang的策略被preempt
和reclaim
干擾,定義了preemptableFn
,排除那些還未准備就緒的job,避免被搶占。
雖然實際上這些job未真正調度到node上去,但是確實從邏輯上把資源分配給它了
-
jobOrderFn
為讓已經就緒的job盡快被調度到節點,定義了jobOrderFn
,讓已經就緒的job擁有更高的優先級 -
jobReadyFn
用來判斷一個job是否已經就緒。
解析Kube-Batch
實現gang的方式:
無論是k8s默認的scheduler, 還是kube-batch ,再進行調度時都是先從邏輯上分配資源給pod,等滿足某一條件之后,才真正將pod 調度到某一個節點上。
kube-batch/pkg/scheduler/framework/session.go Line 281
if ssn.JobReady(job) {
for _, task := range job.TaskStatusIndex[api.Allocated] {
if err := ssn.dispatch(task); err != nil {
glog.Errorf("Failed to dispatch task <%v/%v>: %v",task.Namespace, task.Name, err)
return err
}
}
}
dispatch
內包bind job到node 等實際的調度動作.
jobReady
會調用所有注冊了的 plugin的 Ready
判定函數,只有都判定為 ready ,才返回true。
而gang plugin里面定義的ready判定函數實際上是調用 job 自帶的ready函數,定義在
kube-batch/pkg/scheduler/api/job_info.go#L415
// ReadyTaskNum returns the number of tasks that are ready.
func (ji *JobInfo) ReadyTaskNum() int32 {
occupid := 0
for status, tasks := range ji.TaskStatusIndex {
if AllocatedStatus(status) ||
status == Succeeded {
occupid = occupid + len(tasks)
}
}
return int32(occupid)
}
// Ready returns whether job is ready for run
func (ji *JobInfo) Ready() bool {
occupied := ji.ReadyTaskNum()
return occupied >= ji.MinAvailable
}
5.3 Proportion
Proportion 實現了隊列.
type queueAttr struct {
queueID api.QueueID // 隊列的id
name string //隊列的名字
weight int32 // 隊列的權重,決定分配到的資源的多少
share float64 //參考 drf處的share
deserved *api.Resource //聲明的資源總量
allocated *api.Resource //實際分配到的資源總量
request *api.Resource //該隊列中所有job聲明的要分配的資源總量
}
Proportion 根據各個隊列聲明的權重和全局的資源總量 初始化deserved的值,根據全局的job 初始化
allocated 和 request的值。並監聽全局的資源釋放 和 申請事件 更新隊列的狀態。
定義的幾個plugin function:
- QueueOrderFn
QueueOrderFn 會決定哪一個隊列里的job在調度時會被優先考慮,這里沿用了DRF處jobOrderFn的邏輯,
即share值最小的queue 會最優先被考慮.
- OverusedFn
判斷queue的資源使用是否已經超出限制了,即
allocated > deserved == true
- ReclaimableFn
判斷一個task是否可以被召回,如果召回之后使得已經分配到的資源小於等於deserved 就不應該被召回。
5.4 其他幾個plugin
略
六. 四個Action
kube-batch 默認只開啟了
Allocate
和Backfill
6.1 Allocate
功能 : 將pod(task)分配到某個節點
6.2 Backfill
功能 : 調度未設置資源使用量的pod到節點(資源使用量 = 工作容器和初始化容器的各維度資源的最大值)
6.3 Reclaim
功能 : 召回滿足條件的pod
6.4 Preempt
功能: 搶占已經調度了的滿足條件的pod,並將目標pod調度上去