徐正倫,楊鶴標
(江蘇大學(xué) 計算機科學(xué)與通信工程學(xué)院,江蘇 鎮(zhèn)江 212013)
隨著云計算技術(shù)的迅速發(fā)展,由虛擬化技術(shù)引領(lǐng)的虛擬機技術(shù)逐漸走向成熟。繼AWS把云計算推向業(yè)界之后,各巨頭聯(lián)手打造了龐大的OpenStack與之抗衡[1]。在巨頭們較量之余,Docker公司另辟蹊徑,將Linux Kernel中晦澀難懂的namespace與cgroup封裝成簡單易用的命令行工具,并將待運行的任務(wù)打包成標準的Docker鏡像,成功推動了技術(shù)變革[2]。從此只有大型企業(yè)才有機會接觸的容器技術(shù)現(xiàn)在可被普通開發(fā)者輕易使用,一大批圍繞容器技術(shù)的集群調(diào)度系統(tǒng)應(yīng)運而生,云計算領(lǐng)域掀起了容器化熱潮[3]。
如果說Docker推動了容器走進千家萬戶,那么容器編排技術(shù)才是其走進生產(chǎn)環(huán)境的關(guān)鍵?,F(xiàn)有的容器編排技術(shù)主要有Google Kubernetes、Apache Mesos和Docker Swarm。Mesos其獨特的雙重調(diào)度器設(shè)計要求上層調(diào)度必須由自定義框架實現(xiàn)[4-6]。與現(xiàn)有的開源解決方案Marathon相比,Kubernetes和Swarm顯得功能較弱,必須加以二次開發(fā),否則會逐漸走入幕后[7]。而Swarm雖然隨著Docker 1.12的發(fā)布,原生內(nèi)嵌于Docker內(nèi)部[8],擁有部署簡便、易于使用的優(yōu)點[9-10],但在生產(chǎn)環(huán)境上仍然不夠健壯,缺乏足夠的社區(qū)支持。現(xiàn)Docker公司已經(jīng)逐漸放棄了Swarm的推動,轉(zhuǎn)而在Docker Cloud上啟用Kubernetes,并在最新的master分支代碼上支持Kubernetes集群部署,至此,Kubernetes已經(jīng)成為容器調(diào)度的事實標準[11]。
Kubernetes采用時下流行的微服務(wù)架構(gòu),由多個獨立運行的模塊組成。調(diào)度模塊由獨立的調(diào)度器完成,易于修改和擴展。本文所有工作將基于Kubernetes的調(diào)度器進行。通過分析Kubernetes調(diào)度器源代碼,發(fā)現(xiàn)雖然Kubernetes內(nèi)建的默認調(diào)度算法已經(jīng)相對豐富[12-13],但是調(diào)度時未考慮QoS等級的影響,導(dǎo)致高優(yōu)先級應(yīng)用無法保證服務(wù)質(zhì)量。因此,設(shè)計一種算法對其進行擴展很有必要。
由于允許超售存在,已經(jīng)調(diào)度的Pod隨著業(yè)務(wù)負載的上升所消耗的資源也會逐漸上升,導(dǎo)致節(jié)點所需資源很有可能超出物理機極限。
Kubernetes的QoS策略主要通過Pod聲明所需資源和最大資源進行限制,并通過該設(shè)置將Pod優(yōu)先級從高到低分為3級:①Guaranteed:不但聲明了所需的資源數(shù),還與限制值相同;②Burstable:雖然聲明了所需的資源數(shù)和限制值,但值不同;③Best-Effort:直接未聲明任何資源限制。
對于CPU,此類資源將通過軟性限制避免超額使用。然而對于內(nèi)存等不可壓縮的資源,超出配額只能通過內(nèi)核拋出Out-of-memory錯誤地將Pod殺死[14],并將Pod重新調(diào)度。對于更低優(yōu)先級的Pod將最早殺死,而對于同一優(yōu)先級的Pod,將優(yōu)先殺死占用內(nèi)存多的。
Kubernetes調(diào)度器在預(yù)選過程中直接去除不滿足運行條件(端口占用、主機名、磁盤等硬性要求)的節(jié)點,以減少優(yōu)選階段的計算量[15]。而在優(yōu)選階段則通過打分法為每個節(jié)點得出一個總分,選擇最優(yōu)的解[16]。當存在多個節(jié)點分數(shù)相同時,調(diào)度器會利用Roundrobin算法隨機調(diào)度[17]。
雖然Kubernetes調(diào)度器已經(jīng)預(yù)置了大量優(yōu)選算法(如最少需求策略保證單個節(jié)點不會負載過高,使集群負載均衡,而資源平均消耗策略又保證了單節(jié)點上內(nèi)存與CPU資源的平衡消耗,避免內(nèi)存被使用完),然而CPU仍然空余過多導(dǎo)致資源浪費[18]。之前的調(diào)度算法都只考慮了Pod在調(diào)度前能否滿足需求,卻忽視了Pod在工作時所需資源會動態(tài)變化的特點。顯然一個Pod在空載和高負載情況下對CPU和內(nèi)存的使用情況是不同的[19]。雖然QoS策略保證了高優(yōu)先級Pod能夠在競爭時擁有更高的話語權(quán),有能力將低優(yōu)先級Pod從節(jié)點上“驅(qū)逐”[20],但由于未考慮同一節(jié)點上不同QoS優(yōu)先級Pod的占比,極有可能將一組都是高優(yōu)先級的Pod調(diào)度到同一節(jié)點,導(dǎo)致高優(yōu)先級Pod無法有效擠占低優(yōu)先級資源。因為在同一優(yōu)先級情況下,Kubernetes將首先殺死占用內(nèi)存最大的Pod,而殺死任何高優(yōu)先級Pod的情況均是要盡力避免的。
Kubernetes的QoS機制主要由運行時資源限制與節(jié)點驅(qū)逐機制提供,而調(diào)度器在調(diào)度時并未考慮QoS的影響因素,這有可能造成在單個節(jié)點上缺少低優(yōu)先級Pod,而在需要驅(qū)逐Pod時不得不殺死相對高優(yōu)先級的Pod,即使別的節(jié)點中正在運行的幾乎全是低優(yōu)先級Pod。盡管高優(yōu)先級任務(wù)會驅(qū)逐其它節(jié)點的低優(yōu)先級任務(wù)從而恢復(fù)運行,但是頻繁地重新調(diào)度Pod無疑會造成服務(wù)短暫中斷并加大Kubernetes調(diào)度器壓力。
為解決以上問題,需通過調(diào)整調(diào)度器算法以保證節(jié)點上不同優(yōu)先級的Pod數(shù)量均衡。
為保證節(jié)點上不同優(yōu)先級的Pod數(shù)量均衡,設(shè)計了一個調(diào)度器優(yōu)選算法——BalancedQosPriority。要保證節(jié)點上不同優(yōu)先級的Pod數(shù)量均衡,可通過使節(jié)點上各個不同QoS等級的Pod占總數(shù)的比例與集群上的盡可能相近,即Pn→Pc,其中Pn是節(jié)點上某QoS優(yōu)先級占節(jié)點總數(shù)的百分比,Pc是集群中某QoS優(yōu)先級占節(jié)點總數(shù)的百分比。算法流程如下:
(1)檢查待調(diào)度Pod,計算該Pod的QoS等級,記為L。
(4)最后計算每個工作節(jié)點的優(yōu)先級分數(shù):
score=10× |1-(Pn-Pc)|=
(1)
算法在實現(xiàn)過程中有3點需要注意:
(1)由于Kubernetes是大型分布式集群管理系統(tǒng),節(jié)點數(shù)量可能非常多,因此在獲取節(jié)點信息并計算時采取MapReduce。為使BalancedQosPriority算法能夠應(yīng)用在調(diào)度器中,算法需要實現(xiàn)Map與Reduce兩個接口。
(2)Map的結(jié)果Kubernetes以32位Int保存。為了在Reduce時數(shù)據(jù)有足夠精度,Map的結(jié)果必須避免取整操作。
(3)直接Reduce結(jié)果可能差距很小,由于最后的評分結(jié)果以32位Int表示,直接取整后可能失去參考價值,因此需要在Reduce末尾將結(jié)果正規(guī)化。
最后實現(xiàn)的形式化描述如下:
(int32)Mi=map(nodei)=NL
(2)
(float64)indexi=reduce(M1…Mn,node1…noden)=
(3)
(4)
為驗證上述算法能否有效提高QoS服務(wù)質(zhì)量,設(shè)計調(diào)度器調(diào)度結(jié)果實驗,并對調(diào)度器進行性能比對測試。
實驗環(huán)境見表1。
表1 實驗環(huán)境
本實驗重點測試BalancedQoSPriority算法對集群中各個QoS等級的Pod均衡度的提高。
3.2.1 實驗方法
首先定義均衡度指數(shù)為各個節(jié)點上相同QoS等級Pod數(shù)量的方差,即該指數(shù)越小代表該QoS等級在集群中分布越均衡。各個測試節(jié)點為虛擬節(jié)點,在調(diào)度時忽略虛擬節(jié)點資源消耗的影響。實驗分為兩組,分別將改進前和改進后的調(diào)度器通過測試用例測試兩次,兩次采用相同的測試方法,測試在100個節(jié)點上調(diào)度3 000個Pod后各個QoS等級Pod的均衡指數(shù),實驗結(jié)果如圖1所示。
3.2.2 結(jié)果分析
圖1 各個節(jié)點上Pod數(shù)量的方差
從圖1可以看出,在未采用BalancedQosPriority算法時,由于調(diào)度器未考慮QoS等級的影響因素,均衡指數(shù)較高。而在應(yīng)用BalancedQoSPriority算法后,均衡指數(shù)明顯下降,說明BalancedQosPriority算法在提高均衡度方面作用明顯,算法切實可行。
雖然BalancedQosPriority算法具有可行性,但是客觀上的確增加了調(diào)度器的計算量。如果在提高均衡度的同時帶來了極大的性能損失,那么無疑算法是失敗的。因此必須驗證BalancedQosPriority算法的效率,為此通過Benchmark進行性能測試。
3.3.1 試驗方法
對Kubernetes調(diào)度器進行集成測試,通過運行API Server與調(diào)度器,并通過虛擬節(jié)點創(chuàng)建大量Pod對調(diào)度器發(fā)起壓力測試,統(tǒng)計出調(diào)度完特定數(shù)目Pod需要的時間,消耗的時間越小代表效率越高。
在默認設(shè)置的基礎(chǔ)上分別開啟與關(guān)閉BalancedQo sPriority算法,對比兩種情況下的性能損失,從而得出該算法對整體性能的影響。實驗總共進行5次取平均值,以忽略偶然性造成的影響。
3.3.2 結(jié)果分析
圖2 性能影響對比
從圖2可以看出,應(yīng)用BalancedQosPriority算法前后消耗時間去除誤差后幾乎相等,說明BalancedQosPriority算法沒有影響現(xiàn)有調(diào)度器的執(zhí)行效率,從而證明該算法可行。
合理、有效地利用資源一直是云計算領(lǐng)域研究的熱點課題。無論是提高集群的可用率還是資源使用率,都繞不開調(diào)度器優(yōu)化。本文得益于Kubernetes的開源便利與優(yōu)秀的模組化設(shè)計,針對調(diào)度器在QoS策略上存在的不足,通過設(shè)計一個新的調(diào)度算法,改進了以往在調(diào)度不同QoS等級Pod時沒有盡可能使其在集群中達到均衡的缺點,并通過實驗驗證了算法的有效性和可用性。改進方法保證了Kubernetes集群在高負載情況下QoS優(yōu)先級Pod的穩(wěn)定性,提高了負載的可用率。