天天看點

Kubernetes 排程詳解

本文從 Pod 和節點的配置開始,介紹了 Kubernetes Scheduler 架構、擴充點、API 以及可能發生的與資源相關的瓶頸,并展示了性能調整設定,涵蓋了 Kubernetes 中排程的大多方面。

Kubernetes Scheduler 是 Kubernetes 控制平面的核心元件之一。它在控制平面上運作,将 Pod 配置設定給節點,同時平衡節點之間的資源使用率。将 Pod 配置設定給新節點後,在該節點上運作的 kubelet 會在 Kubernetes API 中檢索 Pod 定義,根據節點上的 Pod 規範建立資源和容器。換句話說,Scheduler 在控制平面内運作,并将工作負載配置設定給 Kubernetes 叢集。

本文将對 Kubernetes Scheduler 進行深入研究,首先概述一般的排程以及具有親和力(affinity)和 taint 的驅逐排程,然後讨論排程程式的瓶頸以及生産中可能遇到的問題,最後研究如何微調排程程式的參數以适合叢集。

Kubernetes 排程是将 Pod 配置設定給叢集中比對節點的過程。Scheduler 監控新建立的 Pod,并為其配置設定最佳節點。它會根據 Kubernetes 的排程原則和我們的配置選項選擇最佳節點。最簡單的配置選項是直接在 PodSpec 設定 nodeName:

上面的 nginx pod 預設情況下将在 node-01 上運作,但是 nodeName 有許多限制導緻無法正常運作 Pod,例如雲中節點名稱未知、資源節點不足以及節點網絡間歇性問題等。是以,除了測試或開發期間,我們最好不使用 nodeName。

如果要在一組特定的節點上運作 Pod,可以使用 nodeSelector。我們在 PodSpec 中将 nodeSelector 定義為一組鍵值對:

對于上面的 nginx pod,Kubernetes Scheduler 将找到一個磁盤類型為 ssd 的節點。當然,該節點可以具有其他标簽。我們可以在 Kubernetes 參考文檔中檢視标簽的完整清單。

位址:https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/

使用 nodeSelector 有限制 Pod 可以在有特定标簽的節點上運作。但它的使用僅受标簽及其值限制。Kubernetes 中有兩個更全面的功能來表達更複雜的排程需求:節點親和力(node affinity),标記容器以将其吸引到一組節點上;taint 和 toleration,标記節點以排斥 Pod。這些功能将在下面讨論。

節點親和力(Node Affinity)是在 Pod 上定義的一組限制,用于确定哪些節點适合進行排程,即使用親和性規則為 Pod 的節點配置設定定義硬性要求和軟性要求。例如可以将 Pod 配置為僅運作帶有 GPU 的節點,并且最好使用 NVIDIA_TESLA_V100 運作深度學習工作負載。Scheduler 會評估規則,并在定義的限制内找到合适的節點。與 nodeSelectors 相似,節點親和性規則可與節點标簽一起使用,但它比 nodeSelectors 更強大。

我們可以為 podspec 添加四個相似性規則:

requiredDuringSchedulingIgnoredDuringExecution

requiredDuringSchedulingRequiredDuringExecution

preferredDuringSchedulingIgnoredDuringExecution

preferredDuringSchedulingRequiredDuringExecution

這四個規則由兩個條件組成:必需或首選條件,以及兩個階段:計劃和執行。以 required 開頭的規則描述了必須滿足的嚴格要求。以 preferred 開頭的規則是軟性要求,将強制執行但不能保證。排程階段是指将 Pod 首次配置設定給節點。執行階段适用于在排程配置設定後節點标簽發生更改的情況。

如果規則聲明為 IgnoredDuringExecution,Scheduler 在第一次配置設定後不會檢查其有效性。但如果使用 RequiredDuringExecution 指定了規則,Scheduler 會通過将容器移至合适的節點來確定規則的有效性。

以下是示例:

上面的 Nginx Pod 具有節點親和性規則,該規則讓 Kubernetes Scheduler 将 Pod 放置在 us-east 的節點上。第二條規則訓示優先使用 us-east-1 或 us-east-2。

使用親和性規則,我們可以讓 Kubernetes 排程決策适用于自定義需求。

叢集中并非所有 Kubernetes 節點都相同。某些節點可能具有特殊的硬體,例如 GPU、磁盤或網絡功能。同樣,我們可能需要将一些節點專用于測試、資料保護或使用者組。我們可以将 Taint 添加到節點以排斥 Pod,如以下示例所示:

使用 test-environment=true:NoScheduletaint 時,除非在 podspec 具有比對的 toleration,否則 Kubernetes Scheduler 将不會配置設定任何 pod:

taint 和 tolerations 共同發揮作用,讓 Kubernetes Scheduler 專用于某些節點并配置設定特定 Pod。

盡管 Kubernetes Scheduler 能選擇最佳節點,但是在 Pod 開始運作之後,“最佳節點”可能會改變。是以從長遠來看,Pod 的資源使用及其節點配置設定可能存在問題。

“Noisy Neighbor”并不特定于 Kubernetes。任何多租戶系統都是它們的潛在地。假設有兩個容器 A 和 B,它們在同一節點上運作。如果 Pod B 試圖通過消耗所有 CPU 或記憶體來創造 noise,Pod A 将出現問題。如果我們為容器設定了資源請求和限制就能控制住 neighbor。Kubernetes 将確定為容器安排其請求的資源,并且不會消耗超出其資源限制的資源。如果在生産中運作 Kubernetes,最好設定資源請求和限制以確定系統可靠。

Kubernetes 節點主要是連接配接到 Kubernetes 控制平面的虛拟機。是以,節點上也有自己的作業系統和相關程序。如果 Kubernetes 工作負載消耗了所有資源,則這些節點将無法運作,并會發生各種問題問題。我們需要在 kubelet 中使用 –system -reserved 設定保留資源,以防止發生這種情況。

如果 Kubernetes Scheduler 無法将 Pod 排程到可用節點,則可以從節點搶占(preempt)或驅逐(evict)一些 Pod 以配置設定資源。如果看到 Pod 在叢集中移動而沒有發現特定原因,可以使用優先級類對其進行定義。同樣,如果沒有排程好 Pod,并且正在等待其他 Pod,也需要檢查其優先級。

可以通過以下方式在 podspec 中為配置設定優先級:

Kubernetes Scheduler 具有可插拔的排程架構架構,可向架構添加一組新的插件。插件實作 Plugin API,并被編譯到排程程式中。下面我們将讨論排程架構的工作流、擴充點和 Plugin API。

排程 Pod 包括兩個階段:排程周期(scheduling cycle)和綁定周期(binding cycle)。在排程周期中,Scheduler 會找到一個可用節點,然後在綁定過程中,将決策應用于叢集。

下圖說明了階段和擴充點的流程:

工作流中的以下幾點對插件擴充開放:

QueueSort:對隊列中的 Pod 進行排序

PreFilter:檢查預處理 Pod 的相關資訊以安排排程周期

Filter:過濾不适合該 Pod 的節點

PostFilter:如果找不到可用于 Pod 的可行節點,調用該插件

PreScore:運作 PreScore 任務以生成一個可共享狀态供 Score 插件使用

Score:通過調用每個 Score 插件對過濾的節點進行排名

NormalizeScore:合并分數并計算節點的最終排名

Reserve:在綁定周期之前選擇保留的節點

Permit:準許或拒絕排程周期結果

PreBind:執行任何先決條件工作,例如配置網絡卷

Bind:将 Pod 配置設定給 Kubernetes API 中的節點

PostBind:通知綁定周期的結果

插件擴充實作了 Plugin API,是 Kubernetes Scheduler 的一部分。我們可以在 Kubernetes 存儲庫中檢查。插件應使用以下名稱進行注冊:

插件還實作了相關的擴充點,如下所示:

Kubernetes Scheduler 有一個工作流來查找和綁定 Pod 的可行節點。當叢集中的節點數量非常多時,Scheduler 的工作量将成倍增加。在大型叢集中,可能需要很長時間才能找到最佳節點,是以要微調排程程式的性能,以在延遲和準确性之間找到折中方案。

percentageOfNodesToScore 将限制節點的數量來計算自己的分數。預設情況下,Kubernetes 在 100 節點叢集的 50% 和 5000 節點叢集的 10% 之間設定線性門檻值。預設最小值為 5%,它要確定至少考慮叢集中 5% 節點的排程。

下面的示例展示了如何通過性能調整 kube-scheduler 來手動設定門檻值:

如果有一個龐大的叢集并且 Kubernetes 工作負載不能承受 Kubernetes Scheduler 引起的延遲,那麼更改百分比是個好主意。

本文涵蓋了 Kubernetes 排程的大多方面,從 Pod 和節點的配置開始,包括 nodeSelector、親和性規則、taint 和 toleration,然後介紹了 Kubernetes Scheduler 架構、擴充點、API 以及可能發生的與資源相關的瓶頸,最後展示了性能調整設定。盡管 Kubernetes Scheduler 能簡單地将 Pod 配置設定給節點,但是了解其動态性并對其進行配置以實作可靠的生産級 Kubernetes 設定至關重要。

原文連結:https://thenewstack.io/a-deep-dive-into-kubernetes-scheduling/

k8s

繼續閱讀