Airbnb的動態 Kubernetes 叢集擴縮容
Airbnb 基礎設施的一個重要作用是保證我們的雲能夠根據需求上升或下降進行自動擴縮容。我們每天的流量波動都非常大,需要依靠動態擴縮容來保證服務的正常執行。
為了支援擴縮容,Airbnb 使用了 Kubernetes 編排系統,並且使用了一種基於 Kubernetes 的服務配置介面[1]。
本文我們將討論如何使用 Kubernetes Cluster Autoscaler 來動態調整叢集的大小,並著重介紹了我們為 Sig-Autoscalsing 社群[2]做出的貢獻。這些改進增加了可定製性和靈活性,以滿足 Airbnb 獨特的業務需求。
Airbnb 的 Kubernetes 叢集
過去幾年中,Airbnb 已經將幾乎所有的線上服務從手動編排的 EC2 例項遷移到了 Kubernetes。如今,我們在近百個叢集中執行了上千個節點來適應這些工作負載。然而,這些變化並不是一蹴而就的。在遷移過程中,隨著新技術棧上的工作負載和流量越來越多,我們底層的 Kubernetes 叢集也隨之變得越來越複雜。這些演變可以劃分為如下三個階段:
階段 1:同質叢集,手動擴縮容
在使用 Kubernetes 之前,每個服務例項都執行在其所在的機器上,透過手動分配足夠的容量來滿足流量增加的場景。每個團隊的容量管理方式都不盡相同,且一旦負載下降,很少會取消配置。
一開始我們的 Kubernetes 叢集的配置相對比較簡單。我們有幾個叢集,每個叢集都有單獨的底層節點型別和配置,它們只執行無狀態的線上服務。隨著服務開始遷移到 Kubernetes,我們開始在多租戶環境中執行容器化的服務。這種聚合方式減少了資源浪費,並且將這些服務的容量管理整合到 Kuberentes 控制平面上。在這個階段,我們手動擴充套件我們的叢集,但相比之前仍然有著顯著的提升。
階段 2:多叢集型別,獨立擴縮容
我們叢集配置的第二個階段是因為更多樣化的工作負載而出現的,每個試圖在 Kubernetes 上執行的工作負載都有著不同的需求。為了滿足這些需求,我們建立了一個抽象的叢集型別。叢集型別定義了叢集的底層配置,這意味著叢集型別的所有叢集都是相同的,從節點型別到叢集元件設定都是相同的。
越來越多的叢集型別導致出現了越來越多的叢集,我們最初透過手動方式來調節每個叢集容量的方式,很快就變得崩潰了。為了解決這個問題,我們為每個叢集新增了 Kubernetes Cluster Autoscaler[3] 元件。該元件會基於pod requests來動態調節叢集的大小。如果一個叢集的容量被耗盡,則 Cluster Autoscaler 會新增一個新的節點來滿足pending狀態的pods。同樣,如果在一段時間內叢集的某些節點的利用率偏低,則Cluster Autoscaler會移除這些節點。這種方式非常適合我們的場景,為我們節省了大約5%的總的雲開銷,以及手動擴充套件叢集的運維開銷。
階段 3:異構叢集,自動擴縮容
當 Airbnb 的幾乎所有線上計算都轉移到 Kubernetes 時,叢集型別的數量已經增長到 30 多個了,叢集的數量也增加到了 100 多個。這種擴充套件使得 Kubernetes 叢集管理相當乏味。例如,在叢集升級時需要單獨對每種型別的叢集進行單獨測試。
在第三個階段,我們會透過建立異構叢集來整合我們的叢集型別,這些叢集可以透過單個 Kubernetes 控制平面來容納許多不同的工作負載。首先,這種方式極大降低了叢集管理的開銷,因為擁有更少、更通用的叢集會減少需要測試的配置數量。其次,現在大多數 Airbnb 的服務已經執行在了 Kubernetes 叢集上,每個叢集的效率可以為成本最佳化提供一個很大的槓桿。整合叢集型別允許我們在每個叢集中執行不同的工作負載。這種工作負載型別的聚合(有些大,有些小)可以帶來更好的封裝和效率,從而提高利用率。透過這種額外的工作負載靈活性,我們可以有更多的空間來實施複雜的擴充套件策略,而不是預設的 Cluster Autoscaler 擴充套件邏輯。具體來說就是我們計劃實現與 Airbnb 特定業務邏輯相關的擴縮容邏輯。
隨著對叢集的擴充套件和整合,我們實現了異構(每個叢集有多種例項型別),我們開始在擴充套件期間實現特定的業務邏輯,並且意識到有必要對擴縮容的行為進行某些變更。下一節將描述我們是如何修改 Cluster Autoscaler,使其變得更加靈活。
Cluster Autoscaler 的改進
自定義 gRPC 擴充套件器
我們對 Cluster Autoscaler 所做的最重要的改進是提供了一種新方法來確定要擴充套件的節點組。在內部,Cluster Autoscaler 會維護一系列對映到不同候選擴容物件的節點組,它會針對當前 Pending 狀態的 pods 執行模擬排程,然後過濾掉不滿足排程要求的節點組。如果存在 Pending 的 pods,Cluster Autoscaler 會嘗試透過擴充套件叢集來滿足這些 pods。所有滿足 pod 要求的節點組都會被傳遞給一個名為 Expander 的元件。
Expander 負責根據需求進一步過濾節點組。Cluster Autoscaler 有大量內建的擴充套件器選項,每個選型都有不同的處理邏輯。例如,預設是隨機擴充套件器,它會隨機選擇可用的節點組。另一個是 Airbnb 曾經使用過的 優先順序擴充套件器[4],它會根據使用者指定的分級優先順序列表來選擇需要擴充套件的節點組。
當我們使用異構叢集邏輯的同時,我們發現預設的擴充套件器無法在成本和例項型別選擇方面滿足我們複雜的業務需求。
假設,我們想要實現一個基於權重的優先順序擴充套件器。目前的優先順序擴充套件器僅允許使用者為節點組設定不同的等級,這意味著它會始終以確定的順序來擴充套件節點組。如果某個等級有多個節點組,則會隨機選擇一個節點組。基於權重的優先順序策略可以支援在同一個等級下設定兩個節點組,其中 80% 的時間會擴充套件一個節點組,另外 20% 的時間會擴充套件另一個節點組。但預設並不支援基於權重的擴充套件器。
除了當前支援的擴充套件器的某些限制外,還有一些操作上的問題:
Cluster Autoscaler 的釋出流水線比較嚴格,在合併到上游之前,需要花大量時間來稽核變更。但我們的業務邏輯和所需的擴充套件策略是在不斷變化的。能夠滿足當前需求的擴充套件器並不一定能夠滿足未來的需求。
我們的業務邏輯是與 Airbnb 關聯的,其他使用者則沒有這種業務邏輯。因此我們實現的特定邏輯並不一定對上游使用者有用。
所以我們對 Cluster Autoscaler 中的新擴充套件器型別提出了一些要求:
我們希望擴充套件器是可擴充套件的,能夠被其他使用者使用。其他使用者在使用預設的 Expanders 可能會遇到類似的限制,我們希望提供一個通用的解決方案,並回饋上游。
我們的解決方案應該能夠獨立於 Cluster Autoscaler 部署,這樣可以讓我們能夠響應快速變更的業務需求。
我們的解決方案應該能夠融入 Kubernetes Cluster Autoscaler 生態系統,這樣就無需一直維護一個 Cluster Autoscale 的分支。
鑑於這些需求,我們提出了一種設計,將擴充套件職責從 Cluster Autoscaler 的核心邏輯中分離出來。我們設計了一種可插拔的 自定義擴充套件器[5],它實現了gRPC客戶端(類似 custom cloud provider[6] ),該自定義擴充套件器分為兩個元件。
第一個元件是內建到 Cluster Autoscaler 中的 gRPC 客戶端,這個 Expander 與 Cluster Autoscaler 中的其他擴充套件器遵循相同的介面,負責將 Cluster Autoscaler 中的有效節點組資訊轉換為定義好的 protobuf 格式(見下文),並接收來自gRPC 服務端的輸出,將其轉換回 Cluster Autoscaler 要擴充套件的最終的可選列表。
第二個元件是 gRPC 服務端,這需要由使用者實現,該服務端作為一個獨立的應用或服務執行。透過客戶端傳遞的資訊以及複雜的擴充套件邏輯來選擇需要擴容的節點組。當前透過 gRPC 傳遞的 protobuf 訊息是 Cluster Autoscaler 中傳遞給 Expander 的內容的(略微)轉換版本。
在前面的例子中,可以非常容易地實現加權隨機優先順序擴充套件器,方法是讓伺服器從優先順序列表中讀取,並透過 confimap 讀取權重百分比,然後進行相應的選擇。
我們的實現還包含一個故障保護選項。建議使用該選項將 多個擴充套件器[7] 作為引數傳遞給 Cluster Autoscaler。使用該選擇後,如果服務端出現故障,Cluster Autoscaler 仍然能夠使用一個備用的擴充套件器進行擴充套件。
由於服務端作為一個獨立的應用執行,因此可以在 Cluster Autoscaler 外開發擴充套件邏輯,且 gRPC 服務端可以根據使用者需求實現自定義,因此這種方案對整個社群來說也非常有用。
在內部,從 2022 年開始,Airbnb 就一直在使用這種方案來擴縮容所有的叢集,期間一直沒有出現任何問題。它允許我們動態地選擇何時去擴充套件特定的節點組來滿足 Airbnb 的業務需求,從而實現了我們開發一個可擴充套件的自定義擴充套件器。
我們的自定義擴充套件器在今年早些時候被上游 Cluster Autoscaler 接受,並將在下一個版本 (v1.24.0) 版本中可以使用。
總結
在過去的四年裡,Airbnb 在我們的 Kubernetes 叢集配置中取得了長足的進步。透過在 Cluster Autoscaler 中開發和引入更加成熟的擴充套件器,我們已經能夠實現圍繞成本和多例項型別開發複雜的、特定業務的擴充套件策略目標,同時還向社群貢獻了一些有用的功能。
來自 “ 雲原生技術社群 ”, 原文作者:David Morrison;原文連結:https://mp.weixin.qq.com/s/O0O44CWTxSsWmpU8xdJVdw,如有侵權,請聯絡管理員刪除。
相關文章
- Redis—叢集擴縮容Redis
- hdfs叢集的擴容和縮容
- Openshif對叢集的擴容與縮容
- Redis Cluster 叢集搭建與擴容、縮容Redis
- ceph叢集的OSD管理基礎及OSD節點擴縮容
- kubernetes實踐之四十一:Pod自動擴容與縮容
- Kubernetes:應用自動擴容、收縮與穩定更新
- Kubernetes的垂直和水平擴縮容的效能評估
- 如何選擇Kubernetes叢集最佳的自動擴充套件策略? - Daniele套件
- 四 GBase 8a MPP Cluster叢集縮容
- 在 kubernetes 環境下如何優雅擴縮容 Pulsar
- 三 GBase 8a MPP Cluster叢集擴容
- 生產調優4 HDFS-叢集擴容及縮容(含伺服器間資料均衡)伺服器
- 基於Ubuntu部署企業級kubernetes叢集---k8s叢集容部署UbuntuK8S
- Redis大叢集擴容效能優化實踐Redis優化
- 【Kubernetes學習筆記】-kubeadm 手動搭建kubernetes 叢集筆記
- Redis大叢集擴容效能最佳化實踐Redis
- Kubernetes 叢集搭建(上)
- Kubernetes 叢集搭建(下)
- Kubernetes叢集搭建(vagrant)
- kubernetes與web叢集Web
- 拆除kubeadm部署的Kubernetes 叢集
- “開箱即用” 的 Kubernetes 叢集
- 用C實現動態擴容的string
- 非 LVM 分割槽動態擴容LVM
- 手動搭建高可用的 kubernetes 叢集(v1.31)
- 用Ansible 自動化搭建本地Kubernetes叢集
- Redis 叢集伸縮原理Redis
- 搭建 Kubernetes 高可用叢集
- kubernetes叢集管理命令(三)
- centos8-LVM捲動態擴容CentOSLVM
- 被vector動態擴容給坑了!
- V8R6叢集節點擴容步驟整理
- Mysql學習筆記---MySQL叢集架構之擴容方案MySql筆記架構
- kubernetes實踐之十五:Kubernetes叢集主要啟動引數說明
- minikube metrics-server HPA 自動擴縮容錯誤Server
- 使用 Kind 搭建你的本地 Kubernetes 叢集
- 使用BPF監視你的Kubernetes叢集