調度流程
調度器就是一個獨立的進程,負責不斷從apiserver拉取還沒有被調度的pod,以及可調度的node列表,通過一些列算法篩選,選出一個node並與該pod綁定,將綁定的結果寫回apiserver
調度算法
下面講解基於k8s v1.6.6的源碼
算法需要經過兩個階段,分別是過濾和打分,首先過濾掉一部分,保證剩餘的節點都是可調度的,接着在打分階段選出最高分節點,該節點就是scheduler的輸出節點。
算法流程:
過濾
過濾環節就是一條過濾器鏈,包含多個過濾器,每個相當於一個函數,接收node和待調度的pod作爲參數,返回bool來確定是否可調度。通過組合多個函數可以完成一條可擴展的過濾器鏈。目前k8s中已註冊的過濾器函數如下:
算法名稱 | 是否默認 | 詳細說明 |
---|---|---|
NoVolumeZoneConflict | 是 | 當主機上zone-label(地區)包含pod中PersistentVolume卷下的zone label時,可以調度。當主機沒有zone-label,表示沒有沒有zone限制,也可調度 |
MaxEBSVolumeCount | 是 | 當主機上被掛載的AWS EBS Volume超過了默認限制39,就不調度到該主機 |
MaxGCEPDVolumeCount | 是 | 當主機上被掛載的GCD Persistent Disk超過了默認限制16,就不調度到該機器 |
MaxAzureDiskVolumeCount | 是 | 當主機上被掛載的Azure Disk Volume超過了默認限制16,就不調度到該機器 |
NoDiskConflict | 是 |
當主機上所有pod使用的卷和待調度pod使用的卷存在衝突,就不調度到該主機。這項檢查只針對GCE, Amazon EBS, Ceph RBD, ISCSI,具體規則爲:
|
MatchInterPodAffinity | 是 | 親和性檢查,設帶調度的pod爲X,當主機上所有正運行的pod與X不相互排斥時,則可調度 |
PodToleratesNodeTaints | 是 | 當pod可以容忍(tolerate)主機所有的taint(污點)時,纔可被調度(容忍taint標籤的方式就是給自己也打上相應tolerations標籤) |
CheckNodeMemoryPressure | 是 | 當主機剩餘內存緊張時,BestEffort類型的pod無法被調度到該主機 |
CheckNodeDiskPressure | 是 | 當主機剩餘磁盤空間緊張時,無法調度到該主機 |
PodFitsHostPorts | 是 | 當待調度pod中所有容器所用到的HostPort與工作節點上已使用端口存在衝突,就不調度到該主機 |
PodFitsPorts | 是 | 被PodFitsHostPorts取代 |
PodFitsResources | 是 | 當總資源-主機中所有pod對資源的request總量 < 帶調度的pod request資源量,則不調度到該主機,現在會檢查CPU,MEM,GPU資源 |
HostName | 是 | 如果待調度的pod指定了pod.Spec.Host,則調度到該主機上 |
MatchNodeSelector | 是 | 當主機label與pod中nodeSelector以及annotations scheduler.alpha.kubernetes.io/affinity匹配,則可調度 |
打分
打分環節也是一條鏈路,包含多個打分函數,每個打分函數會接收node和待調度的pod作爲參數,返回一個範圍在0-10的分數,每個打分函數還有一個權重值。某個node算出的總分就是所有打分函數的分值*權重值的總和,獲取總分最大的node(如果有多個,隨機取一個),該node就是最終要被調度的節點
示例:假設有個節點nodeA,有兩個打分函數priorityFunc1、priorityFunc2(每個方法都能返回一個score),兩個方法分別都有權重因子weight1、weight2。則nodeA的總分爲:finalScoreNodeA = (weight1 * priorityFunc1) + (weight2 * priorityFunc2)
目前k8s中已註冊的打分函數如下:
算法名稱 | 是否默認 | 權重 | 詳細說明 |
---|---|---|---|
SelectorSpreadPriority | 是 | 1 | 相同service/rc的pods越分散,得分越高 |
ServiceSpreadingPriority | 否 | 1 | 相同service的pods越分散,優得分越高,被SelectorSpreadPriority取代,保留在系統中,並不使用 |
InterPodAffinityPriority | 是 | 1 | pod與node上正運行的其他pod親和性匹配度越高,得分越高 |
LeastRequestedPriority | 是 | 1 | 剩餘資源越多,得分越高。cpu((capacity - sum(requested)) * 10 / capacity) + memory((capacity - sum(requested)) * 10 / capacity) / 2 |
BalancedResourceAllocation | 是 | 1 | cpu和內存利用率越接近,得分越高。10 - abs(cpuFraction-memoryFraction)*10 |
NodePreferAvoidPodsPriority | 是 | 10000 | 當node的annotation scheduler.alpha.kubernetes.io/preferAvoidPods被設置時,說明該node不希望被調度,得分低,當沒有設置時得分高。之所以權重較大是因爲一旦設置preferAvoidPods表示該node不希望被調度,該項得分爲0,其他沒有設置的node得分均爲10000*分值,相當於直接過濾掉該節點。思考:其實可以放在過濾環節處理 |
NodeAffinityPriority | 是 | 1 | pod與node的親和性匹配度越高,得分越高 |
TaintTolerationPriority | 是 | 1 | pod對node的污點(taint)的容忍(tolerate)程度越高,得分越高 |
EqualPriority | 否 | 1 | 所有機器得分一樣 |
ImageLocalityPriority | 否 | 1 | 待調度的pod會使用到一些鏡像,擁有這些鏡像越多的節點,得分越高 |
MostRequestedPriority | 否 | 1 | request資源越多,得分越高,與LeastRequestedPriority相反。(cpu(10 * sum(requested) / capacity) + memory(10 * sum(re |