導讀
58雲計算平臺(以下簡稱雲平臺)是58集團基於Kubernetes和Docker打造的私有云平臺(Kubernetes簡寫為K8S),旨在為集團內部提供高效、便捷的一站式雲化解決方案,具有簡單,輕量的特點,能夠高效利用物理資源,更快的部署和統一規範的標準化運行環境。通過雲平臺,業務團隊可以實現服務標準化,上線流程規範化,資源利用合理化。
高效利用物理資源,是K8S等雲化方案的主要目標之一,對企業而言也會有很大收益。而要實現這一目標卻並非易事。本文主要講述隨著K8S在58集團應用規模的不斷擴大調度策略逐步演進的歷程。
原生調度的問題
在物理機等非雲化場景下資源利用率較低,因為業務申請的資源是以整臺物理機為單位的,在業務實施過程中,人力很難在業務與機器之間進行合理的調配。而在雲化場景下通過統一資源調度與管控,我們可以獲得動態調節分配資源的能力,這也是我們在雲平臺上做資源優化的基礎。
K8S總體上是master加node結構,如上圖所示。K8S的調度工作主要由master組件中的scheduler模塊負責,根據多種調度策略聯合篩選,確定每個新創建的pod(容器)應該被調度到哪個node(物理機)上去。K8S提供多種調度策略,具體策略的分析不是本文要討論的重點,此處不展開介紹。
K8S原生的調度策略比較簡單,對於一些線下系統基本滿足需求,但是對於追求最大化資源利用的線上系統來說並不適合。主要的原因在於兩點:“基於申請量的調度”和“資源超分”。
1、基於申請量的調度
在K8S中容器的最大可用資源是在部署時指定的(即“申請量”),資源的“使用量”與“申請量”可能關聯不大;比如某個業務申請了4核的cpu資源,實際使用量可能是0.5核,另一個業務申請了4核的cpu資源,則實際可能會使用3核。K8S的原生策略中,資源調度是以“申請量”為依據的,這樣的調度策略會與實際使用情況脫節。
2、資源超分
由於基於“申請量”的調度策略會出現較嚴重的資源浪費。為了提升集群整體資源利用率,我們必須選擇資源“超分”。資源超分是假設所有的容器都不會將資源用滿,並且不會在同一時刻用滿,基於此,我們不為容器按照1:1(實際需求:申請量)預留資源,而是提升這一比例,比如5:1,具體的比例需要根據不同系統來動態調節。在資源超分情況下,K8S原生調度策略的問題就被進一步放大。以一個與實際無關的指標做調度,會導致機器在利用率上傾斜很嚴重,機器頻發“資源耗盡”問題,對系統穩定性構成風險,也阻礙了我們對資源的充分複用,無法體現雲的優勢。
k8s資源動態均衡性調度策略研究
為了更好的提升資源利用率,我們對調度策略進行了深入的研究與分析,不斷迭代與演進。調度策略的演進主要分為兩個階段,基於使用量的調度策略與動態權重調度策略。
基於使用量的調度策略:在調度中用“使用量”替換“申請量”,從cpu單項資源考量,水平擴展到內存、磁盤等三項資源考量。
動態權重調度策略:著力解決多項資源策略如何共存的問題,避免相互影響,提升整體均衡性效果。
基於使用量的調度策略
1、單項資源均衡性
我們首先解決單項資源的調度問題,先從最關鍵的cpu資源入手。
因為“申請量”與“使用量”脫節是原生策略的關鍵缺陷,解決問題的關鍵就是開發一個以“使用量”為依據的調度策略,那麼問題來了:“使用量”怎麼算?一個業務容器,每分每秒cpu使用率都不一樣。並且,每個業務容器受業務特徵與用戶行為的影響,一天當中的不同時段cpu利用率也存在明顯的起伏差異。
通過觀察容器的監控數據,如上圖所示,我們發現絕大部分業務,其資源利用率都有一個明顯的規律性,因用戶的訪問習慣,每天的峰值和低谷時段,都是相對固定的。
因此,我們選定某一個時段作為“評估時段”。我們就以上午9時~10時這一小時的監控數據為基礎進行整合計算。此外,每個業務每天的流量都可能有一定變化,所以我們以最近7天數據的平均值來估算一個容器在高峰時段的cpu消耗預期。
基於上述“預期使用量”數據,並使用與原生策略類似的模式所研究的K8S調度策略,相對於K8S原生策略,具有更好的應用性。
衡量調度的效果,主要看cpu等資源在各個物理機之間分佈的均衡性。如上圖所示,我們繪製的正態分佈曲線,自研策略分佈曲線顯著收窄,這說明機器間的cpu利用率分佈更平均了,可見新策略的cpu均衡性大幅提高。
2、多項資源得分加權求和
針對cpu的調度策略調整獲得了較好的效果。用類似的模式,我們將策略平移到內存、磁盤等資源。這裡的關鍵問題是幾種資源之間的得分加權方式。我們按照K8S原生的模式,以權重乘以單項得分,進行累加。這種權重計算方式我們在線上運行了很長時間,當發現某項資源出現嚴重傾斜時,通過調整權重的方式來達到平衡,但是這樣的做法只能短期緩解,“摁下葫蘆浮起瓢”。比如,增加cpu單項的權重以提升cpu的調度均衡性;而內存的權重便相對得被降低;當內存的均衡性不足時,我們只能加大內存的權重,cpu的權重又相對降低,cpu的均衡性又變差了。
有沒有辦法,讓多個資源策略避免相互影響呢?
經過觀察,我們注意到:容器對資源的需求,通常具有偏向性。容器A消耗大量cpu(比如10核),但內存的消耗卻只有0.5G;相反,容器B可能消耗20G內存,cpu只佔用0.2核。
物理機在使用上也普遍存在資源消耗不平衡,某臺物理機可能cpu消耗了70%,而內存則只使用了20%。在“固定權重”的得分計算模式下,這種不平衡的情況,引起了此物理機得分一直很低,而導致它的80%的內存一直空閒。
動態權重調度策略
1、動態權重自動感知資源偏向性
認識到固定權重導致的問題,以及容器和物理機所展現出來的“資源偏向性”,我們決定設計一種“動態均衡性”策略。
新的策略主要滿足以下幾點:
a) 幾項資源之間,權重動態計算,根據所調度的容器、備選物理機、以及集群總體資源情況,臨時計算一個權重,每次調度都同;
b) 待調度容器對某項資源的需求越高,此項權重越高;
c) 某臺物理機某項資源空閒程度越高,此項得分更高;
d) 集群總體更緊缺的資源,此項權重更高;
我們歸納為一個公式,如下:
公式的細節略顯枯燥,我們舉個例子來說明“動態權重”的算法。
假設存在node-1和node2(node代表物理機)
- node-1 cpu佔用80%,內存佔用30%,磁盤佔用30%(注:此佔用率是基於前文所述容器“預期使用量”數據進行累加計算得出,而非node實時監控數據)。
- node-2 cpu佔用40%,內存佔用70%,磁盤佔用30%。
如果按照“固定權重”的算法,假設三項資源的權重是比1:1:1。
- node-1得分=2*1+7*1+7*1=16。
- node-2得分=6*1+3*1+7*1=16。
得出node-1與node-2得分正好一樣,但實際上兩個node的資源情況存在明顯的差異,一個偏向cpu,另一個偏向內存。並且,上述計算方法,也沒有考慮不同容器的情況。
假設存在兩個容器,pod-a和pod-b(pod代表容器,k8s裡的容器對象)。
- pod-a 預期使用:cpu 4.61核–內存3.02G –磁盤2.1G
- pod-b 預期使用:cpu 0.26核–內存3.62G –磁盤1.8G
針對上述兩個node和兩個pod(容器),採用“動態均衡性”策略進行計算。首先計算pod的“資源需求度”,即前述公式中右側分母中的三項。通過對pod的幾項資源需求做初步計算,“資源需求度”以相對公平的方式,評估pod的幾項資源需求“哪項需求更高”。計算方式就是:“pod某項資源需求量”/“此項資源在集群所有node的平均剩餘量”。
- pod-a 資源需求度:0.21 - 0.05 - 0.01 (分別是cpu - 內存 - 磁盤)
- pod-b 資源需求度:0.00 - 0.06 - 0.01
基於“資源需求度”,我們進一步計算獲得“動態權重”,計算方法就是:“某項資源的需求度”/ “三項資源需求度的均值”,代表了此項資源需求與其他幾項的關係。
- pod-a 權重:2.38 - 0.55 - 0.07(分別是cpu - 內存 - 磁盤)
- pod-b 權重:0.07 - 2.65 - 0.28
基於“動態權重”數值,我們就可以最終計算出pod針對每個node的得分。首先是pod-a:
- Pod-a 對node-1打分:0.2*10*2.38+0.7*10*0.55+0.7*10*0.07= 9.1
- Pod-a 對node-2打分:0.6*10*2.38+0.3*10*0.55+0.7*10*0.07= 16.42
然後是pod-b對node分別打分:
- Pod-b 對node-1打分:0.2*10*0.07+0.7*10*2.65+0.7*10*0.28= 20.65
- Pod-b 對node-2打分:0.6*10*0.07+0.3*10*2.65+0.7*10*0.28= 10.33
通過上述例子可以看出,按照“固定權重”計算時node-1和node-2的得分相同。而採用“動態權重”計算時針對不同的pod(容器)我們獲得了有顯著差異的得分。Pod-a更大概率會被調度到node-2(16.42 > 9.1);pod-b更大概率會被調度到node-1(20.65 > 10.33)。最終結果,每個pod都儘可能找到了最適合自己資源需求的node。
供需雙方的資源與需求實現互補,從理論分析來說,這樣的調度特性,肯定能讓集群整體獲得優秀的資源均衡性。
2、動態均衡策略的效果
集群資源均衡性效果的評估,我們依然以正態分佈曲線來衡量,主要對比cpu和內存的變化。
上圖所示紅色箭頭指向的曲線是cpu調度效果的變化。綠色箭頭指向的曲線是內存調度效果的變化,兩條曲線都明顯收窄。
兩項主要資源,均衡性數據同時獲得大幅提升,設計理論推導符合預期。兩項甚至更多項資源,從此可以和諧共生,在調度層面不再是“競爭者”。
從成本角度看策略的收益
通過對調度策略的優化以及相關保障機制,我們的研究將服務器的資源利用率提升了4倍以上,每年節約以千萬級的資源成本。
資源和成本的縮減,直接因素是我們在用“超分”的方式提供資源。而“超分”的基礎,離不開一套完善的“調度”策略與相關保障機制。只有這樣,我們才能在“超分”的同時還能保障上層業務和雲集群的穩定性。
總結與展望
我們對雲平臺調度策略的研究始終基於平臺自身的業務特點,從實際需求和痛點出發,逐步完善和發展的。業界其他公司也大多對kubernetes調度策略做過自己的定製與擴展,主要採取諸如“資源預測”、“應用畫像”、“反親和調度”等思路。而我們所研究的雲平臺所採取的方案雖然在“資源預測”等方面與同行有一些共通性,不過“多種資源動態均衡”的思路有一定的創新性。後續,我們會逐步將在調度策略方面所做的工作回饋到開源社區。
參考文獻:
1. https://github.com/kubernetes/kubernetes
2. https://kubernetes.io
作者簡介:
陳鵬:架構師,來自58 TEG 雲平臺部, 主要負責雲平臺底層系統的架構與建設工作。