作者:zouyee,來源:微信公眾號DCOS
摘要
從CNCF基金會的成立,到Kubernetes社區蓬勃發展,歷經6載,17年異軍突起,在mesos、swarm等項目角逐中,拔得頭籌,繼而一統容器編排,其成功的關鍵原因可概括為以下幾點:
- 項目領導者們的堅守與遠見
- 社區的良好運作與社區文化
- 社區與企業落地的正反饋
雖然針對kubernetes的介紹已經比較多了,但是雲原生還是Kubernetes項目的發展都已經邁入深水區,因而今天zouyee為大家帶來《kubernetes調度系統系列文章》,希望通過接下來的五篇文章,讓各位能夠系統深入的了解kubernetes調度系統,該系列對應版本為1.20.+,今天帶來《K8S 調度系統由淺入深系列:簡介》
一、調度簡介
在開始前,先來看看Kubernetes的架構示意圖,其中控制平面包含以下三大組件:kube-scheduler、kube-apiserver、kube-controller-manager。kubelet及kube-proxy組件的分析我們后續單獨成章進行講解,現在我們可以簡單給理解上述組件的難易程度排個序,kube-apiserver、kubelet、kube-scheduler、kube-controller-manager、kube-proxy。

如上所述,kube-scheduler是K8S系統的核心組件之一,其主要負責Pod的調度,其監聽kube-apiserver,查詢未分配Node的Pod(未分配、分配失敗及嘗試多次無法分配),根據配置的調度策略,將Pod調度到最優的工作節點上,從而高效、合理的利用集群的資源,該特性是用戶選擇K8S系統的關鍵因素之一,幫助用戶提升效率、降低能耗。
kube-scheduler 負責將Pod 調度到集群內的最佳節點(基於相應策略計算出的最佳值)上,它監聽kube-apiserver,查詢還未分配節點 的 Pod,然后根據調度策略為這些 Pod 分配節點,執行綁定節點的操作(更新Pod的nodeName字段)。
在上述過程中,需要考慮以下問題:
- 如何確保節點分配的公平性
- 如何確保節點資源分配的高效性
- 如何確保Pod調度的公平性
- 如何確保Pod調度的高效性
- 如何擴展Pod調度策略
為解決上述的問題,kube-scheduler通過匯集節點資源、節點地域、節點鏡像、Pod調度等信息綜合決策,確保Pod分配到最佳節點,以下為kube-scheduler的主要目標:
- 公平性:在調度Pod時需要公平的決策,每個節點都有被分配的機會,調度器需要針對不同節點作出平衡決策。
- 資源高效:最大化提升所有可調度資源的利用率,使有限的CPU、內存等資源服務盡可能更多的Pod。
- 性能:能快速的完成對大規模Pod的調度工作,在集群規模擴增的情況下,依然能確保調度的性能。
- 靈活性:在實際生產中,用戶希望Pod的調度策略是可擴展的,從而可以定制化調度算法以處理復雜的實際問題。因此平台要允許多種調度器並行工作,並支持自定義調度器。
二、調度流程
首先我們通過下面的整體的交互圖,來構建Pod調度的直觀感受。

上述以創建一個Pod為例,簡要介紹調度流程:
- 用戶通過命令行創建Pod(選擇直接創建Pod而不是其他workload,是為了省略kube-controller-manager)
- kube-apiserver經過對象校驗、admission、quota等准入操作,寫入etcd
- kube-apiserver將結果返回給用戶
- 同時kube-scheduler一直監聽節點、Pod事件等(流程1)
- kube-scheduler將spec.nodeName的pod加入到調度隊列中,進行調度周期(該周期即位后續介紹內容)(流程2-3)
- kube-scheduler將pod與得分最高的節點進行binding操作(流程4)
- kube-apiserver將binding信息寫入etcd
- kubelet監聽分配給自己的Pod,調用CRI接口進行Pod創建(該部分內容后續出系列,進行介紹)
- kubelet創建Pod后,更新Pod狀態等信息,並向kube-apiserver上報
- kube-apiserver寫入數據
a. 調度周期
kube-scheduler的工作任務是根據各種調度算法將Pod綁定(bind)到最合適的工作節點,整個調度流程分為兩個階段:過濾和評分。流程示意圖如下所示。

注:以前稱之為predicate與priorities,當前統稱為過濾與評分,實際效果一致
過濾:輸入是所有節點,輸出是滿足預選條件的節點。kube-scheduler根據過濾策略過濾掉不滿足的節點。例如,如果某節點的資源不足或者不滿足預選策略的條件如“節點的標簽必須與Pod的Selector一致”時則無法通過過濾。
評分:輸入是通過過濾階段的節點,評分時會根據評分算法為通過過濾的節點進行打分,選擇得分最高的節點。例如,資源越充足、負載越小的節點可能具有越高的排名。
通俗點說,調度的過程就是在回答兩個問題:1)候選節點有哪些?2)其中最適合的是哪一個?
如果在過濾階段沒有節點滿足條件,Pod會一直處在Pending狀態直到出現滿足的節點,在此期間調度器會不斷的進行重試。如果有多個節點評分一致,那么kube-scheduler任意選擇其一。
注:Pod首先進入調度隊列,失敗后進入backoff,多次失敗后進入unschedule,該部分內容后續介紹。
b. 調度算法
當前支持兩種方式配置過濾、評分算法:
- Scheduling Policies:通過文件或者ConfigMap配置Predicate算法(過濾)和Priorities算法(評分)的算法
- Scheduling Profiles:當前調度系統為插拔架構,其將調度周期分為
QueueSort
、PreFilter
、Filter
、PreScore
、Score
、Reserve
、Permit
、PreBind
、Bind
、PostBind
等階段,通過定制調度周期中不同階段的插件行為來實現自定義。
下面簡單介紹一下通過Scheduling Policies方式配置(pkg/scheduler/framework/plugins/legacy_registry.go)
1)預選(Precates)
算法名稱 | 算法含義 |
---|---|
MatchInterPodAffinity | 檢查pod資源對象與其他pod資源對象是否符合親和性規則 |
CheckVolumeBinding | 檢查節點是否滿足pod資源對象的pvc掛載需求 |
GeneralPredicates | 檢查節點上pod資源對象數量的上線,以及CPU 內存 GPU等資源是否符合要求 |
HostName | 檢查Pod指定的NodeName是否匹配當前節點 |
PodFitsHostPorts | 檢查Pod容器所需的HostPort是否已被節點上其它容器或服務占用。如果已被占用,則禁止Pod調度到該節點 |
MatchNodeSelector | 檢查Pod的節點選擇器是否與節點的標簽匹配 |
PodFitsResources | 檢查節點是否有足夠空閑資源(例如CPU和內存)來滿足Pod的要求 |
NoDiskConflict | 檢查當前pod資源對象使用的卷是否與節點上其他的pod資源對象使用的卷沖突 |
PodToleratesNodeTaints | 如果當前節點被標記為taints,檢查pod資源對象是否能容忍node taints |
CheckNodeUnschedulable | 檢查節點是否可調度 |
CheckNodeLabelPresence | 檢查節點標簽是否存在 |
CheckServiceAffinity | 檢查服務親和性 |
MaxCSIVolumeCountPred | 如果設置了featuregate (attachvolumelimit)功能,檢查pod資源對象掛載的csi卷是否超出了節點上卷的最大掛載數量 |
NoVolumeZoneConflict | 檢查pod資源對象掛載pvc是否屬於跨區域掛載,因為gce的pd存儲或aws的ebs卷都不支持跨區域掛載 |
EvenPodsSpreadPred | 一組 Pod 在某個 TopologyKey 上的均衡打散需求 |
注:其中 MaxEBSVolumeCountPred、 MaxGCEPDVolumeCountPred MaxAzureDiskVolumeCountPred、MaxCinderVolumeCountPred 等雲廠商相關預選算法已經廢棄。
2)優選(Priorities)
算法名稱 | 算法含義 |
---|---|
EqualPriority | 節點權重相等 |
MostRequestedPriority | 偏向具有最多請求資源的節點。這個策略將把計划的Pods放到整個工作負載集所需的最小節點上運行。 |
RequestedToCapacityRatioPriority | 使用默認的資源評分函數模型創建基於ResourceAllocationPriority的requestedToCapacity。 |
SelectorSpreadPriority | 將屬於相同service rcs rss sts 的pod盡量調度在不同的節點上 |
ServiceSpreadingPriority | 對於給定的服務,此策略旨在確保Service的Pods運行在不同的節點上。總的結果是,Service對單個節點故障變得更有彈性。 |
InterPodAffinityPriority | 基於親和性(affinity)和反親和性(anti-affinity)計算分數 |
LeastRequestdPriority | 偏向使用較少請求資源的節點。換句話說,放置在節點上的Pod越多,這些Pod使用的資源越多,此策略給出的排名就越低。 |
BalancedRequestdPriority | 計算節點上cpu和內存的使用率,使用率最均衡的節點最優 |
NodePreferAvoidPodsPriority | 基於節點上定義的注釋(annotaion)記分,注釋中如果定義了alpha.kubernetes.io/preferAvoidPods則會禁用ReplicationController或者將ReplicaSet的pod資源對象調度在該節點上 |
NodeAffinityPriority | 基於節點親和性計算分數 |
TaintTolerationPriority | 基於污點(taint)和容忍度(toleration)是否匹配計算分數 |
ImageLocalityPriority | 基於節點上是否已經下拉了運行pod資源對象的鏡像計算分數 |
EvenPodsSpreadPriority | 用來指定一組符合條件的 Pod 在某個拓撲結構上的打散需求 |