天天看點

Kubernetes必備知識: 排程流程

所屬技術領域:

K8s

|名詞定義|

scheduler 是k8s master的一部分,作為插件存在于k8s生态體系。

|技術特點|

 排程流水線

通過 Informer 将需要排程的 Pod 插入 Queue 中,Pipeline 會循環從 Queue Pop 等待排程的 Pod 放入 Pipeline 執行。

排程流水線 (Schedule Pipeline) 主要有三個階段:Scheduler Thread,Wait Thread,Bind Thread。

 Scheduler Thread 階段: 從如上的架構圖可以看到 Schduler Thread 會經曆 Pre Filter -> Filter -> Post Filter-> Score -> Reserve,可以簡單了解為 Filter -> Score -> Reserve;Filter 階段用于選擇符合 Pod Spec 描述的 Nodes;Score 階段用于從 Filter 過後的 Nodes 進行打分和排序;Reserve 階段将 Pod 跟排序後的最優 Node 的 NodeCache 中,表示這個 Pod 已經配置設定到這個 Node 上, 讓下一個等待排程的 Pod 對這個 Node 進行 Filter 和 Score 的時候能看到剛才配置設定的 Pod。

 Wait Thread 階段: 這個階段可以用來等待 Pod 關聯的資源的 Ready 等待,例如等待 PVC 的 PV 建立成功,或者 Gang 排程中等待關聯的 Pod 排程成功等等;

 Bind Thread 階段: 用于将 Pod 和 Node 的關聯持久化 Kube APIServer。

整個排程流水線隻有在 Scheduler Thread 階段是串行的一個 Pod 一個 Pod 的進行排程,在 Wait 和 Bind 階段 Pod 都是異步并行執行。

 排程詳細流程

Kubernetes必備知識: 排程流程

SchedulingQueue 有三個子隊列:activeQ、backoffQ、unschedulableQ。

Scheduler 啟動的時候所有等待被排程的 Pod 都會進入 activieQ,activeQ 會按照 Pod 的 priority 進行排序,Scheduler Pipepline 會從 activeQ 擷取一個 Pod 進行 Pipeline 執行排程流程,當排程失敗之後會直接根據情況選擇進入 unschedulableQ 或者 backoffQ,如果在目前 Pod 排程期間 Node Cache、Pod Cache 等 Scheduler Cache 有變化就進入 backoffQ,否則進入 unschedulableQ。

unschedulableQ 會定期較長時間(例如 60 秒)刷入 activeQ 或者 backoffQ,或者在 Scheduler Cache 發生變化的時候觸發關聯的 Pod 刷入 activeQ 或者 backoffQ;backoffQ 會以 backoff 機制相比 unschedulableQ 比較快地讓待排程的 Pod 進入 activeQ 進行重新排程。

接着詳細介紹 Scheduler Thread 階段,在 Scheduler Pipeline 拿到一個等待排程的 Pod,會從 NodeCache 裡面拿到相關的 Node 執行 Filter 邏輯比對,這從 NodeCache 周遊 Node 的過程有一個空間算法上的優化,簡單可以概括為在避免過濾所有節點的同時考慮了排程的容災取樣排程。

具體的優化算法邏輯(有興趣的同學可以看 node_tree.go 的 Next 方法):在 NodeCache 中,Node 是按照 zone 進行分堆。在 filter 階段的時候,為會 NodeCache 維護一個 zondeIndex,每 Pop 一個 Node 進行過濾,zoneIndex 往後挪一個位置,然後從該 zone 的 node 清單中取一個 node 出來。

可以看到上圖縱軸有一個 nodeIndex,每次也會自增。如果目前 zone 的節點無資料,那就會從下一個 zone 中拿資料。

大概的流程就是 zoneIndex 從左向右,nodeIndex 從上到下,保證拿到的 Node 節點是按照 zone 打散,進而實作避免過濾所有節點的同時考慮了節點的 az 均衡部署。(最新 release-v.1.17 的版本已經取消這種算法,為什麼取消應該是沒有考慮 Pod 的 prefer 和 node 的 prefer,沒有實作 Pod 的 Spec 要求)

取樣排程裡面的取樣規模這裡簡單介紹一下,預設的取樣比率公式 = Max (5, 50 - 叢集的 node 數 / 125),取樣規模 = Max (100, 叢集 Node 數*取樣比率)。

這裡舉個例子:節點規模為 3000 個節點,那麼取樣比例 = Max (5, 50 - 3000/125) = 26%,那麼取樣規模 = Max (100, 3000* 0.26) = 780,在排程流水線裡面,Filter 隻要比對到 780 個候選節點,就可以停止 Filter 流程,走到 Score 階段。

Score 階段依據 Policy 配置的算分插件,進行排序,分數最高的節點作為 SelectHost。接着将這個 Pod 配置設定到這個 Node 上,這個過程叫做 Reserver 階段可以稱為賬本預占。預占的過程修改 Pod 在 PodCache 的狀态為 Assumed 的狀态(處于記憶體态)。

排程過程涉及到 Pod 狀态機的生命周期,這裡簡單介紹下 Pod 的幾個主要狀态: Initial(虛拟狀态)->Assumed(Reserver)->Added->Deleted(虛拟狀态); 當通過 Informer watch 到 Pod 資料已經确定配置設定到這個節點的時候,才會把 Pod 的狀态變成 Added。

選中完節點在 Bind 的時候,有可能會 Bind 失敗,在 Bind 失敗的時候會做回退,就是把預占用的賬本做 Assumed 的資料退回 Initial,也就是把 Assumed 狀态擦除,從 Node 裡面把 Pod 賬本清除。

如果 Bind 失敗,會把 Pod 重新丢回到 unschedulableQ 隊列裡面。在排程隊列中,什麼情況下 Pod 會到 backoffQ 中呢?這是一個很細節的點。

如果在這麼一個排程周期裡面,Cache 發生了變化,會把 Pod 放到 backoffQ 裡面。在 backoffQ 裡面等待的時間會比在 unschedulableQ 裡面時間更短,backoffQ 裡有一個降級政策,是 2 的指數次幂降級。假設重試第一次為 1s,那第二次就是 2s,第三次就是 4s,第四次就是 8s,最大到 10s。

|資料來源|

名詞定義:

https://blog.csdn.net/yevvzi/article/details/79858170

繼續閱讀