深度解析阿里雲容器服務kubernetes彈性伸縮
前言
cluster-autoscaler
是Kubernetes中非常受大家關注的功能特性,可以通過 cluster-autoscaler
實現節點級別的動態新增與刪除,動態調整容器資源池,應對峰值流量。在Kubernetes中共有三種不同的彈性伸縮策略,分別是 HPA
(HorizontalPodAutoscaling)、 VPA
(VerticalPodAutoscaling)與 CA
(ClusterAutoscaler)。其中HPA和VPA主要擴縮容的物件是容器,而CA的擴縮容物件是節點。
深度解析Kubernetes彈性伸縮佈局
這張圖是阿里雲容器服務Kubernetes中支援的彈性伸縮的內容,主要包含兩條伸縮鏈路:
HPA
HPA(Horizontal Pod Autoscaler) 與 Heapster組成的基於Pod副本的彈性伸縮。HPA的伸縮是基於閾值和排程來實現的。首先在使用HPA前,一定要給需要進行彈性伸縮的負載(Deployment等等)新增資源的申請閾值,新增的方式如下,在spec中新增resource設定requests:
apiVersion: apps/v1beta2 kind: Deployment metadata: name: nginx-deployment-basic labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 resources: requests: cpu: 1 memory: 128Mi limits: cpu: 1 memory: 128Mi
此時這個Deployment就需要1核128Mi的資源,之所以必須要新增資源申請的原因是,彈性伸縮計算閾值後,判斷需要進行擴容,需要通過排程找到能夠符合條件的節點進行伸縮,如果沒有設定requests,那麼很有可能造成彈出來的容器利用率過高,依然無法降低整體的資源利用率,造成HPA無法生效。基於CPU的伸縮HPA Yaml如下:
apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: nginx-deployment-basic labels: app: nginx spec: scaleTargetRef: apiVersion: apps/v1beta2 kind: Deployment name: nginx-deployment-basic minReplicas: 1 maxReplicas: 10 targetCPUUtilizationPercentage: 70
CA(cluster-autoscaler)
cluster-autoscaler的排程和HPA的排程有所區別,他是節點級別的伸縮,可以和HPA結合使用,也可以基於排程單獨使用,CA和傳統的基於閾值的彈性伸縮有很大的區別,因為在kubernetes資源的排程是非常複雜的,常用的排程策略包括資源的判斷、親和性判斷、PDB的判斷等等,因此要確定一個Node是可排程的需要一個非常複雜的流程和過程。而這件事情對於彈性伸縮的場景就更為嚴峻,因為我們要在還沒有這個節點的前提下進行預判,確保伸縮出來的節點能夠緩解資源的壓力。對於有非常複雜的限制條件的負載而言,隨便新增一個節點大概率是無法進行排程的,這也就失去了彈性伸縮的意義。
此外,傳統的閾值判斷通常是累加節點上的資源利用率然後進行平均,確定叢集水位,但是對於kubernetes叢集而言,一個叢集中經常會有不同種類型的機器,可排程的資源也不盡相同,因此有可能造成叢集水位很低,但是對於資源無法排程的現象產生。
因此CA選擇了基於排程來實現擴容的方式,CA會在叢集出現無法排程的Pod的場景時進行擴容,在叢集中有節點資源申請值小於閾值的時候進行縮容。CA的擴容是基於ESS來實現的,一個CA可以支援多個ESS伸縮組,每個伸縮組有不同的伸縮配置,支援不同的機器規格,目前容器服務支援標準ECS(CPU based)、高效能運算ECS(GPU based)、競價例項(Spot Instance) 三種不同型別的ECS規格。 通過控制檯可以開啟彈性伸縮的支援 。
配置完成伸縮組後,此時如果出現無法排程的Pod,且排程策略滿足的情況下,即會從ESS的伸縮組中創建出新的節點並加入到叢集,完成伸縮排程。
CA(cluster-autoscaler)的高階用法
目前控制檯支援了CPU型別的ECS、GPU型別的ECS兩種,支援單可用區的伸縮。那麼對於期望使用更多複雜場景的開發者而言,如何滿足需求呢?
首先我們要來談一下容器服務的控制檯的彈性伸縮和CA(cluster-autoscaler)的關係,簡單的來講,控制檯是通過UI的頁面來配置CA(cluster-autoscaler)的,有高階需求的開發者可以通過手動配置來實現。首先我們先看下阿里雲容器服務kubernetes的CA(cluster-autoscaler)支援的能力。
支援能力 | 支援 |
---|---|
單可用區、多可用區支援 | ️ |
按量付費、競價例項 | ️️ |
ECS(cpu) ECS(gpu) ECS(spot instance) | ️️ |
自定義新增指令碼 | ️ ️ |
定時伸縮 | ️️ |
定向排程伸縮策略 | ️️ |
那麼如何上面提到的但是頁面尚未支援的功能呢。通過頁面可以幫助我們快速建立的ESS的分組以及相應的配置,並下發CA(cluster-autoscaler)的Yaml,我們可以在kube-system下看到cluster-autoscaler。
yaml.png
其中CA(cluster-autoscaler)識別ESS是通過伸縮組的ID來實現的,也就是說,我們可以通過修改這個伸縮組的配置來變更伸縮的行為。容器服務提供伸縮組的跳轉連結,可以快速的到達對應的伸縮組配置。
通過直接修改ESS中的伸縮配置,可以發揮Cluster-Autoscaler更強大的彈性伸縮能力。
- 對於多可用區的支援
由於可用區配置無法直接修改伸縮配置來實現,開發者可以定義新的伸縮組,並增加 --nodes
和相應的伸縮組id,重新部署autoscaler即可。需要特別注意的是,新建的伸縮組中UserData需要拷貝一個通過控制檯建立的伸縮組的UserData來實現。否則可能造成彈出的節點無法加入到叢集。
- 對於競價例項的多規格
可以通過修改伸縮組的配置來實現,需要特別注意的是,多規格一定要保證具有相同的CPU、Memory、GPU的數目,否則可能會造成節點彈出但無法排程。
- 自定義新增指令碼的支援
可以通過修改ESS中UserData來實現,特別注意的是UserData是base64的,通過控制檯建立的伸縮組已經包含了新增節點的部分,開發者自定義的部分可以增添到內容後面,並base64。
- 定時伸縮的支援
定時伸縮可以完全依賴ESS來實現,建立一個ESS的伸縮組,並建立定時的伸縮規則,最後需要需要拷貝一個通過控制檯建立的伸縮組的UserData來填寫當前伸縮組的UserData。注意,定時伸縮的伸縮組不需要新增到CA(cluster-autoscaler)的Yaml中。