本文介紹了Airbnb的叢集擴縮容的演化歷史,以及當前是如何通過Cluster Autoscaler 實現自定義擴充套件器的。最重要的經驗就是Airbnb是如何一步步演化到當前架構的,其驅動因素又是什麼。
譯自:Dynamic Kubernetes Cluster Scaling at Airbnb
Airbnb的基礎設施的一個重要作用是保證雲能夠根據需要自動執行擴縮容。我們每天的流量波動都非常大,需要依靠動態擴縮容來保證服務的正常執行。
為了支援擴縮容,Airbnb使用了Kubernetes編排系統。並且使用了一種基於Kubernetes的服務設定介面,OneTouch,具體參見這裡。
本文中,我們將討論如何使用Kubernetes Cluster Autoscaler來動態調整叢集的大小,並著重介紹了我們為Sig-Autoscalsing社群做出的貢獻。
過去幾年中,Airbnb已經將絕大部分手動編排的EC2範例中遷移到了Kubernetes上。如今,我們在近百個叢集中執行了上千個節點來容納這些負載。然而,這些變化並不是一蹴而就的。在遷移過程中,底層的Kubernetes叢集也同樣進行著演進。隨著新技術棧上的負載和流量越來越多,Kubernetes叢集也隨之變得越來越成熟。這些演進可以劃分為如下幾個階段:
在使用Kubernetes之前,每個服務範例都執行在其所在的機器上,通過手動分配足夠的容量來滿足流量增加的場景。每個團隊的容量管理方式都不盡相同,且一旦負載下降,很少會取消設定。
一開始我們的Kubernetes叢集的設定相對比較簡單。我們有少量叢集,每個叢集都有單獨的底層節點型別和設定,用於執行無狀態的線上服務。隨著服務開始遷移到Kubernetes,我們開始在一個多租戶(一個節點有多個pods)環境中執行容器化的服務。這種聚合方式減少了資源浪費,並且可以將這些服務的容量管理整合到Kuberentes控制平面上。在這個階段,我們實現了叢集的手動擴縮容,但相比之前仍然有著顯著的提升。
叢集設定的第二個階段是伴隨多負載型別出現的,每個試圖在Kubernetes上執行的負載都有著不同的需求。為了符合這些需求,我們建立了一個抽象的叢集型別。"叢集型別"定義了叢集的底層設定,這意味著相同叢集型別的叢集,從節點型別到叢集元件設定都是相同的。
越來越多的叢集型別導致出現了越來越多的叢集,一開始通過手動方式來調節每個叢集容量的方式迅速變得支離破碎。為了修正這個問題,我們為每個叢集新增了Kubernetes Cluster Autoscaler 。該元件會基於pod requests來動態調節叢集的大小。如果一個叢集的容量被耗盡,則會通過新增一個新的節點(由Cluster Autoscaler拉起)來滿足pending狀態的pods。類似地,如果在一段時間內叢集的某些節點的利用率偏低,則Cluster Autoscaler會移除這些節點。這種方式行之有效,為我們節省了大約5%的總雲開銷,以及手動擴充套件叢集的操作開銷。
當Airbnb的幾乎所有線上計算都轉移到Kubernetes時,叢集的型別已經超過30,叢集數目超過100。這種擴充套件使得Kubernetes叢集管理相當乏味。例如,在叢集升級時需要單獨對每種型別的叢集進行測試。
在第三個階段,我們會通過建立異構叢集來整合叢集型別,使用單個Kubernetes控制平面來適應多種不同的工作負載。首先,這種方式極大降低了叢集管理的開銷,通過更少且更通用的叢集減少了需要測試的設定數目。其次,隨著Airbnb 的主要服務已經執行在了Kubernetes叢集上,叢集的效率可以為成本優化提供一個很大的槓桿。整合叢集型別可以允許我們在每個叢集中執行多種負載。這種聚合的負載型別(有些大,有些小)可以帶來更好的封裝和效率,以及更高的利用率。通過這種額外的負載靈活性,我們可以有更多的空間來在預設的Cluster Autoscaler擴充套件邏輯之外,實現成熟的擴縮容策略。特別地,我們計劃實現與Airbnb特定業務邏輯相關的擴縮容邏輯。
隨著對叢集的擴充套件和整合,我們實現了異構(每個叢集有多種範例型別),我們開始在擴充套件過程中實現特定的業務邏輯,並且意識到有必要對擴縮容的行為進行某些變更。下一節將描述我們是如何修改Cluster Autoscaler,使其變得更加靈活。
我們對Cluster Autoscaler的最顯著改進是提供了一種新方法來確定要擴充套件的節點組。在內部,Cluster Autoscaler會維護一系列對映到不同候選擴容物件的節點組,它會針對當前Pending(無法排程)的pods執行模擬排程,然後過濾掉不滿足排程要求的節點組。如果存在Pending(無法排程)的pods,Cluster Autoscaler會嘗試通過擴充套件叢集來滿足這些pods。所有滿足pod要求的節點組都會被傳遞給稱為Expander的元件。
Expander 負責基於執行要求進一步過濾節點組。Cluster Autoscaler有大量內建的擴充套件器選項,每個選型都有不同的處理邏輯。例如,預設是隨機擴充套件器,它會隨機選擇可用的節點組。另一個是Airbnb 曾經使用過的優先順序擴充套件器,它會基於使用者指定的優先順序列表來選擇需要擴充套件的節點組。
當我們使用異構叢集邏輯的同時,我們發現預設的擴充套件器無法在成本和範例型別選擇上滿足複雜的業務需求。
假設,我們想要實現一個基於權重的優先順序擴充套件器。目前的優先順序擴充套件器僅允許使用者為節點組設定不同的等級,這意味著它會始終以確定的順序來擴充套件節點組。如果某個等級有多個節點組,則會隨機選擇一個節點組。基於權重的優先順序策略可以支援在同一個等級下設定兩個節點組,其中80%的時間會擴充套件一個節點組,另外20%的時間會擴充套件另一個節點組。但預設並不支援基於權重的擴充套件器。
除了現有擴充套件器的某些限制外,還有一些操作上的考量:
至此,我們對Cluster Autoscaler中的新擴充套件器型別提出了一系列要求:
鑑於這些需求,我們提出了一種設計,將擴充套件職責從Cluster Autoscaler的核心邏輯中分離出來。我們設計了一種外掛自定義擴充套件器,它實現了gRPC使用者端(類似custom cloud provider),這種自定義擴充套件器分為兩個元件。
第一個元件是內建到Cluster Autoscaler中的gRPC使用者端。這種擴充套件器使用與Cluster Autoscaler中的其他擴充套件器相同的介面,負責將Cluster Autoscaler中的有效節點組資訊轉換為定義好的protobuf 格式(見下文),接收gRPC 伺服器端的輸出,並將其轉換為最終的可選列表,提供給Cluster Autoscaler進行擴容。
service Expander {
rpc BestOptions (BestOptionsRequest) returns (BestOptionsResponse)
}message BestOptionsRequest {
repeated Option options;
map<string, k8s.io.api.core.v1.Node> nodeInfoMap;
}message BestOptionsResponse {
repeated Option options;
}message Option {
// ID of node to uniquely identify the nodeGroup
string nodeGroupId;
int32 nodeCount;
string debug;
repeated k8s.io.api.core.v1.Pod pod;
}
第二個元件是gRPC伺服器端,這需要由使用者實現。該伺服器端作為一個獨立的應用或服務。通過使用者端傳遞的資訊以及複雜的擴充套件邏輯來選擇需要擴容的節點組。當前通過gRPC傳遞的protobuf 訊息是 Cluster Autoscaler中傳遞給擴充套件器的內容的(略微)轉換版本。
在前面的例子中,基於權重的隨機優先順序擴充套件器可以很容易地通過伺服器端來讀取優先順序列表,並通過confimap設定權重百分比來實現。
我們的實現還包含一個故障保護選項。建議使用該選項將多個擴充套件器作為引數傳遞給Cluster Autoscaler。使用該選擇後,如果伺服器端出現故障,Cluster Autoscaler仍然能夠使用一個備用的擴充套件器進行擴充套件。
由於伺服器端作為一個獨立的應用,因此可以在Cluster Autoscaler外開發擴充套件邏輯,且gRPC伺服器端可以根據使用者需求實現自定義,因此這種方案對整個社群來說也非常有用。
從2022年開始,Airbnb 已經在內部使用這種方案來擴縮容所有的叢集,當中沒有出現任何問題。它允許我們動態地選擇何時去擴充套件特定的節點組來滿足Airbnb 的業務需求。通過這種方式實現了最初的開發目標--可延伸的自定義擴充套件器。
在遷移到異構Kubernetes叢集的過程中,我們發現了其他一些可以對Cluster Autoscaler進行改進的bug。以下簡要介紹:
在過去的四年中,在Kubernetes叢集設定中,Airbnb已經走了很長的路。Airbnb在單個平臺上擁有最大的計算量,這為提高效率提供了強大的整合槓桿,我們現在專注於推廣我們的叢集設定。通過在Cluster Autoscaler 中開發和引入更加成熟的擴充套件器,可以實現更加複雜、圍繞成本和多範例型別的特定擴充套件策略,並將有用的特性回饋社群。
本文來自部落格園,作者:charlieroro,轉載請註明原文連結:https://www.cnblogs.com/charlieroro/p/16497628.html