gang scheduler介紹:一個job智政,可能有多個tasks,這些tasks要不全部執(zhí)行牺蹄,要不一個都不執(zhí)行惨远。
上面說到 kube-batch自定義了一個podGroup躯枢,調(diào)度時以podGroup為單位的。現(xiàn)在說一下調(diào)度podGroup的整個過程司忱。
本文分為四個部分:
一:介紹kube-batch的基本概念
二:總結(jié)這些概念的關(guān)系皇忿,已經(jīng)列出可能的疑問
三:介紹如何實(shí)現(xiàn)gang scheduler
四:總結(jié)gang scheduler的實(shí)現(xiàn)流程
第一二部分是為了幫助理解,第四部分是從代碼角度深入理解坦仍。想大概了解的禁添,看到第三部分就可以了。
一:介紹kube-batch的基本概念:queue, podgroup, job桨踪。
(1) queue
這個一個全局的概念,意思就是沒有Namespace的這一說法芹啥。用這個概念的目的是為了實(shí)現(xiàn)多租戶锻离。這里一個租戶就是一個隊(duì)列铺峭。kube-batch默認(rèn)有一個default-queue。如果用戶創(chuàng)建的任務(wù)沒有指定隊(duì)列汽纠,都會放在默認(rèn)的這個隊(duì)列里卫键。
type QueueInfo struct {
UID QueueID
Name string
Weight int32
Queue *arbcorev1.Queue
}
查看 queue 的定義,發(fā)現(xiàn)這里有個 Weight的屬性虱朵。這個干什么用的呢莉炉?
繼續(xù)往下。
proportion.go:116
// Calculates the deserved of each Queue.
deserved := api.EmptyResource()
for _, attr := range pp.queueOpts {
glog.V(4).Infof("Considering Queue <%s>: weight <%d>, total weight <%d>.",
attr.name, attr.weight, totalWeight)
if _, found := meet[attr.queueID]; found {
continue
}
attr.deserved.Add(remaining.Clone().Multi(float64(attr.weight) / float64(totalWeight)))
if !attr.deserved.LessEqual(attr.request) {
attr.deserved = helpers.Min(attr.deserved, attr.request)
meet[attr.queueID] = struct{}{}
}
pp.updateShare(attr)
glog.V(4).Infof("The attributes of queue <%s> in proportion: deserved <%v>, allocate <%v>, request <%v>, share <%0.2f>",
attr.name, attr.deserved, attr.allocated, attr.request, attr.share)
deserved.Add(attr.deserved)
}
可以看出來碴犬,"Weight" 是分配資源用的絮宁。一個Queue代表一個租戶,它們按照權(quán)重分配集群的資源服协。下面這個圖清晰明了:
(2)job
這里很容易弄混绍昂,kube-batch的job 和 k8s的job是不一樣的。
type JobInfo struct {
UID JobID
Name string
Namespace string
Queue QueueID
Priority int32
NodeSelector map[string]string
MinAvailable int32
NodesFitDelta NodeResourceMap
// All tasks of the Job.
TaskStatusIndex map[TaskStatus]tasksMap
Tasks tasksMap
Allocated *Resource
TotalRequest *Resource
CreationTimestamp metav1.Time
PodGroup *v1alpha1.PodGroup
// TODO(k82cn): keep backward compatibility, removed it when v1alpha1 finalized.
PDB *policyv1.PodDisruptionBudget
}
這是kube-batch 中job的定義偿荷,這里要理解成: kube-batch job是一堆Task的集合(1個Task是一個pod)窘游。
這里的job和K8s中job的區(qū)別是:
如果有一個k8s的job, 假設(shè)為Job1,有2個pod, 他指定的podgroup是gp1.
同時還有一個k8s的job, 假設(shè)為Job2跳纳,有2個pod, 他指定的podgroup也是gp1.
如果同時提交這倆個k8s job忍饰。那么在kube-batch看來,當(dāng)前要調(diào)度的只有一個"job"(這是kube-batch的一個作業(yè))寺庄。這個kube-batch job總共有4個Tasks(pod)需要綁定艾蓝。
所以,kube-batch的job,它是指向某個podgroup 所有的k8s job的pod集合铣揉。
有點(diǎn)拗口饶深,結(jié)合上面例子再讀讀。
(3) podgroup
我原本以為一個podgroup對應(yīng)的是一個k8s job逛拱。后面我發(fā)現(xiàn):
a. 我運(yùn)行一個job不指定podgroup也能正常運(yùn)行敌厘。
b. 我同時運(yùn)行倆個job,指定的是同一個podgroup也能正常運(yùn)行。
所以朽合,我就非常奇怪俱两,看了相關(guān)源碼后發(fā)現(xiàn),這里的podgroup是一個pod的集合曹步。
如果有n個k8s job指向他宪彩,那么他就是這個n個Job的所有pod的集合。
二:總結(jié)這些概念的關(guān)系
(1)提交每個k8s job都必須指定一個podgroup
Q: 為什么創(chuàng)建job時讲婚,不指定也能運(yùn)行尿孔?
A: kube-batch會為這類job,創(chuàng)建一個 shadow PodGroup
(2)一個podGroup對應(yīng)一個queue
Q:為什么創(chuàng)建queue時,不指定也能運(yùn)行
A:不指定,默認(rèn)使用default-queue
(3)一個kube-batch中的job 包含podgroup中所有的pod.
(4)這個kube-batch的job使用 queue中的資源活合,完成task
三:介紹如何實(shí)現(xiàn)gang scheduler
結(jié)合圖片和文字一起看雏婶,能加深理解
這里以倆個k8s job為例介紹這個過程
(1)將指向某個podgroup的 所有k8s job中的pod合在一起生成一個 kube-batch job. (比如上面圖中,最后kube-batch job的Tasks是 n1+n2)
(2) 開始調(diào)度kube-batch中的job
(3) 每次完成一個task(這里是假裝綁定一個pod),當(dāng)完成的task數(shù)量 達(dá)到MIN(podgroup設(shè)定的值)時白指,開始真正的綁定留晚,一次性綁定MIN個task。然后將剩下的Tasks 生成一個新的kube-batch job 再次調(diào)度告嘲。如果在沒達(dá)到MIN 個之前错维,已經(jīng)資源不足,那么進(jìn)入backfill 操作橄唬,釋放之前綁定的job赋焕。
所以實(shí)現(xiàn)gang scheduler的關(guān)鍵還是 podgroup,通過設(shè)置podgroup的minNumber轧坎。達(dá)到每次調(diào)度要么 執(zhí)行minNumber個tasks.要么一個都不執(zhí)行宏邮。
PS:
上面的圖片是為了解釋, 所以放了倆個k8s job.
如果想讓這倆個job進(jìn)行g(shù)ang scheduer, 直接令 minNumber = n1+n2.
這樣倆個job就會同時執(zhí)行。
四:總結(jié)gang scheduler的實(shí)現(xiàn)流程
我一開始非常納悶為什么podgroup不是和k8s job一一對應(yīng)缸血。后面我仔細(xì)想想蜜氨,發(fā)現(xiàn)這樣設(shè)計(jì),更加靈活捎泻。
如果是k8s job和podgroup一一對應(yīng)的話飒炎。那么podgroup包含的就是這個k8s job的所有pod.這樣每次就只能對一個k8s job進(jìn)行g(shù)ang scheduler.
而他這樣設(shè)計(jì),則同時進(jìn)行一個或者多個K8s job的調(diào)度笆豁。
(通過調(diào)整n1,n2以及minNumber的值)
注意:
這樣也可能產(chǎn)生不好的影響郎汪。
例如我有兩個K8s job.描述如下:
job1 需要6個pod切威,1個pod需要1個cpu
job2 需要6個pod吭狡,1個pod需要100個cpu
現(xiàn)在集群總共有6個cpu.
如果我不小心,將job1,job2的podgroup設(shè)置成一樣床嫌。那么這次就會出現(xiàn)死鎖哄孤,這倆個job都不會執(zhí)行照筑。
原因:
此時只有一個kube-batch的job,并且Tasks隊(duì)列很有可能為:
job1-pod1, job2-pod1,job1-pod1......
這樣當(dāng)創(chuàng)建到j(luò)ob2-pod1, 這個任務(wù)時,已經(jīng)資源不足了瘦陈。然后釋放資源凝危,重新再來。這樣就會一直死循環(huán)晨逝。
所以蛾默,要靈活使用Podgroup.
本來想再加一個步驟:“從代碼中找出gang scheduler這個過程"
由于篇幅和時間的原因,下篇文章在介紹捉貌。
從代碼角度查找支鸡,能理解更多的細(xì)節(jié)冬念。
比如有多個隊(duì)列,每個隊(duì)列有多個任務(wù)牧挣,那么kubu-batch首先運(yùn)行哪個呢刘急?