天天看點

Kubernetes彈性伸縮全場景解讀(八) - 定時伸縮元件支援HPA相容

前言

在之前的

文章

中,我們介紹了

kubernetes-cronhpa-controller

是如何通過設定定時的方式觸發容器的水準副本伸縮,但是在實際的場景下,雖然定時伸縮對于負載有規律的應用比較友好,但是應用為了防止突發的流量沖擊,還是會配置HPA來做最後的保障的。那麼CronHPA與HPA之間該怎麼選擇呢?

定時伸縮元件相容HPA

在抉擇什麼時候需要CronHPA,什麼時候使用HPA的時候,我們在思考是否可以将CronHPA與HPA一起使用,如果一起使用會有什麼需要解決的問題呢?首先我們先看CronHPA的模闆定義

apiVersion: autoscaling.alibabacloud.com/v1beta1
kind: CronHorizontalPodAutoscaler
metadata:
  labels:
    controller-tools.k8s.io: "1.0"
  name: cronhpa-sample
spec:
   scaleTargetRef:
      apiVersion: apps/v1
      kind: Deployment
      name: nginx-deployment-basic
   jobs:
   - name: "scale-down"
     schedule: "30 */1 * * * *"
     targetSize: 1
   - name: "scale-up"
     schedule: "0 */1 * * * *"
     targetSize: 3           

在CronHPA中是通過

scaleTargetRef

字段來擷取伸縮對象的,并通過jobs的crontab規則定時伸縮執行個體的副本。

那麼我們再來看下HPA的模闆定義

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deployment-basic
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50           

HPA也是通過

scaleTargetRef

來定義伸縮的對象,并通過資源使用率來判斷伸縮的情況。如果同時設定CronHPA與HPA,那麼就會出現HPA與CronHPA同時操作一個

scaleTargetRef

的場景,而兩者之間又互相獨立無法感覺,這樣就會出現兩個controller各自工作,後執行的會覆寫先執行的結果。

Kubernetes彈性伸縮全場景解讀(八) - 定時伸縮元件支援HPA相容

這個問題的本質是兩個controller無法互相感覺,進而造成了異常,當回過頭來看這個問題的時候,其實我們可以發現HPA早期也有同樣的問題,開發者如果希望通過用兩個監控名額同時作用到HPA的時候,如果設定兩個HPA對象,會出現類似的問題,在解決這個問題的時候,是通過在HPA對象中定義metrics字段,将多個metrics合并到一個HPA對象中來實作的,例如:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deployment-basic
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 50           

當兩個metrics觸發彈性的個數不同的時候,會根據穩定性第一的原則,優先彈出更多的副本或者在縮容時保留更多的副本。那麼是否CronHPA和HPA也可以通過這個方案進行整合,答案是

Yes and No

。因為的确可以通過

alibaba-cloud-metrics-adapter

将定時的資料通過External Metrics的方式進行轉換,然後通過HPA中使用External Metrics的方式進行整合和比對。但是這樣會帶來的結果就是,我們需要通過HPA的結構去表達CronHPA的規則,然後再通過Metrics Adapter的模型去轉換時間資訊與副本計算。從模型上來看,這個方式看似相容了HPA,但是實際上對定時伸縮的可讀性、學習成本、出錯診斷、審計與離線都帶來了新的挑戰。

那麼是否還有其他的方法可以實作CronHPA與HPA的相容呢?我們将視角放回

scaleTargetRef

,還記得HPA是怎麼伸縮Deployment的Pod嗎,是HPA将Deployment配置在了

scaleTargetRef

的字段下,然後Deployment通過自身定義查找到了ReplicaSet,在通過ReplicaSet調整了真實的副本數目。

Kubernetes彈性伸縮全場景解讀(八) - 定時伸縮元件支援HPA相容

那麼從這個角度出發,我們有了一個大膽的想法,是否可以将

scaleTargetRef

設定為HPA對象,然後通過HPA對象來尋找真實的

scaleTargetRef

Kubernetes彈性伸縮全場景解讀(八) - 定時伸縮元件支援HPA相容
apiVersion: autoscaling.alibabacloud.com/v1beta1
kind: CronHorizontalPodAutoscaler
metadata:
  labels:
    controller-tools.k8s.io: "1.0"
  name: cronhpa-sample
spec:
   scaleTargetRef:
      apiVersion: autoscaling/v1
      kind: HorizontalPodAutoscaler
      name:  nginx-deployment-basic-hpa
   jobs:
   - name: "scale-down"
     schedule: "30 */1 * * * *"
     targetSize: 1
     runOnce: true
   - name: "scale-up"
     schedule: "0 */1 * * * *"
     targetSize: 3
     runOnce: true           

這樣設計的好處是,首先CronHPA可以感覺HPA目前的狀态,明确的知曉HPA的min、max、desired的數值,同時也知道HPA

scaleTargetRef

所對應的目前replicas。那麼本着穩定性原則,我們要如何操控HPA呢?

hpa(min/max) cronhpa deployment result 場景
1/10 5 hpa(1/10) deployment 5 定時和目前一緻,無需變更
4 目前高于定時,保留目前副本
6 hpa(6/10) deployment 6

定時高于目前,保留定時副本

定時高于HPA下限,修改HPA下限

5/10 hpa(4/10) deployment 5

定時低于目前,保留目前副本

定時低于HPA下限,修改HPA下限

11 hpa(11/11) deployment 11 定時高于HPA上限,修改HPA上限

如上圖是以,CronHPA會通過調整HPA的方式進行感覺,CronHPA要達到的副本和目前副本取大值,來判斷是否要擴容以及修改HPA的上限。CronHPA要達到的副本和HPA的配置取小值,判斷是否要修改HPA的下限。簡單而言,CronHPA不會直接調整Deployment的副本數目,而是通過HPA來操作Deployment,這樣就可以避免HPA和CronHPA的沖突問題了。

最後

定時伸縮CronHPA和HPA都是線上業務場景下非常重要的功能,不論使用何種的相容與适配的方式,穩定性第一的原則是不能改變的,開發者如果對CronHPA感興趣,歡迎

送出PR