1. 程式人生 > >Kubernetes 彈性伸縮全場景解析 (一):概念延伸與元件佈局

Kubernetes 彈性伸縮全場景解析 (一):概念延伸與元件佈局

傳統彈性伸縮的困境

彈性伸縮是 Kubernetes 中被大家關注的一大亮點,在討論相關的元件和實現方案之前。首先想先給大家擴充下彈性伸縮的邊界與定義,傳統意義上來講,彈性伸縮主要解決的問題是容量規劃與實際負載的矛盾。 <br />如上圖所示,藍色的水位線表示叢集的容量隨著負載的提高不斷的增長,紅色的曲線表示叢集的實際的負載真實的變化。而彈性伸縮要解決的就是當實際負載出現激增,而容量規劃沒有來得及反應的場景。 常規的彈性伸縮是基於閾值的,通過設定一個資源緩衝水位來保障資源的充盈,通常 15%-30% 左右的資源預留是比較常見的選擇。換言之就是通過一個具備緩衝能力的資源池用資源的冗餘換取叢集的可用。 這種方式表面上看是沒有什麼問題的,確實在很多的解決方案或者開源元件中也是按照這種方式進行實現的,但是當我們深入的思考這種實現方案的時候會發現,這種方式存在如下三個經典問題。

1. 百分比碎片難題

在一個 Kubernetes 叢集中,通常不只包含一種規格的機器,針對不同的場景、不同的需求,機器的配置、容量可能會有非常大的差異,那麼叢集伸縮時的百分比就具備非常大的迷惑性。假設我們的叢集中存在 4C8G 的機器與 16C32G 的機器兩種不同規格,對於 10% 的資源預留,這兩種規格是所代表的意義是完全不同的。 <br />特別是在縮容的場景下,通常為了保證縮容後的叢集不處在震盪狀態,我們會一個節點一個節點或者二分法來縮容節點,那麼如何根據百分比來判斷當前節點是處在縮容狀態就尤為重要,此時如果大規格機器有較低的利用率被判斷縮容,那麼很有可能會造成節點縮容後,容器重新排程後的爭搶飢餓。如果新增判斷條件,優先縮容小配置的節點,則有可能造成縮容後資源的大量冗餘,最終叢集中可能會只剩下所有的巨石

節點。

2. 容量的規劃炸彈

還記得在沒有使用容器前,是如何做容量規劃的嗎?一般會按照應用來進行機器的分配,例如,應用 A 需要 2 臺 4C8G 的機器,應用 B 需要 4 臺 8C16G 的機器,應用 A 的機器與應用 B 的機器是獨立的,相互不干擾。到了容器的場景中,大部分的開發者無需關心底層的資源了,那麼這個時候容量規劃哪裡去了呢?<br /> <br />在 Kubernetes 中是通過 Request 和 Limit 的方式進行設定,Request 表示資源的申請值,Limit 表示資源的限制值。既然 Request 和 Limit 才是容量規劃的對等概念,那麼這就代表著資源的實際計算規則要根據 Request

 和 Limit 才更加準確。而對於每個節點預留資源閾值而言,很有可能會造成小節點的預留無法滿足排程,大節點的預留又排程不完的場景。

3. 資源利用率困境

叢集的資源利用率是否可以真的代表當前的叢集狀態呢?當一個 Pod 的資源利用率很低的時候,不代表就可以侵佔它所申請的資源。在大部分的生產叢集中,資源利用率都不會保持在一個非常高的水位,但從排程來講,資源的排程水位應該保持在一個比較高的水位。這樣才能既保證叢集的穩定可用,又不過於浪費資源。 如果沒有設定 Request 與 Limit,而叢集的整體資源利用率很高這意味著什麼?這表示所有的 Pod 都在被以真實負載為單元進行排程,相互之間存在非常嚴重的爭搶,而且簡單的加入節點也絲毫無法解決問題,因為對於一個已排程的 Pod 而言,除了手動排程與驅逐之外沒有任何方式可以將這個 Pod 從高負載的節點中移走。那如果我們設定了 Request 與 Limit 而節點的資源利用率又非常高的時候說明了什麼呢?很可惜這在大部分的場景下都是不可能的,因為不同的應用不同的負載在不同的時刻資源的利用率也會有所差異,大概率的情況是叢集還沒有觸發設定的閾值就已經無法排程 Pod 了。

彈性伸縮概念的延伸

既然基於資源利用率的彈性伸縮有上述已知的三個問題,有什麼辦法可以來解決呢?隨著應用型別的多樣性發展,不同型別的應用的資源要求也存在越來越大的差異。彈性伸縮的概念和意義也在變化,傳統理解上彈性伸縮是為了解決容量規劃和線上負載的矛盾,而現在是資源成本與可用性之間的博弈。如果將常見的應用進行規約分類,可以分為如下四種不同型別:<br />

1. 線上任務型別

比較常見的是網站、API 服務、微服務等常見的網際網路業務型應用,這種應用的特點是對常規資源消耗較高,比如 CPU、記憶體、網路 IO、磁碟 IO 等,對於業務中斷容忍性差。

2. 離線任務型別

例如大資料離線計算、邊緣計算等,這種應用的特點是對可靠性的要求較低,也沒有明確的時效性要求,更多的關注點是成本如何降低。

3. 定時任務型別

定時執行一些批量計算任務是這種應用的比較常見形態,成本節約與排程能力是重點關注的部分。

4. 特殊任務型別

例如閒時計算的場景、IOT 類業務、網格計算、超算等,這類場景對於資源利用率都有比較高的要求。 單純的基於資源利用率的彈性伸縮大部分是用來解決第一種型別的應用而產生的,對於其他三種類型的應用並不是很合適,那麼 Kubernetes 是如何解決這個問題的呢?

Kubernetes 的彈性伸縮佈局

Kubernetes 將彈性伸縮的本質進行了抽象,如果拋開實現的方式,對於不同應用的彈性伸縮而言,該如何統一模型呢? Kubernetes 的設計思路是將彈性伸縮劃分為保障應用負載處在容量規劃之內與保障資源池大小滿足整體容量規劃兩個層面。簡單理解,當需要彈性伸縮時,優先變化的應該是負載的容量規劃,當叢集的資源池無法滿足負載的容量規劃時,再調整資源池的水位保證可用性。而兩者相結合的方式是無法排程的 Pod 來實現的,這樣開發者就可以在叢集資源水位較低的時候使用 HPA、VPA 等處理容量規劃的元件實現實時極致的彈性,資源不足的時候通過 Cluster-Autoscaler 進行叢集資源水位的調整,重新排程,實現伸縮的補償。兩者相互解耦又相互結合,實現極致的彈性。

在 Kubernetes 的生態中,在多個維度、多個層次提供了不同的元件來滿足不同的伸縮場景。如果我們從伸縮物件與伸縮方向兩個方面來解讀 Kubernetes 的彈性伸縮的話,可以得到如下的彈性伸縮矩陣。

  • cluster-autoscaler: kubernetes 社群中負責節點水平伸縮的元件,目前處在 GA 階段 (General Availability, 即正式釋出的版本)。
  • HPA: kubernetes 社群中負責 Pod 水平伸縮的元件,是所有伸縮元件中歷史最悠久的,目前支援 autoscaling/v1、 autoscaling/v2beta1 與 autoscaling/v2beta2, 其中 autoscaling/v1 只支援 CPU 一種伸縮指標,在 autoscaling/v2beta1 中增加支援 custom metrics,在 autoscaling/v2beta2 中增加支援 external metrics。
  • cluster-proportional-autoscaler: 根據叢集的節點數目,水平調整 Pod 數目的元件,目前處在 GA 階段。
  • vetical-pod-autoscaler: 根據 Pod 的資源利用率、歷史資料、異常事件,來動態調整負載的 Request 值的元件,主要關注在有狀態服務、單體應用的資源伸縮場景,目前處在 beta 階段。
  • addon-resizer: 根據叢集中節點的數目,縱向調整負載的 Request 的元件,目前處在 beta 階段。

在這五個元件中, cluster-autoscaler、 HPA、 cluster-proportional-autoscaler 是目前比較穩定的元件,建議有相關需求的開發者進行選用。

對於百分之八十以上的場景,我們建議客戶通過 HPA 結合 cluster-autoscaler 的方式進行叢集的彈性伸縮管理, HPA 負責負載的容量規劃管理而 cluster-autoscaler 負責資源池的擴容與縮容。

最後

在本文中,和大家主要討論的是在雲原生時代下彈性伸縮概念的延伸,以及 Kubernetes 社群是如何通過解耦的方式通過多個轉職的元件實現了兩個維度的彈性伸縮,在本系列後面的文章中會為一一解析每個彈性伸縮元件的相