“本文從 Pod 和節(jié)點(diǎn)的配置開始,介紹了 Kubernetes Scheduler 框架、擴(kuò)展點(diǎn)、API 以及可能發(fā)生的與資源相關(guān)的瓶頸,并展示了性能調(diào)整設(shè)置,涵蓋了 Kubernetes 中調(diào)度的大多方面。
Kubernetes Scheduler 是 Kubernetes 控制平面的核心組件之一。它在控制平面上運(yùn)行,將 Pod 分配給節(jié)點(diǎn),同時(shí)平衡節(jié)點(diǎn)之間的資源利用率。將 Pod 分配給新節(jié)點(diǎn)后,在該節(jié)點(diǎn)上運(yùn)行的 kubelet 會(huì)在 Kubernetes API 中檢索 Pod 定義,根據(jù)節(jié)點(diǎn)上的 Pod 規(guī)范創(chuàng)建資源和容器。換句話說,Scheduler 在控制平面內(nèi)運(yùn)行,并將工作負(fù)載分配給 Kubernetes 集群。
本文將對 Kubernetes Scheduler 進(jìn)行深入研究,首先概述一般的調(diào)度以及具有親和力(affinity)和 taint 的驅(qū)逐調(diào)度,然后討論調(diào)度程序的瓶頸以及生產(chǎn)中可能遇到的問題,最后研究如何微調(diào)調(diào)度程序的參數(shù)以適合集群。
調(diào)度簡介
Kubernetes 調(diào)度是將 Pod 分配給集群中匹配節(jié)點(diǎn)的過程。Scheduler 監(jiān)控新創(chuàng)建的 Pod,并為其分配最佳節(jié)點(diǎn)。它會(huì)根據(jù) Kubernetes 的調(diào)度原則和我們的配置選項(xiàng)選擇最佳節(jié)點(diǎn)。最簡單的配置選項(xiàng)是直接在 PodSpec 設(shè)置 nodeName:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: node-01
上面的 nginx pod 默認(rèn)情況下將在 node-01 上運(yùn)行,但是 nodeName 有許多限制導(dǎo)致無法正常運(yùn)行 Pod,例如云中節(jié)點(diǎn)名稱未知、資源節(jié)點(diǎn)不足以及節(jié)點(diǎn)網(wǎng)絡(luò)間歇性問題等。因此,除了測試或開發(fā)期間,我們最好不使用 nodeName。
如果要在一組特定的節(jié)點(diǎn)上運(yùn)行 Pod,可以使用 nodeSelector。我們在 PodSpec 中將 nodeSelector 定義為一組鍵值對:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeSelector:
disktype: ssd
對于上面的 nginx pod,Kubernetes Scheduler 將找到一個(gè)磁盤類型為 ssd 的節(jié)點(diǎn)。當(dāng)然,該節(jié)點(diǎn)可以具有其他標(biāo)簽。我們可以在 Kubernetes 參考文檔中查看標(biāo)簽的完整列表。
地址:https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/
使用 nodeSelector 有約束 Pod 可以在有特定標(biāo)簽的節(jié)點(diǎn)上運(yùn)行。但它的使用僅受標(biāo)簽及其值限制。Kubernetes 中有兩個(gè)更全面的功能來表達(dá)更復(fù)雜的調(diào)度需求:節(jié)點(diǎn)親和力(node affinity),標(biāo)記容器以將其吸引到一組節(jié)點(diǎn)上;taint 和 toleration,標(biāo)記節(jié)點(diǎn)以排斥 Pod。這些功能將在下面討論。
節(jié)點(diǎn)親和力
節(jié)點(diǎn)親和力(Node Affinity)是在 Pod 上定義的一組約束,用于確定哪些節(jié)點(diǎn)適合進(jìn)行調(diào)度,即使用親和性規(guī)則為 Pod 的節(jié)點(diǎn)分配定義硬性要求和軟性要求。例如可以將 Pod 配置為僅運(yùn)行帶有 GPU 的節(jié)點(diǎn),并且最好使用 NVIDIA_TESLA_V100 運(yùn)行深度學(xué)習(xí)工作負(fù)載。Scheduler 會(huì)評估規(guī)則,并在定義的約束內(nèi)找到合適的節(jié)點(diǎn)。與 nodeSelectors 相似,節(jié)點(diǎn)親和性規(guī)則可與節(jié)點(diǎn)標(biāo)簽一起使用,但它比 nodeSelectors 更強(qiáng)大。
我們可以為 podspec 添加四個(gè)相似性規(guī)則:
requiredDuringSchedulingIgnoredDuringExecution
requiredDuringSchedulingRequiredDuringExecution
preferredDuringSchedulingIgnoredDuringExecution
preferredDuringSchedulingRequiredDuringExecution
這四個(gè)規(guī)則由兩個(gè)條件組成:必需或首選條件,以及兩個(gè)階段:計(jì)劃和執(zhí)行。以 required 開頭的規(guī)則描述了必須滿足的嚴(yán)格要求。以 preferred 開頭的規(guī)則是軟性要求,將強(qiáng)制執(zhí)行但不能保證。調(diào)度階段是指將 Pod 首次分配給節(jié)點(diǎn)。執(zhí)行階段適用于在調(diào)度分配后節(jié)點(diǎn)標(biāo)簽發(fā)生更改的情況。
如果規(guī)則聲明為 IgnoredDuringExecution,Scheduler 在第一次分配后不會(huì)檢查其有效性。但如果使用 RequiredDuringExecution 指定了規(guī)則,Scheduler 會(huì)通過將容器移至合適的節(jié)點(diǎn)來確保規(guī)則的有效性。
以下是示例:
apiVersion: v1kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- us-east
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1
- us-east-2
containers:
- name: nginx
image: nginx
上面的 Nginx Pod 具有節(jié)點(diǎn)親和性規(guī)則,該規(guī)則讓 Kubernetes Scheduler 將 Pod 放置在 us-east 的節(jié)點(diǎn)上。第二條規(guī)則指示優(yōu)先使用 us-east-1 或 us-east-2。
使用親和性規(guī)則,我們可以讓 Kubernetes 調(diào)度決策適用于自定義需求。
Taint 與 Toleration
集群中并非所有 Kubernetes 節(jié)點(diǎn)都相同。某些節(jié)點(diǎn)可能具有特殊的硬件,例如 GPU、磁盤或網(wǎng)絡(luò)功能。同樣,我們可能需要將一些節(jié)點(diǎn)專用于測試、數(shù)據(jù)保護(hù)或用戶組。我們可以將 Taint 添加到節(jié)點(diǎn)以排斥 Pod,如以下示例所示:
kubectl taint nodes node1 test-environment=true:NoSchedule
使用 test-environment=true:NoScheduletaint 時(shí),除非在 podspec 具有匹配的 toleration,否則 Kubernetes Scheduler 將不會(huì)分配任何 pod:
apiVersion: v1kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
tolerations:
- key: “test-environment”
operator: “Exists”
effect: “NoSchedule”
taint 和 tolerations 共同發(fā)揮作用,讓 Kubernetes Scheduler 專用于某些節(jié)點(diǎn)并分配特定 Pod。
調(diào)度瓶頸
盡管 Kubernetes Scheduler 能選擇最佳節(jié)點(diǎn),但是在 Pod 開始運(yùn)行之后,“最佳節(jié)點(diǎn)”可能會(huì)改變。所以從長遠(yuǎn)來看,Pod 的資源使用及其節(jié)點(diǎn)分配可能存在問題。
資源請求(Request)和限制(Limit):“Noisy Neighbor”
“Noisy Neighbor”并不特定于 Kubernetes。任何多租戶系統(tǒng)都是它們的潛在地。假設(shè)有兩個(gè)容器 A 和 B,它們在同一節(jié)點(diǎn)上運(yùn)行。如果 Pod B 試圖通過消耗所有 CPU 或內(nèi)存來創(chuàng)造 noise,Pod A 將出現(xiàn)問題。如果我們?yōu)槿萜髟O(shè)置了資源請求和限制就能控制住 neighbor。Kubernetes 將確保為容器安排其請求的資源,并且不會(huì)消耗超出其資源限制的資源。如果在生產(chǎn)中運(yùn)行 Kubernetes,最好設(shè)置資源請求和限制以確保系統(tǒng)可靠。
系統(tǒng)進(jìn)程資源不足
Kubernetes 節(jié)點(diǎn)主要是連接到 Kubernetes 控制平面的虛擬機(jī)。因此,節(jié)點(diǎn)上也有自己的操作系統(tǒng)和相關(guān)進(jìn)程。如果 Kubernetes 工作負(fù)載消耗了所有資源,則這些節(jié)點(diǎn)將無法運(yùn)行,并會(huì)發(fā)生各種問題問題。我們需要在 kubelet 中使用 –system -reserved 設(shè)置保留資源,以防止發(fā)生這種情況。
搶占或調(diào)度 Pod
如果 Kubernetes Scheduler 無法將 Pod 調(diào)度到可用節(jié)點(diǎn),則可以從節(jié)點(diǎn)搶占(preempt)或驅(qū)逐(evict)一些 Pod 以分配資源。如果看到 Pod 在集群中移動(dòng)而沒有發(fā)現(xiàn)特定原因,可以使用優(yōu)先級類對其進(jìn)行定義。同樣,如果沒有調(diào)度好 Pod,并且正在等待其他 Pod,也需要檢查其優(yōu)先級。
以下是示例:
apiVersion: scheduling.k8s.io/v1kind: PriorityClass
metadata:
name: high-priority-nonpreempting
value: 100000preemptionPolicy: NeverglobalDefault: false
description: “This priority class will not preempt other pods.”
可以通過以下方式在 podspec 中為分配優(yōu)先級:
apiVersion: v1kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
priorityClassName: high-priority-nonpreempting
調(diào)度框架
Kubernetes Scheduler 具有可插拔的調(diào)度框架架構(gòu),可向框架添加一組新的插件。插件實(shí)現(xiàn) Plugin API,并被編譯到調(diào)度程序中。下面我們將討論調(diào)度框架的工作流、擴(kuò)展點(diǎn)和 Plugin API。
工作流和擴(kuò)展點(diǎn)
調(diào)度 Pod 包括兩個(gè)階段:調(diào)度周期(scheduling cycle)和綁定周期(binding cycle)。在調(diào)度周期中,Scheduler 會(huì)找到一個(gè)可用節(jié)點(diǎn),然后在綁定過程中,將決策應(yīng)用于集群。
工作流中的以下幾點(diǎn)對插件擴(kuò)展開放:
QueueSort:對隊(duì)列中的 Pod 進(jìn)行排序
PreFilter:檢查預(yù)處理 Pod 的相關(guān)信息以安排調(diào)度周期
Filter:過濾不適合該 Pod 的節(jié)點(diǎn)
PostFilter:如果找不到可用于 Pod 的可行節(jié)點(diǎn),調(diào)用該插件
PreScore:運(yùn)行 PreScore 任務(wù)以生成一個(gè)可共享狀態(tài)供 Score 插件使用
Score:通過調(diào)用每個(gè) Score 插件對過濾的節(jié)點(diǎn)進(jìn)行排名
NormalizeScore:合并分?jǐn)?shù)并計(jì)算節(jié)點(diǎn)的最終排名
Reserve:在綁定周期之前選擇保留的節(jié)點(diǎn)
Permit:批準(zhǔn)或拒絕調(diào)度周期結(jié)果
PreBind:執(zhí)行任何先決條件工作,例如配置網(wǎng)絡(luò)卷
Bind:將 Pod 分配給 Kubernetes API 中的節(jié)點(diǎn)
PostBind:通知綁定周期的結(jié)果
插件擴(kuò)展實(shí)現(xiàn)了 Plugin API,是 Kubernetes Scheduler 的一部分。我們可以在 Kubernetes 存儲(chǔ)庫中檢查。插件應(yīng)使用以下名稱進(jìn)行注冊:
// Plugin is the parent type for all the scheduling framework plugins.
type Plugin interface {
Name() string
}
插件還實(shí)現(xiàn)了相關(guān)的擴(kuò)展點(diǎn),如下所示:
// QueueSortPlugin is an interface that must be implemented by “QueueSort” plugins.
// These plugins are used to sort pods in the scheduling queue. Only one queue sort plugin may be enabled at a time.
type QueueSortPlugin interface {
Plugin
// Less are used to sort pods in the scheduling queue.
Less(*QueuedPodInfo, *QueuedPodInfo) bool
}
Scheduler 性能調(diào)整
Kubernetes Scheduler 有一個(gè)工作流來查找和綁定 Pod 的可行節(jié)點(diǎn)。當(dāng)集群中的節(jié)點(diǎn)數(shù)量非常多時(shí),Scheduler 的工作量將成倍增加。在大型集群中,可能需要很長時(shí)間才能找到最佳節(jié)點(diǎn),因此要微調(diào)調(diào)度程序的性能,以在延遲和準(zhǔn)確性之間找到折中方案。
percentageOfNodesToScore 將限制節(jié)點(diǎn)的數(shù)量來計(jì)算自己的分?jǐn)?shù)。默認(rèn)情況下,Kubernetes 在 100 節(jié)點(diǎn)集群的 50% 和 5000 節(jié)點(diǎn)集群的 10% 之間設(shè)置線性閾值。默認(rèn)最小值為 5%,它要確保至少考慮集群中 5% 節(jié)點(diǎn)的調(diào)度。
下面的示例展示了如何通過性能調(diào)整 kube-scheduler 來手動(dòng)設(shè)置閾值:
apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
algorithmSource:
provider: DefaultProvider
percentageOfNodesToScore: 50
如果有一個(gè)龐大的集群并且 Kubernetes 工作負(fù)載不能承受 Kubernetes Scheduler 引起的延遲,那么更改百分比是個(gè)好主意。
總結(jié)
本文涵蓋了 Kubernetes 調(diào)度的大多方面,從 Pod 和節(jié)點(diǎn)的配置開始,包括 nodeSelector、親和性規(guī)則、taint 和 toleration,然后介紹了 Kubernetes Scheduler 框架、擴(kuò)展點(diǎn)、API 以及可能發(fā)生的與資源相關(guān)的瓶頸,最后展示了性能調(diào)整設(shè)置。盡管 Kubernetes Scheduler 能簡單地將 Pod 分配給節(jié)點(diǎn),但是了解其動(dòng)態(tài)性并對其進(jìn)行配置以實(shí)現(xiàn)可靠的生產(chǎn)級 Kubernetes 設(shè)置至關(guān)重要。
原文鏈接:https://thenewstack.io/a-deep-dive-into-kubernetes-scheduling/
作者:Ron Sobol. 翻譯:Bach(才云)
校對:星空下的文仔(才云)、bot(才云)
責(zé)任編輯:haq
-
kubernetes
+關(guān)注
關(guān)注
0文章
224瀏覽量
8712
原文標(biāo)題:Kubernetes 調(diào)度詳解
文章出處:【微信號:aming_linux,微信公眾號:阿銘linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論