如何定製Kubernetes排程演算法?
隨著雲端計算和容器技術的發展,以Docker為核心的容器技術迅速在開發者和科技公司中應用,Kubernetes憑藉豐富的企業級、生產級功能成為事實上的容器叢集管理系統。可是Kubernetes的 通用性
削弱了排程演算法的 定製性
,本文將調研定製化排程演算法的方法,並且給出一個開源實現。
Kubernetes與排程器架構
圖1是Kubernetes的整體架構圖,叢集節點分為兩種角色: Master節點
和 Node節點
。Master節點是整個叢集的管理中心,負責叢集管理、容器排程、狀態儲存等元件都執行在Master節點上;Node節點是實際上的工作節點,負責執行具體的容器。
圖1 Kubernetes整體架構
Kubernetes排程器是獨立執行的程序,內部執行過程從邏輯上可以分為多個模組。圖2展示了預設排程器內部包含的具體模組,配置模組負責讀取排程器相關配置資訊,並且根據配置內容初始化排程器。
- 優先佇列模組是一個優先堆資料結構,負責將待排程Pod根據優先順序排序,優先順序高的Pod排在前面,排程器會輪詢優先佇列, 當佇列中存在待排程Pod時就會執行排程過程 。
- 排程模組由
演算法模組
、Node快取
和排程擴充套件點
三部分組成,演算法模組提供對Node進行評分的一系列基礎演算法,比如均衡節點CPU和記憶體使用率的NodeResourcesBalancedAllocation演算法,演算法模組是可擴充套件的,使用者可以修改和新增自己的排程演算法;Node快取模組負責快取叢集節點的最新狀態資料,為排程演算法提供資料支撐;排程擴充套件點由一系列擴充套件點構成,每個擴充套件點負責不同的功能,最重要的擴充套件點是Filter、Score和Bind這三個擴充套件點。 - 最後是繫結模組,負責將排程器選擇的Node和Pod繫結在一起。
圖2 Kubernetes排程器架構
Kubernetes排程器程式碼採用可插拔的外掛化設計思路,包括核心部分和可插拔部分。圖2中的配置模組、優先佇列和Node快取是核心部分,演算法模組、排程擴充套件點屬於可插拔部分。 這種外掛化設計允許排程器一些功能通過外掛的方式實現,方便程式碼修改和功能擴充套件,同時保持排程器核心程式碼簡單可維護 。
圖3列出了排程器擴充套件點模組中包含的具體擴充套件點。Pod的排程過程分為 排程週期
和 繫結週期
,排程和繫結週期共同構成Pod的排程上下文。排程上下文由一系列擴充套件點構成,每個擴充套件點負責一部分功能,最重要的擴充套件點是排程週期中的預選(Filter)和優選(Score)擴充套件點和繫結週期中的繫結(Bind)擴充套件點。
預選擴充套件點負責判斷每個節點是否能夠滿足Pod的資源需求,不滿足就過濾掉該節點。優選擴充套件點部分會對每個Pod執行預設的評分演算法,並且將最終評分加權彙總,得到最後所有節點的綜合評分;排程器會選擇綜合評分最高的節點,如果有多個節點評分相同且最高,排程器會通過 水塘取樣演算法
在多個節點中隨機選擇一個作為排程結果,然後將該節點上Pod申請的資源用量進行保留操作,防止被其它Pod使用。在繫結週期中,排程器將Pod繫結到評分最高的節點上,這一步本質是修改Pod物件中節點相關的資訊,並且更新到儲存元件etcd中。
圖3 Kubernetes排程器擴充套件點架構
定製化演算法方案
如果要實現自定義排程演算法,主要有三種方案:
- 修改預設排程器的原始碼,加入自己的排程演算法,然後重新編譯和部署排程器,論文 kcss 和 kubecg 中的排程器研究基於此方案實現;
- 開發自己的排程器,和預設排程器同時執行在叢集中;
- 基於 Kubernetes Scheduler Extender機制 ,在擴充套件排程器中實現自定義演算法,論文 dynamic IO 中的演算法實現基於這種方案。
上述三種自定義排程演算法實現方案的優缺點見表1。綜合來講:
- 方案1改動最小,但是這樣做會破壞開源軟體的可維護性,當Kubernetes主幹程式碼更新時,改動後的排程器要和上游程式碼保持一致, 這會帶來大量的維護和測試工作 。
- 方案2是實現自己的排程器,並且在叢集中執行多個排程器,多個排程器之間沒有叢集資源資料同步,存在併發排程資料競爭和資料不一致的問題。
- 方案3需要預設排程器通過API和Extender互動,新增的網路請求會增加整個排程過程的耗時。
表1 自研排程演算法方案對比:
本文的排程器實現採用方案3,設計並開發符合Scheduler Extender機制和API規範的擴充套件排程器,將其命名為 Liang 。程式碼1是擴充套件排程器JOSN格式的策略配置檔案,通過配置檔案引數將該策略檔案傳遞給Kubernetes預設排程器,其中urlPrefix表示擴充套件排程器Liang執行後監聽的API地址,prioritizeVerb表示優選擴充套件點在擴充套件排程器中的路由。當預設排程器在優選擴充套件點執行完評分外掛後會傳送HTTP POST網路請求到Liang的API地址,並將Pod和候選節點資訊放在HTTP Body中一起傳遞過去。接收到POST請求後,擴充套件排程器Liang會根據評分演算法對節點進行評分並將結果返回給預設排程器。
{ "kind": "Policy", "apiVersion": "v1", "extenders": [ { "urlPrefix": "http://localhost:8000/v1", "prioritizeVerb": "prioritizeVerb", "weight": 1, "enableHttps": false, "httpTimeout": 1000000000, "nodeCacheCapable": true, "ignorable": false } ] }
程式碼1
圖4是帶擴充套件的預設排程器(kube-scheduler)啟動過程,通過kube-policy.json配置檔案將擴充套件排程器Liang的配置資訊告訴預設排程器。
圖4 擴充套件排程器通過配置檔案傳遞給預設排程器啟動
擴充套件排程器Liang
擴充套件排程器Liang獨立於Kubernetes預設排程器,Liang的模組設計和組織架構如圖5所示,包括多維資源採集儲存和API服務兩大部分。多維資源資料採集通過在叢集中執行Prometheus和node-exporter實現,擴充套件排程器Liang負責從Prometheus獲取多維指標然後運用排程演算法,將結果返回給預設排程器。
圖5 擴充套件排程器Liang整體架構
- API Server模組,負責實現符合擴充套件排程器資料格式和傳輸規範的API介面,Liang接收到Kubernetes的評分請求後,解析得到請求中的Pod和候選節點資訊,作為引數傳遞給內部的排程演算法,得到候選節點的評分結果並返回給預設排程器。
- 排程演算法模組,擴充套件排程器Liang的核心模組,負責實現自定義的排程演算法。得益於擴充套件排程器機制,Liang中可以實現多個自定義排程演算法。本文主要設計並實現了BNP和CMDN兩個排程演算法。
- 資料快取模組,主要功能有兩個:
- 通過請求Prometheus的API得到整個Kubernetes叢集中所有節點的狀態資料。
- 實現基於記憶體的指標資料快取機制,提供指標資料的寫入和讀取介面,提高演算法執行時獲取多維指標資料的速度。
Liang使用Go語言開發,程式碼量約3400行,Liang開源地址: http://github.com/adolphlwq/liang 。
表2是擴充套件排程器是否使用快取機制和預設排程器做出排程決策的耗時對比,排程耗時通過在Kubernetes排程器原始碼中列印時間戳的方式獲取,分別執行9次然後計算平均值。從表2中可以看到,預設排程器做出排程決策的耗時非常小,不到1ms。加上擴充套件排程器和快取機制的情況下,平均排程決策耗時為4.439ms,比預設排程器增加了約3ms,增加的時間主要是預設排程器與擴充套件排程器Liang之間網路請求耗時以及Liang執行排程演算法所需的時間。
當擴充套件排程器不加快取機制時,每次做出排程決策的平均耗時為1110.439ms,排程耗時迅速增加超過100倍,主要是每次做出排程決策都要請求Prometheus計算和獲取叢集中的指標資料。因此,擴充套件排程器加上快取機制可以避免請求Prometheus帶來的網路請求時間,降低擴充套件排程器的決策時間,提升了擴充套件排程器的效能。
表2 不同調度器架構決策耗時
BNP演算法
BNP演算法在Liang中實現,它將網路IO使用情況納入KKubernetes排程演算法的考量,能夠均衡叢集中的網路IO用量。
圖6是實驗中預設排程演算法和BNP演算法中,整個叢集中網路IO資源的變化情況,每部署一個Pod統計一次資料,共部署九個Pod。可以明顯看到,BNP實驗中網路IO資源要比預設排程演算法分配更均衡。
圖6 BNP演算法網路IO使用率變化情況
CMDN演算法
CMDN演算法在Liang中實現,它的目標是讓叢集中的多維資源分配更加均衡或者更加緊湊,核心步驟是針對CPU、記憶體、磁碟IO和網路IO以及網絡卡頻寬這五個指標進行綜合排序,選擇最佳Node部署Pod。圖7是實驗中CPU使用率變化對比情況,可以明顯看到,CMDN均衡策略下CPU使用率均衡程度要比預設排程演算法分配更均衡。
圖7 CMDN演算法均衡策略下CPU使用率變化情況
總結
Kubernetes排程演算法的通用性削弱了演算法的定製性。本文研究了Kubernetes排程器架構和擴充套件機制,對比了三種定製化排程演算法方案,選擇擴充套件方案實現 擴充套件排程器Liang
,並在Liang中實現了兩個排程演算法BNP和CMDN用於展示定製化演算法能力。
擴充套件方案極大豐富了定製化排程演算法的能力,可以滿足非常多定製化場景的需求。同時也需要注意,定製排程演算法往往需要更多的資料,這就需要在Kubernetes叢集中額外部署資料採集模組,增加了運維成本,降低了定製化排程演算法的通用性。
- 深入理解Redis
- 深入OpenTelemetry指標
- 獨家新聞:Netflix歷史性地引入軟體工程師級別
- Cilium母公司宣佈完成4000萬美元B輪融資
- 深入理解四種Prometheus指標
- 對比 Istio,Linkerd 和 Consul
- 大規模分散式系統中的級聯故障
- 最佳軟體架構
- 服務網格的eBPF ? 是的,但 Envoy Proxy 將繼續存在
- eBPF、sidecars以及服務網格展望
- Apple M2裸片和架構分析--成本大幅增加及基於IP塊的 A15 晶片
- 如何擴充套件K8s API-K8s與Django
- 兩位將軍的問題
- Komodor 想讓每個工程師都成為 Kubernetes 專家
- 為什麼一次會議的成本比一臺MacBook Pro還高—減少會議中的開發人員的商業案例
- Go程式語言和環境
- Kubernetes聯合創始人Joe Beda:“軟體開發是一項團隊運動”
- 如何使用Go呼叫Kubernetes API-型別和普通機制
- Prodspec和Annealing
- 從零開始搭建SRE