調度器就是一個獨立的進程,負責不斷從apiserver拉取尚未被調度的pod,以及可調度的node列表,經過一些列算法篩選,選出一個node並與該pod綁定,將綁定的結果寫回apiservernode
下面講解基於k8s v1.6.6的源碼git
算法須要通過兩個階段,分別是過濾和打分,首先過濾掉一部分,保證剩餘的節點都是可調度的,接着在打分階段選出最高分節點,該節點就是scheduler的輸出節點。github
算法流程:算法
過濾環節就是一條過濾器鏈,包含多個過濾器,每一個至關於一個函數,接收node和待調度的pod做爲參數,返回bool來肯定是否可調度。經過組合多個函數能夠完成一條可擴展的過濾器鏈。目前k8s中已註冊的過濾器函數以下:api
算法名稱 | 是否默認 | 詳細說明 |
---|---|---|
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就是最終要被調度的節點spa
示例:假設有個節點nodeA,有兩個打分函數priorityFunc一、priorityFunc2(每一個方法都能返回一個score),兩個方法分別都有權重因子weight一、weight2。則nodeA的總分爲:finalScoreNodeA = (weight1 * priorityFunc1) + (weight2 * priorityFunc2)server
目前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(requested) / capacity)) / 2 |