當一個 Pod 被排程時,Kubernetes 內部發生了什麼?

jxlwqq發表於2021-10-08

在 Kubernetes 中,排程是指將 Pod 放置到合適的 Node 上,然後對應 Node 上的 Kubelet 才能夠執行這些 Pod 。

kube-scheduler 是叢集控制平面的主要元件之一。Kubernetes 透過它來決定如何排程叢集中的 Pod。它會使用基於預選(斷言 predicate)和基於優選(優先順序 priority)的評分演算法,根據叢集中的約束以及使用者指定的約束來最佳化資源。

預選(過濾)

kube-scheduler 首先使用預選函式來制定排程策略,決定 Pod 可以在哪些節點上進行排程。它意味著一個硬性約束條件,因此函式的返回值為布林值。例如,一個 Pod 請求 10GB 的記憶體,而節點 A 的配置為 8 GB,那麼節點 A 將返回 false 並從 Pod 的候選排程節點中剔除。另一個例子是節點 B 被叢集管理員執行了 kubectl cordon node-b,被標記節點為不可排程,它也將會被排程決策直接剔除。

排程程式會根據限制條件和複雜性依次進行以下預選檢查,檢查順序儲存在一個名為 predicatesOrdering (順序斷言)的切片中:

var predicateOrdering = []string{
    CheckNodeUnschedulablePred,
    GeneralPred, HostNamePred, PodFitsHostPortsPred,
    MatchNodeSelectorPred, PodFitsResourcesPred, NoDiskConflictPred,
    PodToleratesNodeTaintsPred, CheckNodeLabelPresencePred,
    CheckServiceAffinityPred, MaxEBSVolumeCountPred, MaxGCEPDVolumeCountPred, MaxCSIVolumeCountPred,
    MaxAzureDiskVolumeCountPred, MaxCinderVolumeCountPred, CheckVolumeBindingPred, NoVolumeZoneConflictPred,
    EvenPodsSpreadPred, MatchInterPodAffinityPred,
}
  • CheckNodeUnschedulablePred:檢查節點是否可排程;
  • GeneralPred:一般性檢測,如檢測資源是否充足,Pod 的 Host、Port、Selector 是否匹配;
  • HostNamePred:檢測 Pod 指定的 Node 名稱是否和 Node 名稱相同;
  • PodFitsHostPortsPred:檢查 Pod 請求的埠(網路協議型別)在節點上是否可用;
  • MatchNodeSelectorPred:檢測是否匹配 NodeSelector 節點選擇器的設定;
  • PodFitsResourcesPred:檢查節點的空閒資源(例如,CPU 和記憶體)是否滿足 Pod 的要求;
  • NoDiskConflictPred:根據 Pod 請求的卷是否在節點上已經掛載,評估 Pod 和節點是否匹配;
  • PodToleratesNodeTaintsPred:檢查 Pod 的容忍是否能容忍節點的汙點;
  • CheckNodeLabelPresencePred:檢測 NodeLabel 是否存在;
  • CheckServiceAffinityPred:檢測服務的親和;
  • MaxEBSVolumeCountPred:已廢棄,檢測 Volume 數量是否超過雲服務商 AWS 的儲存服務的配置限制;
  • MaxGCEPDVolumeCountPred:已廢棄,檢測 Volume 數量是否是否超過雲服務商 Google Cloud 的儲存服務的配置限制;
  • MaxCSIVolumeCountPred:Pod 附加 CSI 卷的數量,判斷是否超過配置的限制;
  • MaxAzureDiskVolumeCountPred:已廢棄,檢測 Volume 數量是否超過雲服務商 Azure 的儲存服務的配置限制;
  • MaxCinderVolumeCountPred:已廢棄,檢測 Volume 數量是否超過雲服務商 OpenStack 的儲存服務的配置限制;
  • CheckVolumeBindingPred,:基於 Pod 的卷請求,評估 Pod 是否適合節點,這裡的捲包括繫結的和未繫結的 PVC 都適用;
  • NoVolumeZoneConflictPred:給定該儲存的故障區域限制, 評估 Pod 請求的卷在節點上是否可用;
  • EvenPodsSpreadPred:檢測 Node 是否滿足拓撲傳播限制;
  • MatchInterPodAffinityPred:檢測是否匹配 Pod 的親和與反親和的設定;

可以看出,Kubernetes 正在逐步移除某個具體雲服務商的服務的相關程式碼,而使用介面(Interface)來擴充套件功能。

優選(打分)

預選透過返回 true 或者 false 來表示節點是否參與排程,而優選則是根據優先順序的相對值對所有可排程節點進行排名,以下是為節點評分的優先順序列表:

  • EqualPriority:給予所有節點相等的權重;
  • MostRequestedPriority:支援最多請求資源的節點。 該策略將 Pod 排程到整體工作負載所需的最少的一組節點上;
  • RequestedToCapacityRatioPriority:使用預設的打分方法模型,建立基於 ResourceAllocationPriority 的 requestedToCapacity;
  • SelectorSpreadPriority:屬於同一 Service、 StatefulSet 或 ReplicaSet 的 Pod,儘可能地跨 Node 部署(雞蛋不要只放在一個籃子裡,分散風險,提高可用性);
  • ServiceSpreadingPriority:對於給定的 Service,此策略旨在確保該 Service 關聯的 Pod 在不同的節點上執行。 它偏向把 Pod 排程到沒有該服務的節點。 整體來看,Service 對於單個節點故障變得更具彈性;
  • InterPodAffinityPriority:實現了 Pod 間親和性與反親和性的優先順序;
  • LeastRequestedPriority:偏向最少請求資源的節點。 換句話說,節點上的 Pod 越多,使用的資源就越多,此策略給出的排名就越低;
  • BalancedResourceAllocation:偏向平衡資源使用的節點;
  • NodePreferAvoidPodsPriority:根據節點的註解 scheduler.alpha.kubernetes.io/preferAvoidPods 對節點進行優先順序排序。 你可以使用它來暗示兩個不同的 Pod 不應在同一節點上執行;
  • NodeAffinityPriority:根據節點親和中 PreferredDuringSchedulingIgnoredDuringExecution 欄位對節點進行優先順序排序;
  • TaintTolerationPriority:根據節點上無法忍受的汙點數量,給所有節點進行優先順序排序。 此策略會根據排序結果調整節點的等級;
  • ImageLocalityPriority:偏向已在本地快取 Pod 所需容器映象的節點;
  • EvenPodsSpreadPriority:實現了 Pod 拓撲擴充套件約束的優先順序排序;

這些分值將會累計為節點的總分,用來表明其優先順序。例如,如果一個 Pod 需要 1 個 cpu 核心的資源,而有兩個候選節點滿足這一要求,其中節點 A 有 2 個 CPU 核心可供分配,節點 B 有 4 個核心可供分配,則節點 B 將具有更高的優先順序。 如果多個節點返回相同的優先順序,排程程式將會使用輪循的方式來選擇節點。

最優解

kube-scheduler 使用基於預選和基於優選的評分演算法,理論上需要遍歷所有 Node(實際上有快取邏輯),而當叢集中的 Node 數量超過一定數量後,排程演算法的開銷將變得很大。所以 kube-scheduler 為了解決效能問題,引入了”全域性最優解”和”區域性最優解”兩種最優解。

  • 全域性最優解:遍歷叢集中的所有節點,找出全域性最優的節點;
  • 區域性最優解:只遍歷叢集中的部分節點,找出區域性最有的節點;

在小型叢集中(例如 100 個節點),使用全域性最優解。而在超大型叢集中(例如 5000 個節點)使用區域性最優解。

搶佔機制

Pod 可以設定優先順序(PriorityClass,注意:此處的 Pod 優先順序與優選演算法的優先順序評分不是一個概念)。 Pod 優先順序表示一個 Pod 相對於其他 Pod 的重要性。 如果一個 Pod 無法被排程,排程程式會嘗試搶佔(驅逐)較低優先順序的 Pod。

要使用優先順序和搶佔,需要:

  1. 新增 PriorityClass 物件,並設定 value 值;
  2. 將 Pod 的 Spec.priorityClassName 設定為上述新增的 PriorityClass;

上述設定了高優先順序的 Pod(暫稱為 pod-h) ,如果 kube-scheduler 沒有找到滿足其指定要求的節點,則觸發搶佔邏輯。搶佔邏輯試圖找到某個節點,在該節點中刪除/驅逐一個或多個優先順序低於 pod-h 的 Pod。被驅逐的 Pod 消失後,pod-h 可以被排程到該節點上。

更多

更多經典示例請參考:github.com/jxlwqq/kubernetes-examp...

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章