目錄
一、排程器的排程政策
二、Predicates謂詞(過濾)
2.1 GeneralPredicates(一般謂詞)
2.2 與 Volume 相關的過濾規則
2.3 主控端相關的過濾規則
2.4 Pod 相關的過濾規則
2.5 小結
三、Priorities優先級(打分)
四、總結
了解一下 排程器的排程政策 也是加深對k8s的了解,事先可以看一下官網的《排程政策 》
一、排程器的排程政策
主要有兩處政策:過濾的 謂詞(Predicates) 和打分的 優先級(Priorities) 。
二、Predicates謂詞(過濾)
Predicates 在排程過程中的作用,可以了解為 Filter,即:它按照排程政策,從目前叢集的所有節點中,“過濾”出一系列符合條件的節點。這些節點,都是可以運作待排程 Pod 的主控端。
官網的《排程政策 》,在 Kubernetes 中,預設的排程政策有如下三種。
2.1 GeneralPredicates(一般謂詞)
顧名思義,這一組過濾規則,負責的是最基礎的排程政策。比如,PodFitsResources 計算的就是主控端的 CPU 和記憶體資源等是否夠用。
當然,我在前面已經提到過,PodFitsResources 檢查的隻是 Pod 的 requests 字段。需要注意的是,Kubernetes 的排程器并沒有為 GPU 等硬體資源定義具體的資源類型,而是統一用一種名叫 Extended Resource 的、Key-Value 格式的擴充字段來描述的。
2.2 與 Volume 相關的過濾規則
這一組過濾規則,負責的是跟容器持久化 Volume 相關的排程政策。
其中,NoDiskConflict 檢查的條件,是多個 Pod 聲明挂載的持久化 Volume 是否有沖突。比如,AWS EBS 類型的 Volume,是不允許被兩個 Pod 同時使用的。是以,當一個名叫 A 的 EBS Volume 已經被挂載在了某個節點上時,另一個同樣聲明使用這個 A Volume 的 Pod,就不能被排程到這個節點上了。
MaxPDVolumeCountPredicate 檢查的條件,則是一個節點上某種類型的持久化 Volume 是不是已經超過了一定數目,如果是的話,那麼聲明使用該類型持久化 Volume 的 Pod 就不能再排程到這個節點了。
MaxPDVolumeCountPredicate 檢查的條件,則是一個節點上某種類型的持久化 Volume 是不是已經超過了一定數目,如果是的話,那麼聲明使用該類型持久化 Volume 的 Pod 就不能再排程到這個節點了。
VolumeZonePredicate,則是檢查持久化 Volume 的 Zone(高可用域)标簽,是否與待考察節點的 Zone 标簽相比對。
此外,這裡還有一個叫作 VolumeBindingPredicate 的規則。它負責檢查的,是該 Pod 對應的 PV 的 nodeAffinity 字段,是否跟某個節點的标簽相比對。
2.3 主控端相關的過濾規則
這一組規則,主要考察待排程 Pod 是否滿足 Node 本身的某些條件。
比如,PodToleratesNodeTaints,負責檢查的就是我們前面經常用到的 Node 的“污點”機制。隻有當 Pod 的 Toleration 字段與 Node 的 Taint 字段能夠比對的時候,這個 Pod 才能被排程到該節點上。
2.4 Pod 相關的過濾規則
這一組規則,跟 GeneralPredicates 大多數是重合的。而比較特殊的,是 PodAffinityPredicate。這個規則的作用,是檢查待排程 Pod 與 Node 上的已有 Pod 之間的親密(affinity)和反親密(anti-affinity)關系。
PS:可以檢視官網的《親和性和反親和性》
2.5 小結
四種類型的 Predicates,就構成了排程器确定一個 Node 可以運作待排程 Pod 的基本政策。
在具體執行的時候, 當開始排程一個 Pod 時,Kubernetes 排程器會同時啟動 16 個 Goroutine,來并發地為叢集裡的所有 Node 計算 Predicates,最後傳回可以運作這個 Pod 的主控端清單。
需要注意的是,在為每個 Node 執行 Predicates 時,排程器會按照固定的順序來進行檢查。這個順序,是按照 Predicates 本身的含義來确定的。比如,主控端相關的 Predicates 會被放在相對靠前的位置進行檢查。要不然的話,在一台資源已經嚴重不足的主控端上,上來就開始計算 PodAffinityPredicate,是沒有實際意義的。
三、Priorities優先級(打分)
在 Predicates 階段完成了節點的“過濾”之後,Priorities 階段的工作就是為這些節點打分。這裡打分的範圍是 0-10 分,得分最高的節點就是最後被 Pod 綁定的最佳節點。
Priorities 裡最常用到的一個打分規則,是 LeastRequestedPriority。它的計算方法,可以簡單地總結為如下所示的公式:
score = (cpu((capacity-sum(requested))10/capacity) + memory((capacity-sum(requested))10/capacity))/2
可以看到,這個算法實際上就是在選擇空閑資源(CPU 和 Memory)最多的主控端。
而與 LeastRequestedPriority 一起發揮作用的,還有 BalancedResourceAllocation。它的計算公式如下所示:
score = 10 - variance(cpuFraction,memoryFraction,volumeFraction)*10
其中,每種資源的 Fraction 的定義是 :Pod 請求的資源 / 節點上的可用資源。而 variance 算法的作用,則是計算每兩種資源 Fraction 之間的“距離”。而最後選擇的,則是資源 Fraction 差距最小的節點。
是以說,BalancedResourceAllocation 選擇的,其實是排程完成後,所有節點裡各種資源配置設定最均衡的那個節點,進而避免一個節點上 CPU 被大量配置設定、而 Memory 大量剩餘的情況。
此外,還有 NodeAffinityPriority、TaintTolerationPriority 和 InterPodAffinityPriority 這三種 Priority。顧名思義,它們與前面的 PodMatchNodeSelector、PodToleratesNodeTaints 和 PodAffinityPredicate 這三個 Predicate 的含義和計算方法是類似的。但是作為 Priority,一個 Node 滿足上述規則的字段數目越多,它的得分就會越高。
在預設 Priorities 裡,還有一個叫作 ImageLocalityPriority 的政策。它是在 Kubernetes v1.12 裡新開啟的排程規則,即:如果待排程 Pod 需要使用的鏡像很大,并且已經存在于某些 Node 上,那麼這些 Node 的得分就會比較高。
當然,為了避免這個算法引發排程堆疊,排程器在計算得分的時候還會根據鏡像的分布進行優化,即:如果大鏡像分布的節點數目很少,那麼這些節點的權重就會被調低,進而“對沖”掉引起排程堆疊的風險。