基於業務團隊(Cloud BU 應用平臺)在開發Serverless引擎框架的過程中完成的K8s Cluster Autoscaler華爲雲插件。 目前該插件已經貢獻給了K8s開源社區,見下圖:
本文將會涉及到下述內容:
直入主題,這裏不再贅述K8s的基本概念。
什麼是彈性伸縮?
顧名思義是根據用戶的業務需求和策略,自動調整其彈性計算資源的管理服務,其優勢有:
在具體解釋CA概念之前,咋們先從宏觀上了解一下K8s所支持的幾種彈性伸縮方式(CA只是其中的一種)。
K8s支持的幾種彈性伸縮方式:
注: 爲了描述精確性,介紹下面幾個關鍵概念時,先引用K8S官方解釋鎮一下場 :)。"簡而言之"部分爲作者本人的解讀。
A set of components that automatically adjust the amount of CPU and memory requested by Pods running in the Kubernetes Cluster. Current state - beta.
簡而言之: 對於某一個POD,對其進行擴縮容(由於使用場景不多,不做過多介紹)
A component that scales the number of pods in a replication controller, deployment, replica set or stateful set based on observed CPU utilization (or, with beta support, on some other, application-provided metrics).
簡而言之: 對於某一Node, 根據預先設置的伸縮策略(如CPU, Memory使用率某設定的閥值),增加/刪減其中的Pods。
A component that automatically adjusts the size of a Kubernetes Cluster so that: all pods have a place to run and there are no unneeded nodes.
簡而言之: 對於K8S集羣,增加/刪除其中的Nodes,達到集羣擴縮容的目的。
前面做了這麼多鋪墊,是時候切入本文主題了。下面我將主要從架構和代碼兩個維度來揭開CA模塊的神祕面紗,並配合FAQ的形式解答常見的問題。
CA整體架構及所含子模塊
如上圖所示, CA模塊包含以下幾個子模塊, 詳見K8S CA模塊在Github的源碼:
通過對K8s CA模塊的架構和源碼的織結構的介紹,我總結有以下幾點最佳實踐值得學習和借鑑, 可以適用在任何編程語言上:
若想更進一步瞭解和學習,請點擊這裏查看更完整的常見問題列表及解答。
由於篇幅關係,只對核心子模塊深入介紹,通過結合核心子模塊與其他子模塊之間如何協調和合作的方式順帶介紹一下其他的子模塊。
CA模塊整體入口處
程序啓動入口處: kubernetes/autoscaler/cluster-autoscaler/main.go
CA的autoscaler子模塊
如上圖所示,autoscaler.go是接口,其默認的實現是static_autoscaler.go, 該實現會分別調用scale_down.go和scale_up.go裏的ScaleDown以及ScaleUp函數來完成擴縮容。
那麼問題來了,合適ScaleUp和ScaleDown方法會被調用呢,咋們按照順序一步一步來捋一下, 回到CA整體入口,那裏有一個RunOnce(在autoscaler接口的默認實現static_autoscaler.go裏)方法,會啓動一個Loop 一直運行listen和watch系統裏面是否有那些處於pending狀態的Pods(i.e. 需要協助找到Node的Pods), 如下面代碼片段(static_autoscaler.go裏的RunOnce函數)所示, 值得注意的是,在實際調用ScaleUp之前會有幾個 if/else 判斷是否符合特定的條件:
對於ScaleDown函數的調用,同理,也在RunOnce函數裏, ScaleDown主要邏輯是遵循如下幾步:
通過上面的介紹結合代碼片段,我們瞭解到何時ScaleUp/ScaleDown函數會被調用。接下來,我們來看看當這兩個核心函數被調用時,裏面具體都發生了什麼。
先來看一下ScaleUp:
從上圖代碼片段,以及我裏面標註的註釋,可以看到,這裏發生了下面幾件事:
CA的cloudprovider子模塊
與具體的雲提供商(i.e. AWS, GCP, Azure, Huawei Cloud)對接來對對應雲平臺上的Node Group(有的雲平臺叫Node Pool)裏的Node進行增刪操作已達到擴縮容的目的。其代碼對應於與之同名的cloudprovider package。詳見Github代碼。 沒個雲提供商,都需要按照k8s約定的方式進行擴展,開發自家的cloudprovider插件,如下圖:
下文會專門介紹華爲雲如何擴展該模塊的
下圖是華爲cloudprovider插件的大致的代碼結構, 綠色框裏是SDK實際是對CCE(雲容器引擎 CCE) 進行必要操作所需要的 (對Node Pool/Group裏的Node 進行增加和刪除)。 按理說我們不需要自己寫這一部分,不過由於咋們雲CCE 團隊的SDK實在是不完善,所以我們開發了一些必要的對CCE進行操作的SDK。重點是紅色框中的代碼:
huaweicloud_cloud_provider.go是入口處,其負責總huaweicloud_cloud_config.go讀取配置,並實例化huaweicloud_manager.go對象。huaweicloud_manager.go對象裏通過調用藍色框部門裏的CCE SDK來獲取CCE整體的信息。 CCE整體的信息被獲取到後,可以調用huaweicloud_node_group.go 來完成對該CCE綁定的Node Group/Pool進行Node的擴縮容已達到對整體CCE的Node伸縮。
我剛開始接受該項目的時候,一頭霧水,不知道該如何下手。K8s關於這一塊的文檔寫的又不是很清楚。以往的經驗以及K8s Github README中提供的信息,我加入他們的Slack組織,找到相應的興趣組channel( 對應我的情況就是sig-autoscaling channel),提出了我的問題(如下面截圖)。 基於K8s代碼倉的大小,如果沒找到合適的擴展點,幾乎無法改動和擴展的。
劃重點: 現在幾乎所有的開源組中都有Slack羣組,加入找到相應的興趣組,裏面大牛很多,提出問題,一般會有人熱心解答的。 郵件列表也可以,不過我認爲Slack高效實時一點,強烈推薦。對於我本人平常接觸到的開源項目,我一般都會加入到其 Slack中,有問題隨時提問。 當然,中國貢獻的開源項目,好多以微信羣的方式溝通 :)譬如咋們華爲開源出去的微服務框架項目 ServiceComb,我也有加微信羣。總之, 對於開源項目,一定要找到高效的和組織溝通的方式。
另外,對於貢獻代碼過程中,如果使用到了三方開源代碼,由於版權和二次分發的問題,儘量避免直接包含三方源代碼, 如果實在需要,可以對其進行擴展,並在新擴展的文件附上華爲的版權信息與免責聲明。 關於公司的具體要求和政策請參閱文件: 對外開源代碼出口自檢標準與指導書 以及 對外開源流程指導