平 凡 陳莉君
(西安郵電大學(xué)計(jì)算機(jī)學(xué)院 西安 710121)
隨著云計(jì)算技術(shù)的飛速發(fā)展,以Docker為代表的容器技術(shù)因其輕量級(jí)、可遷移、可快速部署等特性而得到了業(yè)界的廣泛應(yīng)用[1]。Kubernetes則因其優(yōu)秀的容器管理能力和輕量開源的特點(diǎn)成為了業(yè)界容器編排系統(tǒng)的首選[2]。然而Kubernetes只實(shí)現(xiàn)了對(duì)于Pod的靜態(tài)調(diào)度,缺少集群節(jié)點(diǎn)的動(dòng)態(tài)負(fù)載均衡。在集群長(zhǎng)時(shí)間運(yùn)行的場(chǎng)景下,會(huì)出現(xiàn)集群中節(jié)點(diǎn)的負(fù)載不均衡的情況從而引發(fā)諸多問題[3]。
由于Kubernetes容器云平臺(tái)備受關(guān)注,其負(fù)載均衡領(lǐng)域已經(jīng)有諸多學(xué)者做了大量研究[3~9]。楊鵬飛[4]設(shè)計(jì)了應(yīng)用對(duì)資源有不同敏感度的負(fù)載均衡模塊,解決了應(yīng)用對(duì)資源有不同實(shí)際需求情況下的調(diào)度問題,以減少碎片化的資源。彭麗蘋、呂曉丹、蔣朝惠等[5]對(duì)Ceph集群數(shù)據(jù)副本存儲(chǔ)策略進(jìn)行改進(jìn),建立了一個(gè)資源調(diào)度優(yōu)化模型,在此基礎(chǔ)上提出了基于Docker云平臺(tái)的應(yīng)用容器部署算法和應(yīng)用在線遷移算法。楊欣[6]實(shí)現(xiàn)了一種自動(dòng)化的智能彈性負(fù)載均衡機(jī)制,通過分析預(yù)測(cè)機(jī)制和資源池模塊來解決彈性伸縮過程中的滯后性問題。但上述文獻(xiàn)都沒有考慮到云平臺(tái)的動(dòng)態(tài)負(fù)載均衡,致使集群長(zhǎng)時(shí)間運(yùn)行情況下會(huì)出現(xiàn)負(fù)載極不均衡的情況。唐瑞[7]提出了搶占式調(diào)度策略以及簡(jiǎn)單的動(dòng)態(tài)負(fù)載均衡策略,但是針對(duì)具體待重新調(diào)度Pod的選擇方案還有待改進(jìn)。
本文提出了針對(duì)Kubernetes的動(dòng)態(tài)負(fù)載均衡機(jī)制,解決集群長(zhǎng)時(shí)間運(yùn)行情況下負(fù)載可能出現(xiàn)的不均衡問題。首先提出將高于集群平均負(fù)載的節(jié)點(diǎn)集合為高負(fù)載隊(duì)列。然后在高負(fù)載隊(duì)列中挑選出合適的可被重新調(diào)度的Pod刪除。在選擇被重新調(diào)度的Pod時(shí),依據(jù)先過濾,后排序的原則。使Pod在Kubernetes的調(diào)度器下做新的調(diào)度。以此保持Kubernetes動(dòng)態(tài)的負(fù)載均衡。
Kubernetes動(dòng)態(tài)負(fù)載均衡的核心在于讓Pod做重新調(diào)度。重調(diào)度的一個(gè)相關(guān)組件是Kubernetes調(diào)度器。調(diào)度器的作用是將待調(diào)度隊(duì)列中的Pod依據(jù)特定的調(diào)度策略綁定給集群中某一個(gè)節(jié)點(diǎn),然后將綁定的結(jié)果信息寫入到Etcd中。隨后,該節(jié)點(diǎn)中的Kubelet通過APIServer監(jiān)聽到此綁定事件,Kubelet就會(huì)在該節(jié)點(diǎn)中依據(jù)Pod的詳細(xì)信息從鏡像倉(cāng)庫(kù)拉取對(duì)應(yīng)鏡像并啟動(dòng)容器。Kubernetes調(diào)度器框架如圖1所示。

圖1 Kubernetes調(diào)度器框架圖
Kubernetes的調(diào)度流程分為以下兩步:
1)預(yù)選調(diào)度:檢查所有可用節(jié)點(diǎn),篩選出符合Pod要求的節(jié)點(diǎn)。這些節(jié)點(diǎn)成為下一流程的候選節(jié)點(diǎn)。預(yù)選策略如:NoDiskConflict、PodFitsResources等。
2)優(yōu)選調(diào)度:在流程1)篩選出來的節(jié)點(diǎn)中進(jìn)一步進(jìn)行篩選。采用優(yōu)選策略計(jì)算出每一個(gè)候選節(jié)點(diǎn)的得分,得分最高者為最適合被調(diào)度的節(jié)點(diǎn)。優(yōu)選策略如:LeastRequestedPriority、BalancedResourceAllocation等。
3.1.1 集群中節(jié)點(diǎn)主要性能指標(biāo)的數(shù)學(xué)表示
在Kubernetes集群中,CPU和Memory是節(jié)點(diǎn)性能的主要衡量指標(biāo)。集群中的n個(gè)節(jié)點(diǎn)可表示各節(jié)點(diǎn)的資源配額表示為集群中標(biāo)號(hào)為i的節(jié)點(diǎn)資源配額表,其中c,m分別表示第i個(gè)節(jié)點(diǎn)的iiCPU配額與Memory配額。集群中通過規(guī)格系數(shù)λi衡量各節(jié)點(diǎn)的性能。性能越好,規(guī)格系數(shù)λi越高。假設(shè)集群各節(jié)點(diǎn)的規(guī)格系數(shù)向量為,其中標(biāo)號(hào)為i的節(jié)點(diǎn)的規(guī)格系數(shù)分別表示標(biāo)號(hào)為i的節(jié)點(diǎn)的CPU和Memory的規(guī)格系數(shù)。因此,標(biāo)號(hào)為i的節(jié)點(diǎn)的資源配額可表示為q是一個(gè)對(duì)角矩陣,C、M是常量系數(shù)。
例如對(duì)于一臺(tái)雙核2G內(nèi)存的節(jié)點(diǎn)和一臺(tái)八核16G內(nèi)存的節(jié)點(diǎn),可將兩者的則兩者的規(guī)格系數(shù)分別為集群中各節(jié)點(diǎn)的資源配額可以表示為
通過設(shè)置規(guī)格系數(shù),可以將不同規(guī)格的節(jié)點(diǎn)進(jìn)行區(qū)別對(duì)待。
以上描述涉及的各參數(shù)如表1所示。

表1 集群主要性能指標(biāo)參數(shù)表示
3.1.2 集群負(fù)載均值
集群負(fù)載均值指集群CPU負(fù)載均值和Memory負(fù)載均值。用來衡量集群整體的負(fù)載情況。
集群CPU負(fù)載均值avCpuUsed由節(jié)點(diǎn)的CPU規(guī)格系數(shù)加權(quán)平均表示為

其中cpuUsedi表示標(biāo)號(hào)為i的節(jié)點(diǎn)的CPU使用率,αi是標(biāo)號(hào)為i的節(jié)點(diǎn)的CPU規(guī)格系數(shù),
集群Memory負(fù)載均值avMemoryUsed由節(jié)點(diǎn)的Memory規(guī)格系數(shù)加權(quán)平均表示為

其中memoryUsedi表示標(biāo)號(hào)為i的節(jié)點(diǎn)的Memory使用率,βi是標(biāo)號(hào)為i的節(jié)點(diǎn)的Memory規(guī)格系數(shù),i∈{1,2,…,i,…,n}。
各參數(shù)的描述見表2。

表2 集群負(fù)載均值相關(guān)參數(shù)表示
3.1.3 動(dòng)態(tài)負(fù)載均衡的觸發(fā)方式
本文提出的動(dòng)態(tài)負(fù)載均衡機(jī)制有三種觸發(fā)方式:
1)集群節(jié)點(diǎn)擴(kuò)容觸發(fā):當(dāng)集群增加節(jié)點(diǎn)的數(shù)量時(shí),觸發(fā)Kubernetes的動(dòng)態(tài)負(fù)載均衡。
2)節(jié)點(diǎn)域值觸發(fā):當(dāng)集群中節(jié)點(diǎn)的某資源使用率達(dá)到預(yù)設(shè)的閾值時(shí)(如CPU使用率超過90%),觸發(fā)Kubernetes的動(dòng)態(tài)負(fù)載均衡。
3)定時(shí)機(jī)制:定時(shí)觸發(fā)Kubernetes的動(dòng)態(tài)負(fù)載均衡。
3.2.1 節(jié)點(diǎn)CPU和Memory得分
為了準(zhǔn)確衡量集群中各節(jié)點(diǎn)的相對(duì)負(fù)載狀況,對(duì)集群中各節(jié)點(diǎn)的資源(CPU和Memory)做分值計(jì)算。
標(biāo)號(hào)為i的節(jié)點(diǎn)CPU負(fù)載得分計(jì)算公式為

Memory負(fù)載得分計(jì)算公式為

節(jié)點(diǎn)的負(fù)載總得分計(jì)算公式為

各參數(shù)描述見表3。
CPU和Memory負(fù)載得分區(qū)間為[ ]0,+∞ ,用CPU來舉例說明資源得分的具體含義,Memory得分含義類似。cpuScorei分值大于0表示該節(jié)點(diǎn)的CPU負(fù)載情況優(yōu)于集群CPU平均負(fù)載情況,小于0反之。得分越高,資源情況越好,通過得分可以判斷節(jié)點(diǎn)相對(duì)于集群整體的相對(duì)負(fù)載情況。負(fù)載總得分scorei用來進(jìn)行節(jié)點(diǎn)的排序。

表3 節(jié)點(diǎn)得分相關(guān)參數(shù)表示
3.2.2 建立高負(fù)載隊(duì)列
若是定時(shí)或節(jié)點(diǎn)擴(kuò)容觸發(fā)的動(dòng)態(tài)負(fù)載均衡,則依據(jù)各節(jié)點(diǎn)CPU和Memory的得分,將CPU和Memory得分為負(fù)數(shù)的節(jié)點(diǎn)篩選出來。并建立高負(fù)載隊(duì)列。即高負(fù)載隊(duì)列中的節(jié)點(diǎn)滿足公式:

高負(fù)載隊(duì)列示例如圖2所示。

圖2 高負(fù)載隊(duì)列示例
若是閾值觸發(fā)的動(dòng)態(tài)負(fù)載均衡,除了要重復(fù)以上步驟計(jì)算得分并建立高負(fù)載隊(duì)列以外,還要將該觸發(fā)閾值的節(jié)點(diǎn)加入到隊(duì)首。
節(jié)點(diǎn)高負(fù)載隊(duì)列的數(shù)據(jù)結(jié)構(gòu)表示如下:
type queue_node struct{
nodeId int //節(jié)點(diǎn)的唯一標(biāo)識(shí)符
nodeName string //節(jié)點(diǎn)名稱
score float32 //節(jié)點(diǎn)的負(fù)載總得分
server *next //服務(wù)器指針
}
高負(fù)載隊(duì)列使用優(yōu)先隊(duì)列實(shí)現(xiàn),在優(yōu)先隊(duì)列中有插入、刪除、查找三種基本操作。
每次觸發(fā)動(dòng)態(tài)負(fù)載均衡,都查找得分最低的節(jié)點(diǎn),待刪除其上的某些Pod之后,若節(jié)點(diǎn)達(dá)到了要求,則將此節(jié)點(diǎn)從隊(duì)列中刪除。此時(shí)再查找得分最低的節(jié)點(diǎn),刪除其上的某些Pod之后,再將此節(jié)點(diǎn)從隊(duì)列中刪除,以此類推,直到處理完其中的所有節(jié)點(diǎn)。
對(duì)于處理觸發(fā)閾值的節(jié)點(diǎn),要將該節(jié)點(diǎn)中的Pod刪除直至該節(jié)點(diǎn)不會(huì)再閾值觸發(fā)動(dòng)態(tài)負(fù)載均衡為止。
3.2.3 選擇重調(diào)度的Pod
高負(fù)載隊(duì)列建立之后,需要從得分最低(觸發(fā)閾值)的節(jié)點(diǎn)中選擇需要被重新調(diào)度的Pod刪除。選擇重調(diào)度的Pod需以下步驟:
1)篩選掉不可被重新調(diào)度的Pod
有狀態(tài)且狀態(tài)信息存儲(chǔ)于本地節(jié)點(diǎn)中的應(yīng)用是不能被重新調(diào)度的,因?yàn)樵揚(yáng)od在被重新調(diào)度到其它節(jié)點(diǎn)上運(yùn)行時(shí)狀態(tài)信息將會(huì)丟失,當(dāng)業(yè)務(wù)對(duì)數(shù)據(jù)敏感時(shí),此Pod的重新調(diào)度是不被允許的。
重啟策略為Never的Pod不可以被重新調(diào)度,因?yàn)橹貑⒉呗詾镹ever的Pod在被節(jié)點(diǎn)刪除之后是不會(huì)自動(dòng)再被重新在新的節(jié)點(diǎn)上部署的。
2)剩余Pod做優(yōu)先級(jí)的劃分
描述Pod重要性的參考有兩個(gè):Pod的重啟策略與服務(wù)資源質(zhì)量。
Pod 的重啟策略:Always、Onfailed、Never。其中Never的Pod不能被重新調(diào)度。
以重啟策略作為Pod優(yōu)先級(jí)的劃分,是因?yàn)橹貑⒉呗詾锳lways的Pod無論何種情況,只要被刪除就會(huì)立即被重新調(diào)度,而重啟策略為Onfailed的Pod只有當(dāng)它異常退出時(shí)調(diào)度器才會(huì)重新調(diào)度。因此一般情況下,在集群中以重啟策略為Always部署的Pod重要性高于以O(shè)nfailed部署的Pod。當(dāng)要選擇被重新調(diào)度的Pod時(shí)首先應(yīng)選擇重啟策略為Onfailed的Pod。
Pod的資源服務(wù)質(zhì)量:Gurantee、Burst。當(dāng)Pod的資源requests=limit時(shí),資源服務(wù)質(zhì)量為Gurantee。當(dāng)Pod的資源requests<limit時(shí),資源服務(wù)質(zhì)量為 Burst[10]。
資源服務(wù)質(zhì)量為Guranteee說明該P(yáng)od對(duì)資源服務(wù)質(zhì)量的要求高于為Burst的Pod。所以資源服務(wù)質(zhì)量為Gurantee的Pod重要性高于資源服務(wù)質(zhì)量為Burst的Pod。因此當(dāng)要選擇被重新調(diào)度的Pod時(shí)首先選擇資源服務(wù)質(zhì)量為Burst的Pod。
綜上,Pod重新調(diào)度的優(yōu)先級(jí)劃分如表4所示。

表4 待重調(diào)度Pod的優(yōu)先級(jí)
以此順序來選擇被刪除的Pod。
3.2.4 總體設(shè)計(jì)
如圖3所示,本文針對(duì)Kubernetes的動(dòng)態(tài)負(fù)載均衡機(jī)制共有三種觸發(fā)方式:定時(shí)器、集群節(jié)點(diǎn)擴(kuò)容、節(jié)點(diǎn)觸發(fā)閾值。觸發(fā)集群的動(dòng)態(tài)負(fù)載均衡之后,首先集群會(huì)收集并分析負(fù)載信息,并依據(jù)上述得分建立節(jié)點(diǎn)的高負(fù)載隊(duì)列。若是節(jié)點(diǎn)資源超出閾值觸發(fā)的動(dòng)態(tài)負(fù)載均衡,則將觸發(fā)閾值的節(jié)點(diǎn)插入到高負(fù)載隊(duì)列隊(duì)首。最后從高負(fù)載隊(duì)列中選擇適合被重新調(diào)度的Pod做重調(diào)度。

圖3 動(dòng)態(tài)負(fù)載均衡機(jī)制設(shè)計(jì)圖
本次實(shí)驗(yàn)使用三臺(tái)規(guī)格系數(shù)不同的服務(wù)器搭建的版本為v1.4.9的Kubernetes作為實(shí)驗(yàn)平臺(tái)。用Guestbook作為實(shí)驗(yàn)用的應(yīng)用,該Guestbook經(jīng)過修改,將Web前端容器、Redis-Master、Redis-Slave放在同一個(gè)Pod中。Web前端容器向Redis-Master中寫入數(shù)據(jù),然后Redis-Master將數(shù)據(jù)同步到Redis-Slave中,Web前端容器再?gòu)腞edis-Slave中讀出數(shù)據(jù)。壓力測(cè)試工具使用Webbench。實(shí)驗(yàn)會(huì)通過客戶端向集群APIServer發(fā)出創(chuàng)建應(yīng)用命令以及壓力測(cè)試。
集群主要軟件的描述如表5所示。

表5 集群主要軟件描述
1)通過客戶端向集群的APIServer創(chuàng)建12個(gè)GuestBook應(yīng)用,之后每10min創(chuàng)建12個(gè)(三種重啟策略與兩種服務(wù)資源質(zhì)量各兩個(gè)且各應(yīng)用requests值不同),直至創(chuàng)建60個(gè)GuestBook。
2)在客戶端用Webbench向各工作節(jié)點(diǎn)并行發(fā)出Web請(qǐng)求,請(qǐng)求數(shù)由隨機(jī)函數(shù)隨機(jī)生成。
3)在Master節(jié)點(diǎn)上監(jiān)測(cè)并記錄各節(jié)點(diǎn)的資源使用情況,記錄方式為剛創(chuàng)建GuestBook時(shí)記錄一次,創(chuàng)建9min后一次。這樣可以具體了解剛創(chuàng)建完應(yīng)用時(shí)的節(jié)點(diǎn)負(fù)載情況與服務(wù)一段時(shí)間之后的節(jié)點(diǎn)負(fù)載情況。
4)定時(shí)動(dòng)態(tài)負(fù)載均衡,在創(chuàng)建應(yīng)用之后的5min進(jìn)行動(dòng)態(tài)負(fù)載均衡。
5)使用Kubernetes的默認(rèn)調(diào)度算法重復(fù)步驟1)~3)。
含有動(dòng)態(tài)負(fù)載均衡機(jī)制的調(diào)度算法如圖4所示,本文共做了10次檢測(cè),由于前兩次檢測(cè)時(shí)Pod的數(shù)量較少,容易出現(xiàn)訪問集中于某節(jié)點(diǎn)的情況,所以可見前兩次檢測(cè)節(jié)點(diǎn)的得分較為分散。而由于在集群運(yùn)行中進(jìn)行動(dòng)態(tài)的負(fù)載均衡,所以集群中節(jié)點(diǎn)的得分在后面的檢測(cè)中逐漸趨于0。也即負(fù)載趨于均衡。

圖4 含動(dòng)態(tài)負(fù)載均衡機(jī)制的調(diào)度算法各節(jié)點(diǎn)綜合得分變化曲線圖
Kubernetes的默認(rèn)調(diào)度算法的檢測(cè)結(jié)果如圖5所示,同樣由于前兩次檢測(cè)時(shí)Pod的數(shù)量較少,出現(xiàn)了訪問集中于某節(jié)點(diǎn)的情況,所以前兩次訪問也較分散。從第3次檢測(cè)開始,我們可以看到奇數(shù)次檢測(cè)負(fù)載較為均衡而偶數(shù)次檢測(cè)負(fù)載比較分散。這是因?yàn)槠鏀?shù)次檢測(cè)時(shí),集群剛被默認(rèn)調(diào)度算法調(diào)度了新的Pod,而偶數(shù)次檢測(cè)時(shí)集群已經(jīng)運(yùn)行了一段時(shí)間了。

圖5 默認(rèn)調(diào)度算法各節(jié)點(diǎn)綜合得分變化曲線圖
綜合以上實(shí)驗(yàn)結(jié)果,我們可以看出Kubernetes的默認(rèn)調(diào)度算法在靜態(tài)調(diào)度時(shí)可以很好地維持集群的負(fù)載均衡度,但是在集群長(zhǎng)時(shí)間運(yùn)行的情況下集群的負(fù)載會(huì)出現(xiàn)較大的波動(dòng)。本文提出的動(dòng)態(tài)負(fù)載均衡機(jī)制結(jié)合靜態(tài)調(diào)度與動(dòng)態(tài)調(diào)度,可以較好地維持集群系統(tǒng)的均衡性,保持集群系統(tǒng)的穩(wěn)定。
由于當(dāng)前Kubernetes的調(diào)度器僅提供了基于資源申請(qǐng)值requests的靜態(tài)調(diào)度策略,而缺少依據(jù)節(jié)點(diǎn)實(shí)際負(fù)載值進(jìn)行集群節(jié)點(diǎn)動(dòng)態(tài)負(fù)載均衡的機(jī)制。本文提出了一種基于節(jié)點(diǎn)實(shí)際負(fù)載值的集群動(dòng)態(tài)負(fù)載均衡機(jī)制,通過定時(shí)、集群擴(kuò)容及節(jié)點(diǎn)閾值的方式觸發(fā)集群的動(dòng)態(tài)負(fù)載均衡。通過對(duì)集群各節(jié)點(diǎn)分值的計(jì)算建立節(jié)點(diǎn)的高負(fù)載隊(duì)列,并從高負(fù)載隊(duì)列中選擇合適的Pod進(jìn)行重調(diào)度,以此達(dá)到動(dòng)態(tài)負(fù)載均衡的目的。但是由于集群在運(yùn)行當(dāng)中需要做Pod的重新調(diào)度,所以會(huì)增加一定的計(jì)算負(fù)擔(dān),考慮到增加的計(jì)算負(fù)擔(dān)與節(jié)點(diǎn)的數(shù)量是簡(jiǎn)單的線性關(guān)系,因此這個(gè)計(jì)算負(fù)擔(dān)是完全可以接受的。本文的實(shí)驗(yàn)結(jié)果表明,相比于Kubernetes默認(rèn)的調(diào)度算法,含有動(dòng)態(tài)負(fù)載均衡機(jī)制的調(diào)度算法能夠更有效地保持集群負(fù)載的均衡。