天天看點

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》
導讀:Serverless 和 Autoscaling 是近些年來廣大開發者非常關心的内容。有人說 Serverless 是容器 2.0,終有一天容器會和 Serverless 進行一場決戰,分出勝負。實際上,容器和 Serverless 是可以共存并且互補的,特别是在 Autoscaling 相關的場景下,Serverless 可以與容器完美相容,彌補容器場景在使用簡單、速度、成本的缺欠,在本文中将會為大家介紹容器在彈性場景下的原理、方案與挑戰,以及 Serverless 是如何幫助容器解決這些問題的。

當我們在談論"彈性伸縮"的時候

當我們在談論"彈性伸縮"的時候,我們在談論什麼?"彈性伸縮"對于團隊中不同的角色有不同的意義,而這正是彈性伸縮的魅力所在。

從一張資源曲線圖講起

這張圖是闡述彈性伸縮問題時經常引用的一張圖,表示的是叢集的實際資源容量和應用所需容量之間的關系。

  • 其中紅色的曲線表示的是應用實際所需的容量,因為應用的資源申請量相比節點而言會小很多,是以曲線相對比較平滑;
  • 而綠色的折線表示的是叢集的實際資源容量,折線的拐點表明此時進行了手動的容量調整,例如增加節點或者移除節點,因為單個節點的資源容量固定且相對較大,是以以折線為主。
《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

首先,我們先看左側第一塊黃色栅格的區域,這個區域表示叢集的容量無法滿足業務的容量所需,在實際的場景中,通常會伴随出現由于資源不足而無法排程的 Pod 等現象。

中間的栅格區域,叢集的容量遠高于實際資源所需的容量,此時會出現資源的浪費,實際的表現通常是節點的負載配置設定不均,部分節點上面無排程負載,而另外一些節點的負載相對較高。

右側栅格區域表示的是激增的峰值容量,我們可以看到,到達峰值前的曲率是非常陡峭的,這種場景通常是由于流量激增、大批量任務等非正常容量規劃内的場景,激增的峰值流量給運維同學的反應時間非常短,一旦處理不當就有可能引發事故。

彈性伸縮對于不同角色的人員,有着不同的意義:

  • 開發人員希望通過彈性伸縮使應用獲得高可用的保障;
  • 運維人員希望通過彈性伸縮降低基礎設施的管理成本;
  • 架構師希望通過彈性伸縮得到靈活彈性的架構應對突發的激增峰值。

彈性伸縮有多種不同的元件和方案,選擇适合自己業務需求的方案是落地執行前的第一步。

Kubernetes 彈性伸縮能力解讀

Kubernetes 彈性伸縮的相關元件

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

Kubernetes 彈性伸縮的元件可以從兩個次元進行解讀:一個是伸縮方向,一個是伸縮對象。

從伸縮方向上,分為橫向與縱向。從伸縮對象上,分為節點與 Pod。那麼将這個象限進行展開,就變成如下 3 類元件:

  1. cluster-autoscaler,節點水準伸縮;
  2. HPA & cluster-proportional-autoscaler,Pod 水準伸縮;
  3. vertical pod autoscaler&addon resizer,Pod 縱向伸縮。

其中 HPA 與 Cluster-Autoscaler 是開發者最常組合使用的彈性伸縮元件。HPA 負責容器的水準伸縮,Cluster-Autoscaler 負責節點的水準伸縮。很多的開發者會産生這樣的疑問:為什麼彈性伸縮一個功能需要細化成這麼多元件分開處理,難道不可以直接設定一個門檻值,就實作叢集的自動水位管理嗎?

Kubernetes 的彈性伸縮挑戰

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

了解 Kubernetes 的排程方式可以幫助開發者更好的了解 Kubernetes 彈性伸縮的設計哲學。在 Kubernetes 中,排程的最小單元是一個 Pod,Pod 會根據排程政策被排程到滿足條件的節點上,這些政策包括資源的比對關系、親和性與反親和性等等,其中資源的比對關系的計算是排程中的核心要素。

通常和資源相關的有如下四個概念:

  • Capacity 表示一個節點所能配置設定的容量總量;
  • Limit 表示一個 Pod 能夠使用的資源總量;
  • Request 表示一個 Pod 在排程上占用的資源空間;
  • Used 表示一個 Pod 的真實資源使用。

在了解這四個基本概念和使用場景之後,我們再來看下 Kubernetes 彈性伸縮的三大難題:

1.容量規劃炸彈

還記得在沒有使用容器前,是如何做容量規劃的嗎?一般會按照應用來進行機器的配置設定,例如,應用 A 需要 2 台 4C8G 的機器,應用 B 需要 4 台 8C16G 的機器,應用 A 的機器與應用 B 的機器是獨立的,互相不幹擾。到了容器的場景中,大部分的開發者無需關心底層的資源了,那麼這個時候容量規劃哪裡去了呢?

在 Kubernetes 中是通過 

Request

 和 

Limit

 的方式進行設定,

Request

 表示資源的申請值,

Limit

 表示資源的限制值。既然 

Request

 和 

Limit

 才是容量規劃的對等概念,那麼這就代表着資源的實際計算規則要根據 

Request

 和 

Limit

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

2.百分比碎片陷阱

在一個 Kubernetes 叢集中,通常不隻包含一種規格的機器。針對不同的場景、不同的需求,機器的配置、容量可能會有非常大的差異,那麼叢集伸縮時的百分比就具備非常大的迷惑性。

假設我們的叢集中存在 4C8G 的機器與 16C32G 兩種不同規格的機器,對于 10% 的資源預留而言,這兩種規格是所代表的意義是完全不同的。特别是在縮容的場景下,通常為了保證縮容後的叢集不處在震蕩狀态,我們會一個節點一個節點來縮容節點,那麼如何根據百分比來判斷目前節點是處在縮容狀态就尤為重要。此時如果大規格機器有較低的使用率被判斷縮容,那麼很有可能會造成節點縮容後,容器重新排程後的争搶饑餓。如果添加判斷條件,優先縮容小配置的節點,則有可能造成縮容後資源的大量備援,最終叢集中可能會隻剩下所有的

巨石

節點。

3.資源使用率困境

叢集的資源使用率是否可以真的代表目前的叢集狀态呢?當一個 Pod 的資源使用率很低的時候,不代表就可以侵占他所申請的資源。在大部分的生産叢集中,資源使用率都不會保持在一個非常高的水位,但從排程來講,資源的排程水位應該保持在一個比較高的水位。這樣才能既保證叢集的穩定可用,又不過于浪費資源。

如果沒有設定 

Request

 與 

Limit

,而叢集的整體資源使用率很高,這意味着什麼?這表示所有的 Pod 都在被以真實負載為單元進行排程,互相之間存在非常嚴重的争搶,而且簡單的加入節點也絲毫無法解決問題,因為對于一個已排程的 Pod 而言,除了手動排程與驅逐,沒有任何方式可以将這個 Pod 從高負載的節點中移走。那如果我們設定了 

Request

 與 

Limit

 而節點的資源使用率又非常高的時候說明了什麼呢?很可惜這在大部分的場景下都是不可能的,因為不同的應用不同的負載在不同的時刻資源的使用率也會有所差異,大機率的情況是叢集還沒有觸發設定的門檻值就已經無法排程 Pod 了。

在了解了 Kubernetes 彈性伸縮的三大問題後,我們再來看下 Kubernetes 的解決辦法是什麼?

Kubernetes 的彈性伸縮設計哲學

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

Kubernetes 的設計理念是将彈性伸縮分成排程層伸縮和資源層伸縮。排程層負責根據名額、門檻值伸縮出排程單元,而資源層伸縮負責滿足排程單元的資源需求。

在排程層通常是通過 HPA 的方式進行 Pod 的水準伸縮,HPA 的使用方式和我們傳統意義上了解的彈性伸縮是非常接近和類似的,通過設定判斷的名額、判斷的門檻值來進行水準伸縮。

在資源層目前主流的方案是通過 cluster-autoscaler 進行節點的水準伸縮。當出現 Pod 由于資源不足造成無法排程時,cluster-autoscaler 會嘗試從配置伸縮組中,選擇一個可以滿足排程需求的組,并自動向組内加入執行個體,當執行個體啟動後注冊到 Kubernetes 後,kube-scheduler 會重新觸發 Pod 的排程,将之前無法排程的 Pod 排程到新生成的節點上,進而完成全鍊路的擴容。

同樣在縮容時,排程層會現根據資源的使用率與設定的門檻值比較,實作 Pod 水準的縮容。當節點上 Pod 的排程資源降低到資源層縮容門檻值的時候,此時 Cluster-Autoscaler 會進行低排程百分比的節點的排水,排水完成後會進行節點的縮容,完成整個鍊路的收縮。

Kubernetes 彈性伸縮方案的阿克琉斯之踵

經典的 Kubernetes 彈性伸縮的案例

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

這張圖是一個非常經典的彈性伸縮的案例,可以代表大多數的線上業務的場景。應用的初始架構是一個 Deployment,下面有兩個 Pod,這個應用的接入層是通 過Ingress Controller 的方式進行對外暴露的,我們設定應用的伸縮政策為:單個 Pod 的 QPS 到達 100,則進行擴容,最小為 2 個 Pod,最大為 10 個 Pod。

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

HPA controller 會不斷輪訓 alibaba-cloud-metrics-adapter,來擷取 Ingress Gateway 目前路由的 QPS 名額。當 Ingress Gateway 的流量到達 QPS 門檻值時,HPA controller 會觸發 Deployment 的 Pod 數目變化;當 Pod 的申請容量超過叢集的總量後,cluster-autoscaler 會選擇合适的伸縮組,彈出相應的 Node,承載之前未排程的 Pod。

這樣一個經典的彈性伸縮案例就解析完畢了,那麼在實際的開發過程中,會遇到哪些問題呢?

經典的 Kubernetes 彈性伸縮的缺點與解法

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

首先是擴容時延的問題,社群标準模式是通過建立、釋放 ECS 的方式,擴容的時延在 2min-2.5min 左右,而阿裡雲獨立的極速模式是通過建立、停機、啟動的方式進行實作,停機時隻收取存儲的費用,不收取計算的費用。可以通過非常低廉的價格獲得 50% 以上的彈性效率。

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

此外複雜度也是 cluster-autoscaler 繞不過的問題,想要用好 cluster-autoscaler,需要深入的了解 cluster-autoscaler 的一些内部機制,否則極有可能造成無法彈出或者無法縮容的場景。

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

對于大多數的開發者而言,cluster-autoscaler 的工作原理是黑盒的,而且 cluster-autoscaler 目前最好的問題排查方式依然是檢視日志。一旦 cluster-autoscaler 出現運作異常後者由于開發者配置錯誤導緻無法如預期的伸縮,那麼 80% 以上的開發者是很難自己進行糾錯的。

阿裡雲容器服務團隊開發了一款 kubectl plugin,可以提供 cluster-autoscaler 更深層次的可觀測性,可以檢視目前 cluster-autoscaler 所在的伸縮階段以及自動彈性伸縮糾錯等能力。

雖然目前遇到的幾個核心的問題,都不是壓死駱駝的最後一棵稻草。但是我們一直在思考,是否有其他的方式可以讓彈性伸縮使用起來更簡單、更高效?

阿克琉斯的馬丁靴 - Serverless Autoscaling

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

資源層伸縮的核心問題在于學習成本較高、排錯困難、時效性差。當回過頭來看 Serverless 的時候,我們可以發現這些問題恰好是 Serverless 的特點與優勢,那麼是否有辦法讓 Serverless 成為 Kubernetes 資源層的彈性方案呢?

Serverless Autoscaling 元件 - virtual-kubelet-autoscaler

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

阿裡雲容器服務團隊開發了 virtual-kubelet-autoscaler,一個在 Kubernetes 中實作 serverless autoscaling 的元件。

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

當出現了無法排程的 Pod 的時候,virtual-kubelet 負責承載真實的負載,可以了解為一個虛拟節點,擁有無限大的 capacity。當 Pod 排程到 virtual-kubelet 上時,會将 Pod 通過輕量級執行個體 ECI 進行啟動。目前 ECI 的啟動時間在 30s 之内,程式從排程開始到運作一般會在 1 分鐘内拉起。

《Serverless 與容器決戰在即?有了彈性伸縮就不一樣了》

與 cluster-autoscaler 類似,virtual-kubelet-autoscaler 也需要使用模拟排程的機制來判斷 Pod 是否可以被真實處理和承載,但是相比 cluster-autoscaler 而言,存在如下差異:

  1. virtual-kubelet-autoscaler 模拟排程的對象是增加了排程政策的 Pod Template 并非 Node Template。
  2. virtual-kubelet-autoscaler 的核心是選擇 virtual-kubelet 來承載負載,一旦 Pod 模拟排程成功綁定到 virtual-kubelet 上後,Pod 的生命周期管理、問題的排查等就與傳統的 Pod 沒有差異,不再是黑盒排查問題。

virtual-kubelet-autoscaler 不是"銀彈"

virtual-kubelet-autoscaler 并不是用來替代 cluster-autoscaler 的,virtual-kubelet-autoscaler 的優勢在于使用簡單、高彈性高并發,按量按需計費。但是與此同時也犧牲了部分的相容性,目前對 cluster-pi、coredns 等機制支援的還并不完善,隻需少許的配置 virtual-kubelet-autoscaler 是可以和 cluster-autoscaler 相容的。virtual-kubelet-autoscaler 特别适合的場景是大資料離線任務、CI/CD 作業、突發型線上負載等。

最後

serverless autoscaling 已經逐漸成為 Kubernetes 彈性伸縮的重要組成部分,當 serverless autoscaling 相容性基本補齊的時候,serverless 使用簡單、無需運維、成本節約的特性會與 Kubernetes 形成完美互補,實作 Kubernetes 彈性伸縮的新飛躍。

原文連結

本文為雲栖社群原創内容,未經允許不得轉載。

繼續閱讀