網(wǎng)站首頁 編程語言 正文
kube-scheduler
是 kubernetes 系統(tǒng)的核心組件之一,主要負(fù)責(zé)整個集群資源的調(diào)度功能,根據(jù)特定的調(diào)度算法和策略,將 Pod 調(diào)度到最優(yōu)的工作節(jié)點(diǎn)上面去,從而更加合理、更加充分的利用集群的資源,這也是我們選擇使用 kubernetes 一個非常重要的理由。如果一門新的技術(shù)不能幫助企業(yè)節(jié)約成本、提供效率,我相信是很難推進(jìn)的。
調(diào)度流程
默認(rèn)情況下,kube-scheduler 提供的默認(rèn)調(diào)度器能夠滿足我們絕大多數(shù)的要求,我們前面和大家接觸的示例也基本上用的默認(rèn)的策略,都可以保證我們的 Pod 可以被分配到資源充足的節(jié)點(diǎn)上運(yùn)行。但是在實(shí)際的線上項目中,可能我們自己會比 kubernetes 更加了解我們自己的應(yīng)用,比如我們希望一個 Pod 只能運(yùn)行在特定的幾個節(jié)點(diǎn)上,或者這幾個節(jié)點(diǎn)只能用來運(yùn)行特定類型的應(yīng)用,這就需要我們的調(diào)度器能夠可控。
kube-scheduler
是 kubernetes 的調(diào)度器,它的主要作用就是根據(jù)特定的調(diào)度算法和調(diào)度策略將 Pod 調(diào)度到合適的 Node 節(jié)點(diǎn)上去,是一個獨(dú)立的二進(jìn)制程序,啟動之后會一直監(jiān)聽 API Server,獲取到 PodSpec.NodeName 為空的 Pod,對每個 Pod 都會創(chuàng)建一個 binding。
這個過程在我們看來好像比較簡單,但在實(shí)際的生產(chǎn)環(huán)境中,需要考慮的問題就有很多了:
- 如何保證全部的節(jié)點(diǎn)調(diào)度的公平性?要知道并不是說有節(jié)點(diǎn)資源配置都是一樣的
- 如何保證每個節(jié)點(diǎn)都能被分配資源?
- 集群資源如何能夠被高效利用?
- 集群資源如何才能被最大化使用?
- 如何保證 Pod 調(diào)度的性能和效率?
- 用戶是否可以根據(jù)自己的實(shí)際需求定制自己的調(diào)度策略?
考慮到實(shí)際環(huán)境中的各種復(fù)雜情況,kubernetes 的調(diào)度器采用插件化的形式實(shí)現(xiàn),可以方便用戶進(jìn)行定制或者二次開發(fā),我們可以自定義一個調(diào)度器并以插件形式和 kubernetes 進(jìn)行集成。
kubernetes 調(diào)度器的源碼位于 kubernetes/pkg/scheduler 中,大體的代碼目錄結(jié)構(gòu)如下所示:(不同的版本目錄結(jié)構(gòu)可能不太一樣)
kubernetes/pkg/scheduler
-- scheduler.go ? ? ? ? //調(diào)度相關(guān)的具體實(shí)現(xiàn)
|-- algorithm
| ? |-- predicates ? ? ?//節(jié)點(diǎn)篩選策略
| ? |-- priorities ? ? ?//節(jié)點(diǎn)打分策略
|-- algorithmprovider
| ? |-- defaults ? ? ? ? //定義默認(rèn)的調(diào)度器
其中 Scheduler 創(chuàng)建和運(yùn)行的核心程序,對應(yīng)的代碼在 pkg/scheduler/scheduler.go,如果要查看kube-scheduler
的入口程序,對應(yīng)的代碼在 cmd/kube-scheduler/scheduler.go。
調(diào)度主要分為以下幾個部分:
- 首先是預(yù)選過程,過濾掉不滿足條件的節(jié)點(diǎn),這個過程稱為
Predicates
- 然后是優(yōu)選過程,對通過的節(jié)點(diǎn)按照優(yōu)先級排序,稱之為
Priorities
- 最后從中選擇優(yōu)先級最高的節(jié)點(diǎn),如果中間任何一步驟有錯誤,就直接返回錯誤
Predicates
階段首先遍歷全部節(jié)點(diǎn),過濾掉不滿足條件的節(jié)點(diǎn),屬于強(qiáng)制性規(guī)則,這一階段輸出的所有滿足要求的 Node 將被記錄并作為第二階段的輸入,如果所有的節(jié)點(diǎn)都不滿足條件,那么 Pod 將會一直處于 Pending 狀態(tài),直到有節(jié)點(diǎn)滿足條件,在這期間調(diào)度器會不斷的重試。
所以我們在部署應(yīng)用的時候,如果發(fā)現(xiàn)有 Pod 一直處于 Pending 狀態(tài),那么就是沒有滿足調(diào)度條件的節(jié)點(diǎn),這個時候可以去檢查下節(jié)點(diǎn)資源是否可用。
Priorities
階段即再次對節(jié)點(diǎn)進(jìn)行篩選,如果有多個節(jié)點(diǎn)都滿足條件的話,那么系統(tǒng)會按照節(jié)點(diǎn)的優(yōu)先級(priorites)大小對節(jié)點(diǎn)進(jìn)行排序,最后選擇優(yōu)先級最高的節(jié)點(diǎn)來部署 Pod 應(yīng)用。
下面是調(diào)度過程的簡單示意圖:
更詳細(xì)的流程是這樣的:
首先,客戶端通過 API Server 的 REST API 或者 kubectl 工具創(chuàng)建 Pod 資源
API Server 收到用戶請求后,存儲相關(guān)數(shù)據(jù)到 etcd 數(shù)據(jù)庫中
調(diào)度器監(jiān)聽 API Server 查看為調(diào)度(bind)的 Pod 列表,循環(huán)遍歷地為每個 Pod 嘗試分配節(jié)點(diǎn),這個分配過程就是我們上面提到的兩個階段:
- 預(yù)選階段(Predicates),過濾節(jié)點(diǎn),調(diào)度器用一組規(guī)則過濾掉不符合要求的 Node 節(jié)點(diǎn),比如 Pod 設(shè)置了資源的 request,那么可用資源比 Pod 需要的資源少的主機(jī)顯然就會被過濾掉
- 優(yōu)選階段(Priorities),為節(jié)點(diǎn)的優(yōu)先級打分,將上一階段過濾出來的 Node 列表進(jìn)行打分,調(diào)度器會考慮一些整體的優(yōu)化策略,比如把 Deployment 控制的多個 Pod 副本分布到不同的主機(jī)上,使用最低負(fù)載的主機(jī)等等策略
經(jīng)過上面的階段過濾后選擇打分最高的 Node 節(jié)點(diǎn)和 Pod 進(jìn)行 binding 操作,然后將結(jié)果存儲到 etcd 中最后被選擇出來的 Node 節(jié)點(diǎn)對應(yīng)的 kubelet 去執(zhí)行創(chuàng)建 Pod 的相關(guān)操作
其中Predicates
過濾有一系列的算法可以使用,我們這里簡單列舉幾個:
- PodFitsResources:節(jié)點(diǎn)上剩余的資源是否大于 Pod 請求的資源
- PodFitsHost:如果 Pod 指定了 NodeName,檢查節(jié)點(diǎn)名稱是否和 NodeName 匹配
- PodFitsHostPorts:節(jié)點(diǎn)上已經(jīng)使用的 port 是否和 Pod 申請的 port 沖突
- PodSelectorMatches:過濾掉和 Pod 指定的 label 不匹配的節(jié)點(diǎn)
- NoDiskConflict:已經(jīng) mount 的 volume 和 Pod 指定的 volume 不沖突,除非它們都是只讀的
- CheckNodeDiskPressure:檢查節(jié)點(diǎn)磁盤空間是否符合要求
- CheckNodeMemoryPressure:檢查節(jié)點(diǎn)內(nèi)存是否夠用
除了這些過濾算法之外,還有一些其他的算法,更多更詳細(xì)的我們可以查看源碼文件:k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates.go。
而Priorities
優(yōu)先級是由一系列鍵值對組成的,鍵是該優(yōu)先級的名稱,值是它的權(quán)重值,同樣,我們這里給大家列舉幾個具有代表性的選項:
- LeastRequestedPriority:通過計算 CPU 和內(nèi)存的使用率來決定權(quán)重,使用率越低權(quán)重越高,當(dāng)然正常肯定也是資源是使用率越低權(quán)重越高,能給別的 Pod 運(yùn)行的可能性就越大
- SelectorSpreadPriority:為了更好的高可用,對同屬于一個 Deployment 或者 RC 下面的多個 Pod 副本,盡量調(diào)度到多個不同的節(jié)點(diǎn)上,當(dāng)一個 Pod 被調(diào)度的時候,會先去查找該 Pod 對應(yīng)的 controller,然后查看該 controller 下面的已存在的 Pod,運(yùn)行 Pod 越少的節(jié)點(diǎn)權(quán)重越高
- ImageLocalityPriority:就是如果在某個節(jié)點(diǎn)上已經(jīng)有要使用的鏡像節(jié)點(diǎn)了,鏡像總大小值越大,權(quán)重就越高
- NodeAffinityPriority:這個就是根據(jù)節(jié)點(diǎn)的親和性來計算一個權(quán)重值,后面我們會詳細(xì)講解親和性的使用方法
除了這些策略之外,還有很多其他的策略,同樣我們可以查看源碼文件:k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/ 了解更多信息。每一個優(yōu)先級函數(shù)會返回一個0-10的分?jǐn)?shù),分?jǐn)?shù)越高表示節(jié)點(diǎn)越優(yōu),同時每一個函數(shù)也會對應(yīng)一個表示權(quán)重的值。最終主機(jī)的得分用以下公式計算得出:
finalScoreNode = (weight1 * priorityFunc1) + (weight2 * priorityFunc2) + … + (weightn * priorityFuncn)
自定義調(diào)度
上面就是 kube-scheduler 默認(rèn)調(diào)度的基本流程,除了使用默認(rèn)的調(diào)度器之外,我們也可以自定義調(diào)度策略。
調(diào)度器擴(kuò)展
kube-scheduler
在啟動的時候可以通過 --policy-config-file
參數(shù)來指定調(diào)度策略文件,我們可以根據(jù)我們自己的需要來組裝Predicates
和Priority
函數(shù)。選擇不同的過濾函數(shù)和優(yōu)先級函數(shù)、控制優(yōu)先級函數(shù)的權(quán)重、調(diào)整過濾函數(shù)的順序都會影響調(diào)度過程。
下面是官方的 Policy 文件示例:
{ "kind" : "Policy", "apiVersion" : "v1", "predicates" : [ {"name" : "PodFitsHostPorts"}, {"name" : "PodFitsResources"}, {"name" : "NoDiskConflict"}, {"name" : "NoVolumeZoneConflict"}, {"name" : "MatchNodeSelector"}, {"name" : "HostName"} ], "priorities" : [ {"name" : "LeastRequestedPriority", "weight" : 1}, {"name" : "BalancedResourceAllocation", "weight" : 1}, {"name" : "ServiceSpreadingPriority", "weight" : 1}, {"name" : "EqualPriority", "weight" : 1} ] }
多調(diào)度器
如果默認(rèn)的調(diào)度器不滿足要求,還可以部署自定義的調(diào)度器。并且,在整個集群中還可以同時運(yùn)行多個調(diào)度器實(shí)例,通過 podSpec.schedulerName 來選擇使用哪一個調(diào)度器(默認(rèn)使用內(nèi)置的調(diào)度器)。
apiVersion: v1
kind: Pod
metadata:
? name: nginx
? labels:
? ? app: nginx
spec:
? schedulerName: my-scheduler ?# 選擇使用自定義調(diào)度器 my-scheduler
? containers:
? - name: nginx
? ? image: nginx:1.10
要開發(fā)我們自己的調(diào)度器也是比較容易的,比如我們這里的 my-scheduler:
- 首先需要通過指定的 API 獲取節(jié)點(diǎn)和 Pod
- 然后選擇
phase=Pending
和schedulerName=my-scheduler
的pod - 計算每個 Pod 需要放置的位置之后,調(diào)度程序?qū)?chuàng)建一個
Binding
- 對象然后根據(jù)我們自定義的調(diào)度器的算法計算出最適合的目標(biāo)節(jié)點(diǎn)
優(yōu)先級調(diào)度
與前面所講的調(diào)度優(yōu)選策略中的優(yōu)先級(Priorities)不同,前面所講的優(yōu)先級指的是節(jié)點(diǎn)優(yōu)先級,而我們這里所說的優(yōu)先級 pod priority 指的是 Pod 的優(yōu)先級,高優(yōu)先級的 Pod 會優(yōu)先被調(diào)度,或者在資源不足低情況犧牲低優(yōu)先級的 Pod,以便于重要的 Pod 能夠得到資源部署。
要定義 Pod 優(yōu)先級,就需要先定義PriorityClass
對象,該對象沒有 Namespace 的限制:
apiVersion: v1
kind: PriorityClass
metadata:
? name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."
其中:
-
value
為 32 位整數(shù)的優(yōu)先級,該值越大,優(yōu)先級越高 -
globalDefault
用于未配置 PriorityClassName 的 Pod,整個集群中應(yīng)該只有一個PriorityClass
將其設(shè)置為 true
然后通過在 Pod 的spec.priorityClassName
中指定已定義的PriorityClass
名稱即可:
apiVersion: v1
kind: Pod
metadata:
? name: nginx
? labels:
? ? app: nginx
spec:
? containers:
? - name: nginx
? ? image: nginx
? ? imagePullPolicy: IfNotPresent
? priorityClassName: high-priority
另外一個值得注意的是當(dāng)節(jié)點(diǎn)沒有足夠的資源供調(diào)度器調(diào)度 Pod,導(dǎo)致 Pod 處于 pending 時,搶占(preemption)邏輯就會被觸發(fā)。Preemption
會嘗試從一個節(jié)點(diǎn)刪除低優(yōu)先級的 Pod,從而釋放資源使高優(yōu)先級的 Pod 得到節(jié)點(diǎn)資源進(jìn)行部署。
現(xiàn)在我們通過下面的圖再去回顧下 kubernetes 的調(diào)度過程是不是就清晰很多了:
原文鏈接:https://blog.csdn.net/agonie201218/article/details/128234052
相關(guān)推薦
- 2023-03-19 C語言利用goto語句設(shè)計實(shí)現(xiàn)一個關(guān)機(jī)程序_C 語言
- 2022-07-28 Redis內(nèi)存碎片處理實(shí)例詳解_Redis
- 2022-07-21 配置nacos持久化
- 2022-12-19 Tensorflow加載與預(yù)處理數(shù)據(jù)詳解實(shí)現(xiàn)方法_python
- 2024-01-28 在已有g(shù)it倉庫的情況下,如何提交修改后的文件
- 2023-01-20 .Net執(zhí)行SQL存儲過程之易用輕量工具詳解_ASP.NET
- 2023-02-14 詳解C/C++?Linux出錯處理函數(shù)(strerror與perror)的使用_C 語言
- 2022-07-14 React父子組件傳值(組件通信)的實(shí)現(xiàn)方法_React
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支