大型Kubernetes集羣的資源編排優化

背景

雲原生這個詞想必你們應該不陌生了,容器是雲原生的重要基石,而Kubernetes通過這幾年的快速迭代發展已經成爲容器編排的事實標準了。愈來愈多的公司不管是大公司仍是中小公司已經在他們的生產環境中開始使用Kubernetes, 原生Kubernetes雖然已經提供了一套很是完整的資源調度及管理方案可是在實際使用過程當中仍是會碰到不少問題:node

  1. 集羣節點負載不均衡的問題
  2. 業務建立Pod資源申請不合理的問題
  3. 業務如何更快速的擴容問題
  4. 多租戶資源搶佔問題

這些問題多是你們在使用Kubernetes的過程當中應該會常常遇到的幾個比較典型的資源問題,接下來咱們將分別介紹在騰訊內部是若是解決和優化這些問題的。負載均衡

集羣節點負載不均衡的問題

咱們知道Kubernetes原生的調度器可能是基於Pod Request的資源來進行調度的,沒有根據Node當前和過去一段時間的真實負載狀況進行相關調度的決策。這樣就會致使一個問題在集羣內有些節點的剩餘可調度資源比較多可是真實負載卻比較高,而另外一些節點的剩餘可調度資源比較少可是真實負載卻比較低, 可是這時候Kube-scheduler會優先將Pod調度到剩餘資源比較多的節點上(根據LeastRequestedPriority策略)。性能

如上圖,很顯然調度到Node1是一個更優的選擇。爲了將Node的真實負載狀況加到調度策略裏,避免將Pod調度到高負載的Node上,同時保障集羣中各Node的真實負載儘可能均衡,咱們擴展了Kube-scheduler實現了一個基於Node真實負載進行預選和優選的動態調度器(Dynamic-scheduler)。優化

Dynamic-scheduler在調度的時候須要各Node上的負載數據,爲了避免阻塞動態調度器的調度這些負載數據,須要有模塊按期去收集和記錄。以下圖所示node-annotator會按期收集各節點過去5分鐘,1小時,24小時等相關負載數據並記錄到Node的annotation裏,這樣Dynamic-scheduler在調度的時候只須要查看Node的annotation便能很快獲取該節點的歷史負載數據。spa

爲了不Pod調度到高負載的Node上,須要先經過預選把一些高負載的Node過濾掉,以下圖所示(其中的過濾策略和比例是能夠動態配置的,能夠根據集羣的實際狀況進行調整)Node2過去5分鐘的負載,Node3過去1小時的負載多超過了對應的域值因此不會參與接下來的優選階段。設計

同時爲了使集羣各節點的負載儘可能均衡,Dynamic-scheduler會根據Node負載數據進行打分, 負載越低打分越高。以下圖所示Node1的打分最高將會被優先調度(這些打分策略和權重也是能夠動態配置的)。資源

Dynamic-scheduler只能保證在調度的那個時刻會將Pod調度到低負載的Node上,可是隨着業務的高峯期不一樣Pod在調度以後這個Node可能會出現高負載。爲了不因爲Node的高負載對業務產生影響咱們在Dynamic-scheduler以外還實現了一個Descheduler,它會監控Node的高負載狀況將一些配置了高負載遷移的Pod遷移到負載比較低的Node上。部署

業務如何更快速的擴容問題

業務上雲的一個重要優點就是在雲上能實現更好的彈性伸縮,Kubernetes原生也提供了這種橫向擴容的彈性伸縮能力(HPA)。可是官方的這個HPA Controller在實現的時候用的是一個Gorountine來處理整個集羣的全部HPA的計算和同步問題,在集羣配置的HPA比較多的時候可能會致使業務擴容不及時的問題,其次官方HPA Controller不支持爲每一個HPA進行單獨的個性化配置。同步

爲了優化HPA Controller的性能和個性化配置問題,咱們把HPA Controller單獨抽離出來單獨部署。同時爲每個HPA單獨配置一個Gorountine,而且每個HPA多能夠根據業務的須要進行單獨的配置。產品

其實僅僅優化HPA Controller仍是不能知足一些業務在業務高峯時候的一些需求,好比在業務作活動的時候但願在流量高峯期以前就可以把業務擴容好。這個時候咱們就須要一個定時HPA的功能,爲此咱們定義了一個CronHPA的CRD和CronHPA Operator。CronHPA會在業務定義的時間進行擴容和縮容,同時還能和HPA一塊兒配合工做。

業務建立Pod資源申請不合理的問題

經過Dynamic-scheduler和Descheduler來保障集羣各節點的負載均衡問題。可是我可能會面臨另外一個比較頭疼的問題就是集羣的總體負載比較低可是可調度資源已經沒有了,從而致使Pod Pending。這個每每是因爲Pod 資源申請不合理或者業務高峯時段不一樣所致使的,那咱們是否能夠根據Node負載狀況對Node資源進行必定比例的超賣呢。因而咱們經過Kubernetes的MutatingWebhook來截獲並修改Node的可調度資源量的方式來對Node資源進行超賣。

這裏須要注意的是節點的超賣控制須要比較靈活不能一律而論,好比負載高的Node超賣比例應該要設置比較小或者不能設置超賣。

多租戶資源搶佔問題

當平臺用戶增多的時候,若是對資源不作任何控制那麼各租戶之間資源搶佔是不可避免的。Kubernetes原生提供的ResourceQuota能夠提供Namespace級別對資源配額限制。可是騰訊內部資源預算管理一般是按產品維度,而一個產品可能會包括不少Namespace的顯然ResourceQuota不太適合這種場景。其次ResourceQuota只有資源限制功能不能作資源預留,當業務要作活動的時候不能保證活動期間有足夠的資源可使用。

爲了實現一個產品維度且有資源預留功能的配額管理功能,咱們設計了一個DynamicQuota的CRD來管理產品在各集羣的配額。以下圖所示產品2在各集羣所佔的配額資源其它產品多沒法使用。

若是一個產品佔用配額一直不使用就可能會致使平臺資源的浪費,所以咱們在產品配額預留的基礎上提供了在不一樣產品間配額借調的功能。以下圖所示產品1暫時不用的配額能夠借調給產品2臨時使用。

當平臺有多集羣的時候,產品配額須要如何分配。爲了簡化配下發操做,以下圖所示管理員在下發產品配額的時候只需配置一個該產品的配額總量,配額下發模塊會根據產品目前在各集羣的使用狀況按比例分配到各個集羣。

產品在各集羣的資源使用狀況是會時刻變化的,因此產品在各集羣配額也須要根據業務的使用狀況進行動態的調整。以下圖所示產品在集羣2中的配額已經快用完的時候,配額調整模塊會動態的把配額從使用很少的集羣1和集羣3調到集羣2。

在線業務和離線業務混合部署是雲平臺的發展趨勢,因此咱們在設計配額管理的時候也把在離線配額控制考慮進去了。以下圖所示咱們在集羣維度加了一個離線配額控制,一個集羣的離線業務資源使用不能超過該集羣總資源的30%(這個比例能夠根據實際狀況進行調整)。其次一個產品的在線業務和離線業務配額之和又不能超過產品在該集羣的總配額。

總結

上面提到的方案只是簡單說了一下咱們的一些解決問題的思路,其實在真正運做的過程當中還有不少細節須要考慮和優化。好比:上面提到的產品配額管理若是一個產品的配額不足了,這時候業務有高峯須要進行HPA擴容,這時候配額管理模塊須要對這種擴容優化並放行。
【騰訊雲原生】雲說新品、雲研新術、雲遊新活、雲賞資訊,掃碼關注同名公衆號,及時獲取更多幹貨!!

相關文章
相關標籤/搜索