通過 Windows 命令提示符(cmd)在桌面新建文件夾,并在該文件夾中編譯、運(yùn)行一段 Java 程序段
808
2025-03-31
背景信息
基于業(yè)務(wù)團(tuán)隊(duì)(Cloud BU 應(yīng)用平臺)在開發(fā)Serverless引擎框架的過程中完成的K8s Cluster Autoscaler華為云插件。 目前該插件已經(jīng)貢獻(xiàn)給了K8s開源社區(qū),見下圖:
本文將會涉及到下述內(nèi)容:
對K8s Cluster Autoscaler模塊的架構(gòu)和代碼的Deep Dive,尤其是核心功能點(diǎn)的所涉及的算法的介紹。
K8s Cluster Autoscaler 華為云插件模塊的介紹。
什么是K8s Cluster Autoscaler (CA)?
什么是彈性伸縮?
顧名思義是根據(jù)用戶的業(yè)務(wù)需求和策略,自動調(diào)整其彈性計(jì)算資源的管理服務(wù),其優(yōu)勢有:
從應(yīng)用開發(fā)者的角度:能夠讓應(yīng)用程序開發(fā)者專注實(shí)現(xiàn)業(yè)務(wù)功能,無需過多考慮系統(tǒng)層資源
從系統(tǒng)運(yùn)維者的角度:極大的降低運(yùn)維負(fù)擔(dān), 如果系統(tǒng)設(shè)計(jì)合理可以實(shí)現(xiàn)“零運(yùn)維”
是實(shí)現(xiàn)Serverless架構(gòu)的基石,也是Serverless的主要特性之一
在具體解釋CA概念之前,咋們先從宏觀上了解一下K8s所支持的幾種彈性伸縮方式(CA只是其中的一種)。
VPA (Vertical Pod Autoscaler)
A set of components that automatically adjust the amount of CPU and memory requested by Pods running in the Kubernetes Cluster. Current state - beta.
簡而言之:?對于某一個(gè)POD,對其進(jìn)行擴(kuò)縮容(由于使用場景不多,不做過多介紹)
HPA(Horizontal Pod Autoscaler)?- 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, 根據(jù)預(yù)先設(shè)置的伸縮策略(如CPU, Memory使用率某設(shè)定的閥值),增加/刪減其中的Pods。
HPA伸縮策略:
HPA依賴metrics-server組件收集Pod上metrics, 然后根據(jù)預(yù)先設(shè)定的伸縮策略(如:CPU使用率大于50%),來決定擴(kuò)縮容Pods。計(jì)算CPU/Memory使用率時(shí),是取所有Pods的平均值。關(guān)于具體如何計(jì)算的,點(diǎn)擊此處有詳細(xì)算法介紹。
注:metrics-server默認(rèn)只支持基于cpu和memory監(jiān)控指標(biāo)伸縮策略
HPA架構(gòu)圖:
圖中下半部門Prometheus監(jiān)控系統(tǒng)和K8s Prometheus Adapter組件的引入是為了能夠使用自定義的metrics來設(shè)置伸縮策略,由于不是本文的重點(diǎn),這里不做過多介紹,?K8s官方文檔有個(gè)Walkthrough案例一步一步在實(shí)操中掌握和理解該模塊。如果用戶只需要依據(jù)cpu/memory的監(jiān)控指標(biāo)來設(shè)置伸縮策略,只要deploy默認(rèn)的metrics-server組件(其安裝對K8s來說就是一次deployment,非常方便, 上面的鏈接里有安裝步驟)
CA (Cluster Autoscaler)- Node級別伸縮
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,達(dá)到集群擴(kuò)縮容的目的。
Kubernetes(K8s) Cluster Autoscaler(CA)模塊源碼解析:
前面做了這么多鋪墊,是時(shí)候切入本文主題了。下面我將主要從架構(gòu)和代碼兩個(gè)維度來揭開CA模塊的神秘面紗,并配合FAQ的形式解答常見的問題。
CA整體架構(gòu)及所含子模塊
如上圖所示, CA模塊包含以下幾個(gè)子模塊,?詳見K8S CA模塊在Github的源碼:
autoscaler: 核心模塊,包含核心Scale Up和Scale Down功能(對應(yīng)Github里?core?Package)。
在擴(kuò)容時(shí)候:其ScaleUp函數(shù)會調(diào)用estimator模塊來評估所需節(jié)點(diǎn)數(shù)
在縮容時(shí):其ScaleDown函數(shù)會調(diào)用simulator模塊來評估縮容的節(jié)點(diǎn)數(shù)
estimator: 負(fù)責(zé)計(jì)算擴(kuò)容需要多少Node (對應(yīng)Github里?estimator?Package)
simulator: 負(fù)責(zé)模擬調(diào)度,計(jì)算縮容節(jié)點(diǎn) (對應(yīng)Github里?simulator?Package)
expander: 負(fù)責(zé)擴(kuò)容時(shí),選擇合適的Node的算法 (對應(yīng)Github里?expander?Package),可以增加或定制化自己的算法
cloudprovider: CA模塊提供給具體云提供商的接口 (對應(yīng)Github里cloudprovider?Package)。關(guān)于這個(gè)子模塊后面也會著重介紹,也是我們?nèi)A為云cloudprovider的擴(kuò)展點(diǎn)。
autoscaler通過該模塊與具體云提供商對接(如上圖右下角方框所示 AWS, GCE等云提供商),并可以調(diào)度每個(gè)云提供商提供的Node.
cloudprovider預(yù)先設(shè)定了一些列接口,供具體的云提供商實(shí)現(xiàn),來完成調(diào)度其提供的Node的目的
通過對K8s CA模塊的架構(gòu)和源碼的織結(jié)構(gòu)的介紹,我總結(jié)有以下幾點(diǎn)最佳實(shí)踐值得學(xué)習(xí)和借鑒, 可以適用在任何編程語言上:
SOLID設(shè)計(jì)原則無處不在,具體反映在:
每個(gè)子模塊僅負(fù)責(zé)解決某一特定問題 - 單一職責(zé)
每個(gè)子模塊都預(yù)留有擴(kuò)展點(diǎn) - 開閉原則
每個(gè)子模塊的接口隔離做的很清晰 - 接口分離原則
…
清晰的子模塊包的組織結(jié)構(gòu)
插件式的擴(kuò)展點(diǎn)設(shè)計(jì)
關(guān)于CA模塊的用戶常見問題
CA和k8s其他彈性伸縮方式的關(guān)系?
VPA更新已經(jīng)存在的Pod使用的resources
HPA更新已經(jīng)存在的Pod副本數(shù)
如果沒有足夠的節(jié)點(diǎn)在可伸縮性事件后運(yùn)行POD,則CA會擴(kuò)容新的Node到集群中,之前處于Pending狀態(tài)的Pods將會被調(diào)度到被新管理的node上
CA何時(shí)調(diào)整K8S集群大小?
何時(shí)擴(kuò)容: 當(dāng)資源不足,Pod調(diào)度失敗,即存在一直處于Pending狀態(tài)的Pod(見下頁流程圖), 從Cloud Provider處添加NODE到集群中
何時(shí)縮容: Node的資源利用率較低,且Node上存在Pod都能被重新調(diào)度到其它Node上去
CA多久檢查一次Pods的狀態(tài)?
CA每隔10s檢查是否有處于pending狀態(tài)的Pods
如何控制某些Node不被CA在縮容時(shí)刪除?
Node上有Pod被PodDisruptionBudget控制器限制。PodDisruptionBudgetSpec
Node上有命名空間是kube-system的Pods。
Node上Pod被Evict之后無處安放,即沒有其他合適的Node能調(diào)度這個(gè)pod
Node有annotation: “cluster-autoscaler.kubernetes.io/scale-down-disabled”: “true”
Node上存有如下annotation的Pod:“cluster-autoscaler.kubernetes.io/safe-to-evict”: “false”.點(diǎn)擊見詳情
若想更進(jìn)一步了解和學(xué)習(xí),請點(diǎn)擊這里查看更完整的常見問題列表及解答。
CA模塊源碼解析
由于篇幅關(guān)系,只對核心子模塊深入介紹,通過結(jié)合核心子模塊與其他子模塊之間如何協(xié)調(diào)和合作的方式順帶介紹一下其他的子模塊。
程序啟動入口處:?kubernetes/autoscaler/cluster-autoscaler/main.go
如上圖所示,autoscaler.go是接口,其默認(rèn)的實(shí)現(xiàn)是static_autoscaler.go, 該實(shí)現(xiàn)會分別調(diào)用scale_down.go和scale_up.go里的ScaleDown以及ScaleUp函數(shù)來完成擴(kuò)縮容。
那么問題來了,合適ScaleUp和ScaleDown方法會被調(diào)用呢,咋們按照順序一步一步來捋一下, 回到CA整體入口,那里有一個(gè)RunOnce(在autoscaler接口的默認(rèn)實(shí)現(xiàn)static_autoscaler.go里)方法,會啟動一個(gè)Loop 一直運(yùn)行l(wèi)isten和watch系統(tǒng)里面是否有那些處于pending狀態(tài)的Pods(i.e. 需要協(xié)助找到Node的Pods), 如下面代碼片段(static_autoscaler.go里的RunOnce函數(shù))所示, 值得注意的是,在實(shí)際調(diào)用ScaleUp之前會有幾個(gè) if/else 判斷是否符合特定的條件:
對于ScaleDown函數(shù)的調(diào)用,同理,也在RunOnce函數(shù)里, ScaleDown主要邏輯是遵循如下幾步:
找出潛在的利用率低的Nodes (即代碼里的scaleDownCandidates數(shù)組變量)
然后為Nodes里的Pods找到“下家”(即可以被安放的Nodes,對應(yīng)代碼里的podDestinations數(shù)組變量)
然后就是下面截圖所示,幾個(gè)if/else判斷符合ScaleDown條件,就執(zhí)行TryToScaleDown函數(shù)
通過上面的介紹結(jié)合代碼片段,我們了解到何時(shí)ScaleUp/ScaleDown函數(shù)會被調(diào)用。接下來,我們來看看當(dāng)這兩個(gè)核心函數(shù)被調(diào)用時(shí),里面具體都發(fā)生了什么。
先來看一下ScaleUp:
從上圖代碼片段,以及我里面標(biāo)注的注釋,可以看到,這里發(fā)生了下面幾件事:
通過cloudprovider子模塊(下面專門介紹這個(gè)子模塊)從具體云提供商處獲取可以進(jìn)行擴(kuò)容的的NodeGroups
把那些Unschedulable Pods按照擴(kuò)容需求進(jìn)行分組(對應(yīng)上面代碼里的對buildPodEquivalenceGroups函數(shù)的調(diào)用)
把第1步得到的所有可用的NodeGroups和第2步得到的待分配的Pods, 作為輸入,送入給estimator子模塊的裝箱算法(該調(diào)用發(fā)生對上圖中computeExpansionOption函數(shù)調(diào)用內(nèi)部)?,得到一些候選的Pods調(diào)度/分配方案。由于estimator子模塊的核心就是裝箱算法,下圖就是實(shí)現(xiàn)了裝箱算法的Estimate函數(shù),這里實(shí)現(xiàn)有個(gè)小技巧,就是算法開始之前,先調(diào)用calculatePodScore把兩維問題降為一維問題(即Pod對CPU和Memory的需求),然后就是傳統(tǒng)的裝箱算法,兩個(gè)for loop來給 Pods找到合適的Node. 至于具體如何降維的,詳見binpacking.estimator.go里的calculatePodScore函數(shù)源碼。
把第3步得到的一些方案,送入給?expander子模塊,得到最優(yōu)的分配方案(對應(yīng)代碼片段中ExpanderStrategy.BestOption的函數(shù)調(diào)用)expander提供了下面截圖中的集中策略,用戶可以通過實(shí)現(xiàn)expander接口的BestOption函數(shù),來實(shí)現(xiàn)自己的expander策略
與具體的云提供商(i.e. AWS, GCP, Azure, Huawei Cloud)對接來對對應(yīng)云平臺上的Node Group(有的云平臺叫Node Pool)里的Node進(jìn)行增刪操作已達(dá)到擴(kuò)縮容的目的。其代碼對應(yīng)于與之同名的cloudprovider package。詳見Github代碼。 沒個(gè)云提供商,都需要按照k8s約定的方式進(jìn)行擴(kuò)展,開發(fā)自家的cloudprovider插件,如下圖:
下文會專門介紹華為云如何擴(kuò)展該模塊的
華為云cloudprovider插件開發(fā)及開源貢獻(xiàn)心得
華為云cloudprovider插件如何擴(kuò)展和開發(fā)的?
下圖是華為cloudprovider插件的大致的代碼結(jié)構(gòu), 綠色框里是SDK實(shí)際是對CCE(云容器引擎 CCE)?進(jìn)行必要操作所需要的 (對Node Pool/Group里的Node 進(jìn)行增加和刪除)。 按理說我們不需要自己寫這一部分,不過由于咋們云CCE 團(tuán)隊(duì)的SDK實(shí)在是不完善,所以我們開發(fā)了一些必要的對CCE進(jìn)行操作的SDK。重點(diǎn)是紅色框中的代碼:
huaweicloud_cloud_provider.go是入口處,其負(fù)責(zé)總huaweicloud_cloud_config.go讀取配置,并實(shí)例化huaweicloud_manager.go對象。huaweicloud_manager.go對象里通過調(diào)用藍(lán)色框部門里的CCE SDK來獲取CCE整體的信息。 CCE整體的信息被獲取到后,可以調(diào)用huaweicloud_node_group.go 來完成對該CCE綁定的Node Group/Pool進(jìn)行Node的擴(kuò)縮容已達(dá)到對整體CCE的Node伸縮。
如何從開源社區(qū)獲取所需資源及開源過程中需要注意的點(diǎn)?
我剛開始接受該項(xiàng)目的時(shí)候,一頭霧水,不知道該如何下手。K8s關(guān)于這一塊的文檔寫的又不是很清楚。以往的經(jīng)驗(yàn)以及K8s Github README中提供的信息,我加入他們的Slack組織,找到相應(yīng)的興趣組channel( 對應(yīng)我的情況就是sig-autoscaling channel),提出了我的問題(如下面截圖)。 基于K8s代碼倉的大小,如果沒找到合適的擴(kuò)展點(diǎn),幾乎無法改動和擴(kuò)展的。
劃重點(diǎn): 現(xiàn)在幾乎所有的開源組中都有Slack群組,加入找到相應(yīng)的興趣組,里面大牛很多,提出問題,一般會有人熱心解答的。 郵件列表也可以,不過我認(rèn)為Slack高效實(shí)時(shí)一點(diǎn),強(qiáng)烈推薦。對于我本人平常接觸到的開源項(xiàng)目,我一般都會加入到其 Slack中,有問題隨時(shí)提問。 當(dāng)然,中國貢獻(xiàn)的開源項(xiàng)目,好多以微信群的方式溝通 :)譬如咋們?nèi)A為開源出去的微服務(wù)框架項(xiàng)目 ServiceComb,我也有加微信群。總之, 對于開源項(xiàng)目,一定要找到高效的和組織溝通的方式。
另外,對于貢獻(xiàn)代碼過程中,如果使用到了三方開源代碼,由于版權(quán)和二次分發(fā)的問題,盡量避免直接包含三方源代碼, 如果實(shí)在需要,可以對其進(jìn)行擴(kuò)展,并在新擴(kuò)展的文件附上華為的版權(quán)信息與免責(zé)聲明。 關(guān)于公司的具體要求和政策請參閱文件:?對外開源代碼出口自檢標(biāo)準(zhǔn)與指導(dǎo)書?以及?對外開源流程指導(dǎo)
Kubernetes 華為開源鏡像站 Mirrors 云原生 GitHub
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。