溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么進行Kubernetes集群調度器原理剖析及思考

發布時間:2021-11-22 17:03:14 來源:億速云 閱讀:181 作者:柒染 欄目:云計算

這篇文章將為大家詳細講解有關怎么進行Kubernetes集群調度器原理剖析及思考,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

云環境或者計算倉庫級別(將整個數據中心當做單個計算池)的集群管理系統通常會定義出工作負載的規范,并使用調度器將工作負載放置到集群恰當的位置。好的調度器可以讓集群的工作處理更高效,同時提高資源利用率,節省能源開銷。

通用調度器,如Kubernetes原生調度器Scheduler實現了根據特定的調度算法和策略將pod調度到指定的計算節點(Node)上。但實際上設計大規模共享集群的調度器并不是一件容易的事情。調度器不僅要了解集群資源的使用和分布情況,還要兼顧任務分配速度和執行效率。過度設計的調度器屏蔽了太多的技術實現,以至于無法按照預期完成調度任務,或導致異常情況的發生,不恰當的調度器的選擇同樣會降低工作效率,或導致調度任務無法完成。

本文主要從設計原理、代碼實現兩個層面介紹Kubernetes的調度器以及社區對其的補充加強,同時對業界常用調度器的設計實現進行比較分析。通過本文,讀者可了解調度器的來龍去脈,從而為選擇甚至設計實現適合實際場景的調度器打下基礎。

注明:本文中代碼基于v1.11版本Kubernetes進行分析,如有不當之處,歡迎指正!

調度器的基本知識

1.1 調度器的定義

通用調度的定義是指基于某種方法將某項任務分配到特定資源以完成相關工作,其中任務可以是虛擬計算元素,如線程、進程或數據流,特定資源一般是指處理器、網絡、磁盤等,調度器則是完成這些調度行為的具體實現。使用調度器的目的是實現用戶共享系統資源的同時,降低等待時間,提高吞吐率以及資源利用率。

本文中我們討論的調度器是指大規模集群下調度任務的實現,比較典型的有Mesos/Yarn(Apache)、Borg/Omega(Google)、Quincy(Microsoft)等。構建大規模集群(如數據中心規模)的成本非常之高,因此精心設計調度器就顯得尤為重要。

常見類型的調度器的對比分析如下表1所示:

怎么進行Kubernetes集群調度器原理剖析及思考

1.2 調度器的考量標準

我們首先思考一下調度器是根據哪些信息來進行調度工作的,以及哪些指標可以用來衡量調度工作質量。

調度器的主要工作是將資源需求與資源提供方做全局最優的匹配。所以一方面調度器的設計需要了解不同類型的資源拓撲,另一方面還需要對工作負載有充分的認識。

了解不同類型的資源拓撲,充分掌握環境拓撲信息能夠使調度工作更充分的利用資源(如經常訪問數據的任務如果距數據近可以顯著減少執行時間),并且可以基于資源拓撲信息定義更加復雜的策略。但全局資源信息的維護消耗會限制集群的整體規模和調度執行時間,這也讓調度器難以擴展,從而限制集群規模。

另一方面,由于不同類型的工作負載會有不同的甚至截然相反的特性,調度器還需要對工作負載有充分的認識,例如服務類任務,資源需求少,運行時間長,對調度時間并不敏感;而批處理類任務,資源需求大,運行時間短,任務可能相關,對調度時間要求較高。 同時,調度器也要滿足使用方的特殊要求。如任務盡量集中或者分散,保證多個任務同時進行等。

總的來說,好的調度器需要平衡好單次調度(調度時間,質量),同時要考慮到環境變化對調度結果的影響,保持結果最優(必要時重新調度),保證集群規模,同時還要能夠支持用戶無感知的升級和擴展。調度的結果需要滿足但不限于下列條件,并最大可能滿足盡可能優先級較高的條件:

資源使用率最大化

滿足用戶指定的調度需求

滿足自定義優先級要求

調度效率高,能夠根據資源情況快速做出決策

能夠根據負載的變化調整調度策略

充分考慮各種層級的公平性

1.3 鎖對調度器設計的影響

對于資源的調度,一定會涉及到鎖的應用,不同類型鎖的選擇將直接決定調度器的使用場景。類似Mesos等兩層調度器,一般采用悲觀鎖的設計實現方式,當資源全部滿足任務需要時啟動任務,否則將增量繼續申請更多的資源直到調度條件滿足;而共享狀態的調度器,會考慮使用樂觀鎖的實現方式,Kubernetes默認調度器是基于樂觀鎖進行設計的。

我們首先通過一個簡單的例子,比較下悲觀鎖和樂觀鎖處理邏輯的不同,假設有如下的一個場景:

作業A讀取對象O

作業B讀取對象O

作業A在內存中更新對象O

作業B在內存中更新對象O

作業A寫入對象O實現持久化

作業B寫入對象O實現持久化

悲觀鎖的設計是對對象O實現獨占鎖,直到作業A完成對對象O的更新并寫入持久化數據之前,阻斷其他讀取請求。樂觀鎖的設計是對對象O實現共享鎖,假設所有的工作都能夠正常完成,直到有沖突產生,記錄沖突的發生并拒絕沖突的請求。

樂觀鎖一般會結合資源版本實現,同樣是上述中的例子,當前對象O的版本為v1,作業A首先完成對對象O的寫入持久化操作,并標記對象O的版本為v2,作業B在更新時發現對象版本已經變化,則會取消更改。

Kubernetes調度器剖析

Kubernetes中的計算任務大多通過pod來承載運行。pod是用戶定義的一個或多個共享存儲、網絡和命名空間資源的容器的組合,是調度器可調度的最小單元。Kubernetes的調度器是控制平面的一部分,它主要監聽APIServer提供的pod任務列表,獲取待調度pod,根據預選和優選策略,為這些pod分配運行的節點。概括來說,調度器主要依據資源消耗的描述得到一個調度結果。

2.1 Kubernetes調度器的設計

Kubernetes的調度設計參考了Omega的實現,主要采用兩層調度架構,基于全局狀態進行調度,通過樂觀鎖控制資源歸屬,同時支持多調度器的設計。

兩層架構幫助調度器屏蔽了很多底層實現細節,將策略和限制分別實現,同時過濾可用資源,讓調度器能夠更靈活適應資源變化,滿足用戶個性化的調度需求。相比單體架構而言,不僅更容易添加自定義規則、支持集群動態伸縮,同時對大規模集群有更好的支持(支持多調度器)。

相比于使用悲觀鎖和部分環境視圖的架構(如Mesos),基于全局狀態和樂觀鎖實現的好處是調度器可以看到集群所有可以支配的資源,然后搶占低優先級任務的資源,以達到策略要求的狀態。它的資源分配更符合策略要求,避免了作業囤積資源導致集群死鎖的問題。當然這會有搶占任務的開銷以及沖突導致的重試,但總體來看資源的使用率更高了。

Kubernetes中默認只有一個調度器,而Omega的設計本身支持資源分配管理器共享資源環境信息給多個調度器。所以從設計上來說,Kubernetes可以支持多個調度器。

2.2 Kubernetes調度器的實現

Kubernetes調度器的工作流程如下圖所示。調度器的工作本質是通過監聽pod的創建、更新、刪除等事件,循環遍歷地完成每個pod的調度流程。如調度過程順利,則基于預選和優選策略,完成pod和主機節點的綁定,最終通知kubelet完成pod啟動的過程。如遇到錯誤的調度過程,通過優先級搶占的方式,獲取優先調度的能力,進而重新進入調度循環的過程,等待成功調度。

2.2.1 調度循環的完整邏輯

Kubernetes調度器完成調度的整體流程如下圖1所示。下面就每個步驟的實現邏輯進行說明。

怎么進行Kubernetes集群調度器原理剖析及思考(1)基于事件驅動啟動循環過程

Kubernetes調度器維護sharedIndexInformer,來完成informer對象的初始化工作。也就是調度器會監聽pod創建、更新、刪除的操作事件,主動更新事件緩存,并持久化到內存隊列,發起調度循環。

該過程的函數入口在

https://github.com/kubernetes/kubernetes/blob/9cbccd38598e5e2750d39e183aef21a749275087/pkg/scheduler/factory/factory.go#L631

怎么進行Kubernetes集群調度器原理剖析及思考(2)將沒有調度的pod加到調度器緩存并更新調度器隊列

Informer對象負責監聽pod的事件,主要的事件類型有:針對已調度pod的addPodToCache、updatePodInCache、deletePodFromCache和針對未被調度pod的addPodToSchedulingQueue、updatePodInSchedulingQueue、deletePodFromSchedulingQueue六種事件。該過程的函數入口在:

https://github.com/kubernetes/kubernetes/blob/9cbccd38598e5e2750d39e183aef21a749275087/pkg/scheduler/eventhandlers.go

各類事件的含義如下表2所示:

怎么進行Kubernetes集群調度器原理剖析及思考

(3)對調度器隊列中的每個pod執行調度

這里需要指出的是,在單個pod調度的過程中,對于主機節點的調度算法是順序執行的。也就是說,pod在調度的過程中會嚴格的順序執行Kubernetes內置的策略和優先級,然后選擇最合適的節點。

單個pod的調度過程分為預選和優選兩個階段。預選階段調度器根據一組規則過濾掉不符合要求的主機,選擇出合適的節點;優選階段通過節點優先級打分的方式(依據整體優化策略等),選擇出分值最高的節點進行調度。

單個pod的調度過程由以下函數作為入口: https://github.com/kubernetes/kubernetes/blob/9cbccd38598e5e2750d39e183aef21a749275087/pkg/scheduler/scheduler.go#L457
怎么進行Kubernetes集群調度器原理剖析及思考

當然,調度的過程可能由于沒有滿足pod運行條件的節點而調度失敗,此時當pod有優先級指定的時候,將觸發競爭機制。具有高優先級的pod將嘗試搶占低優先級的pod資源。相關部分代碼實現如下:

怎么進行Kubernetes集群調度器原理剖析及思考如果資源搶占成功,將在下一次調度循環時標記可調度過程。如果搶占失敗,調度程序退出。調度結果不保存意味著pod仍然會出現在未分配列表中。

(4)接下來檢查用戶提供的插件的條件是否滿足

Reserve插件是Kubernets留給用戶進行擴展的接口,基于reserver插件用戶在這個階段可以設定自定義條件,從而滿足期望的調度過程。插件的入口函數在: https://github.com/kubernetes/kubernetes/blob/9cbccd38598e5e2750d39e183aef21a749275087/pkg/scheduler/plugins/registrar.go

可以在https://github.com/kubernetes/kubernetes/tree/9cbccd38598e5e2750d39e183aef21a749275087/pkg/scheduler/plugins/examples查看插件擴展reserver接口進行自定義調度的示例。

(5)找到滿足的節點后,更新Pod對象的標簽,保存被調度節點的結果

該過程的函數入口在https://github.com/kubernetes/kubernetes/blob/9cbccd38598e5e2750d39e183aef21a749275087/pkg/scheduler/scheduler.go#L517。
怎么進行Kubernetes集群調度器原理剖析及思考

(6)完成pod到節點的綁定

pod到節點的綁定需要首先完成存儲卷的掛載,最后通過pod對象的更新,完成最后的綁定。具體代碼的邏輯可以參考: https://github.com/kubernetes/kubernetes/blob/9cbccd38598e5e2750d39e183aef21a749275087/pkg/scheduler/scheduler.go#L524 。

(7)調度完成后,主協程返回,執行下一個調度

至此調度的完整流程就完成了,下面重點介紹下,在單個pod調度過程中Kubernetes主要是如何對節點進行選擇的,主要包括預選和優選兩種策略。

2.2.2 單個pod的調度流程

單個pod的調度過程如下圖2所示。主要包括由pre-filter、filter、post-filter的預選過程和scoring的優選過程。

怎么進行Kubernetes集群調度器原理剖析及思考圖2:單個Pod的調度過程

(1)pod進入調度階段,首先進入預選環節

通過規則過濾找到滿足pod調度條件的節點。
怎么進行Kubernetes集群調度器原理剖析及思考

k8s內置了許多過濾規則,調度器會按照事先定義好的順序進行過濾。內置的過濾規則主要包括檢查節點是否有足夠資源(例如CPU、內存與GPU等)滿足pod的運行需求,檢查pod容器所需的HostPort是否已被節點上其它容器或服務占用,檢查節點標簽(label)是否匹配pod的nodeSelector屬性要求,根據 taints 和 toleration 的關系判斷pod是否可以調度到節點上pod是否滿足節點容忍的一些條件,還有檢查是否滿足csi最大可掛載卷限制等。
怎么進行Kubernetes集群調度器原理剖析及思考

(2)經過預選策略對節點過濾后,進入優選階段

調度器根據預置的默認規則進行打分(優先級函數得分*權重的和),然后選擇分數最高的節點實現pod到節點的綁定。

怎么進行Kubernetes集群調度器原理剖析及思考Kubernetes內置的優先級函數如下,主要包括平均分布優先級(SelectorSpreadPriority)、最少訪問優先級(LeastRequestedPriority)、平衡資源分布優先級(BalancedResourceAllocation)等。

怎么進行Kubernetes集群調度器原理剖析及思考SelectorSpreadPriority:為了更好的高可用,對同屬于一個service、replication controller或者replica的多個Pod副本,盡量調度到多個不同的節點上。

InterPodAffinityPriority:通過迭代 weightedPodAffinityTerm的元素計算和,如果對該節點滿足相應的PodAffinityTerm,則將 “weight” 加到和中,具有最高和的節點是最優選的。

LeastRequestedPriority:由節點空閑資源與節點總容量的比值,即由(總容量-節點上Pod的容量總和-新Pod的容量)/總容量)來決定節點的優先級。CPU和memory具有相同權重,比值越大的節點得分越高。

BalancedResourceAllocation:CPU和內存使用率越接近的節點優先級越高,該策略不能單獨使用,必須和LeastRequestedPriority同時使用,也就是說盡量選擇在部署Pod后各項資源更均衡的機器。

NodePreferAvoidPodsPriority(權重1w): 如果節點的 Anotation 沒有設置 key-value:scheduler. alpha.kubernetes.io/ preferAvoidPods = “…”,則該 節點對該 policy 的得分就是10分,加上權重10000,那么該節點對該policy的得分至少10W分。如果節點的Anotation設置了scheduler.alpha.kubernetes.io/preferAvoidPods = “…” ,如果該 pod 對應的 Controller 是 ReplicationController 或 ReplicaSet,則該節點對該 policy 的得分就是0分。

NodeAffinityPriority:實現Kubernetes調度中的親和性機制。

TaintTolerationPriority : 使用 Pod 中 tolerationList 與 節點 Taint 進行匹配,配對成功的項越多,則得分越低。

Kubernetes調度器的不足和解決思路

3.1典型的幾個問題和解決思路

(1)調度器只根據當前資源環境情況進行一次調度,一旦完成調度就沒有機制實現調整

雖然pod只有在自己退出、用戶刪除以及集群資源不足等情況下才會有變化。但資源拓撲的變化是隨時都有可能發生的,如批處理任務會結束,節點會新增或崩潰。這些情況導致調度的結果可能在調度時是最優的,但在拓撲變化后調度質量由于以上情況的發生而下降。

經過社區討論,認為需要重新找出不滿足調度策略的pod,刪除并創建替代者來重新調度,據此設計啟動了項目descheduler。

(2)調度以單個pod進行的,因而調度互相關聯的工作負載會難以實現

如大數據分析、機器學習等計算多依賴于批處理任務,這類工作負載相關性大,互相之間有依賴關系。為了解決這個問題,社區經過討論,提出了coscheduling 一次調度一組pod的項目,以此來優化這類調度任務的執行。

(3)目前調度器的實現只關心是否能將pod與節點綁定,資源使用情況的數據未被充分利用

目前,集群的使用量只能通過監控數據間接推導。如果k8s集群剩余資源不足時,并沒有直觀數據可以用來觸發擴容或者告警。

根據上述情況,社區啟動了cluster-capacity framework項目 ,提供集群的容量數據,方便集群的維護程序或者管理員基于這些數據做集群擴容等。也有項目抓取監控數據自己計算集群的整體負載情況給調度算法參考,如poseidon。

3.2 Kubernetes調度器的定制擴展

如上節所述,通用調度器在某些場景下并不能滿足用戶個性化需求,實際環境下運行的集群的調度器,往往需要根據實際的需求做定制與二次開發。

kubernetes的調度器以插件化的形式實現的, 方便用戶對調度的定制與二次開發。定制調度器有如下幾種方式的選擇:

更改Kubernetes內置策略,通過更改默認的策略文件或者重新編譯調度器來實現。

擴展調度器在pre-filter、filter、post-filter、reserve、prebind、bind和post-bind各個階段的接口,更改調度器過濾、打分、搶占、預留的具體實現邏輯。

更改調度器調度算法,從頭實現調度器邏輯。
怎么進行Kubernetes集群調度器原理剖析及思考

企業場景應用的案例

4.1 通用計算場景

Kubernetes default-scheduler滿足通用計算的需求,主要服務于以快速開發測試為目標的持續集成和持續部署平臺(DevOps平臺)、以標準三層架構應用為特點的容器應用運行與運維平臺(容器平臺)、PaaS平臺和云原生應用的核心基礎架構平臺(aPaaS平臺)幾種場景。

通常情況下,標準Kubernetes調度器能夠滿足大多數通過計算場景的訴求,主要解決應用上云過程中不同異構云資源之間的調度問題,應用上云后彈性伸縮、故障自愈等的動態調度響應,標準中間件服務和數據庫服務基于日常運維規范的調度問題以及云原生應用在服務治理、配置管理、狀態反饋、事件鏈路跟蹤上的綜合調度過程。

4.2 批處理場景

大數據分析和機器學習類任務執行時需要大量資源,多個任務同時進行時,資源很快會用盡,部分任務會需要等待資源釋放。這類型任務的步驟往往互相關聯,單獨運行步驟可能會影響最終結果。使用默認的調度器在集群資源緊張時,甚至會出現占用資源的pod都在等待依賴的pod運行完畢,而集群沒有空閑資源去運行依賴任務,導致死鎖。所以在調度這類任務時,支持群組調度(在調度作業所需的資源都收集完成后才進行調度),減少了pod數量,因而降低調度器的負載,同時避免了很多資源緊張帶來的問題。

與默認調度器一次調度一個pod不同,kube-batch定義了PodGroup 定義一組相關的pod資源,并實現了一個全新的調度器。調度器的流程基本與默認調度器相同。Podgroup保證一組pod可以同時被調度。是Kubernetes社區在大數據分析場景中的一種實現。

4.3 特定領域業務場景

特定的業務場景需要調度器能夠快速生成調度的策略,并盡可能避免調度超時。Poseidon是大規模集群中基于圖應用數據局部性減少任務執行時間同時混合多種調度算法提升調度速度的一種調度器。

Poseidon是基于Firmament算法的調度器,它通過接收heapster數據來構建資源使用信息。調用Firmament實現進行調度。Firmament算法受Quincy[11]啟發,構建一個從任務到節點的圖,但作者為減少調度時間,將兩種計算最短路徑的算法合并,將全量環境信息同步改為增量同步。讓Firmament處理短時間批量任務時快于Quincy,在資源短缺時沒有Kubernetes默認調度器超時的問題。

主要從設計原理、代碼實現等層面介紹Kubernetes的調度器以及社區對其的補充加強,總結了Kubernetes調度器的設計原理以及在何種場景如何增強Kubernetes來滿足業務需求,提供技術選型的依據和評價標準。

關于怎么進行Kubernetes集群調度器原理剖析及思考就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女