kube-batch 解析


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調度上去


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM