1. 程式人生 > >Horizontal Pod Autoscaler(Pod水平自動伸縮)

Horizontal Pod Autoscaler(Pod水平自動伸縮)

Horizontal Pod Autoscaler 根據觀察到的CPU利用率(或在支援自定義指標的情況下,根據其他一些應用程式提供的指標)自動伸縮 replication controller, deployment, replica set, stateful set 中的pod數量。注意,Horizontal Pod Autoscaling不適用於無法伸縮的物件,例如DaemonSets。

Horizontal Pod Autoscaler 被實現作為Kubernetes API資源和控制器。該資源決定控制器的行為。控制器會定期調整副本控制器或部署中副本的數量,以使觀察到的平均CPU利用率與使用者指定的目標相匹配。

1. Horizontal Pod Autoscaler 是如何工作的

Horizontal Pod Autoscaler 實現為一個控制迴圈,其週期由--horizontal-pod-autoscaler-sync-period選項指定(預設15秒)。

在每個週期內,controller manager都會根據每個HorizontalPodAutoscaler定義的指定的指標去查詢資源利用率。 controller manager從資源指標API(針對每個pod資源指標)或自定義指標API(針對所有其他指標)獲取指標。

對於每個Pod資源指標(比如:CPU),控制器會從資源指標API中獲取相應的指標。然後,如果設定了目標利用率值,則控制器計算利用率值作為容器上等效的資源請求百分比。如果設定了目標原始值,則直接使用原始指標值。然後,控制器將所有目標容器的利用率或原始值(取決於指定的目標型別)取平均值,併產生一個用於縮放所需副本數量的比率。

如果某些Pod的容器未設定相關資源請求,則不會定義Pod的CPU使用率,並且自動縮放器不會對該指標採取任何措施。

2. 演算法細節

desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]

直譯為:(當前指標值 ➗ 期望指標值) ✖️ 當前副本數 ,結果再向上取整,最終結果就是期望的副本數量

例如,假設當前指標值是200m ,期望指標值是100m,期望的副本數量就是雙倍。因為,200.0 / 100.0 == 2.0 

如果當前值是50m,則根據50.0 / 100.0 == 0.5,那麼最終的副本數量就是當前副本數量的一半

如果該比率足夠接近1.0,則會跳過伸縮

當targetAverageValue或者targetAverageUtilization被指定的時候,currentMetricValue取HorizontalPodAutoscaler伸縮目標中所有Pod的給定指標的平均值。

所有失敗的和標記刪除的Pod將被丟棄,即不參與指標計算

當基於CPU利用率來進行伸縮時,如果有尚未準備好的Pod(即它仍在初始化),那麼該Pod將被放置到一邊,即將被保留。

kubectl 也支援Horizontal Pod Autoscaler

# 檢視autoscalers列表
kubectl get hpa
# 檢視具體描述
kubectl describe hpa
# 刪除autoscaler
kubectl delete hpa

# 示例:以下命名將會為副本集foo建立一個autoscaler,並設定目標CPU利用率為80%,副本數在2~5之間
kubectl autoscale rs foo --min=2 --max=5 --cpu-percent=80

3. 演示

Horizontal Pod Autoscaler automatically scales the number of pods in a replication controller, deployment, replica set or stateful set based on observed CPU utilization.

建立Dockerfile,並構建映象

FROM java:8
COPY ./hello-world-0.0.1-SNAPSHOT.jar hello-world.jar 
CMD java -jar hello-world.jar 

在hello-world.jar中執行一些CPU密集型計算

執行映象並暴露為服務

kubectl run hello-world-example \
     --image=registry.cn-hangzhou.aliyuncs.com/chengjs/hello-world:2.0 \
     --requests='cpu=200m' \
     --limits='cpu=500m' \
     --expose \
     --port=80 \
     --generator=run-pod/v1 

建立 Horizontal Pod Autoscaler

HPA將增加和減少副本數量,以將所有Pod的平均CPU利用率維持在50% 

kubectl autoscale deployment hello-world-example --cpu-percent=50 --min=1 --max=10 

檢查autoscaler的當前狀態

kubectl get hpa 

增加負載

接下來,利用壓測工具持續請求,以增加負載,再檢視

kubectl get deployment hello-world-example

通過使用autoscaling/v2beta2版本,你可以定義更多的指標 

首先,以autoscaling/v2beta2格式獲取HorizontalPodAutoscaler的YAML

kubectl get hpa.v2beta2.autoscaling -o yaml > /tmp/hpa-v2.yaml

在編輯器中開啟/tmp/hpa-v2.yaml檔案,接下來對其進行修改

第一個可以替換的指標型別是Pod指標。這些指標在各個容器中平均在一起,並且和目標值進行比較,已確定副本數。例如:

type: Pods
pods:
  metric:
    name: packets-per-second
  target:
    type: AverageValue
    averageValue: 1k 

第二個可以替換的指標型別是物件指標。顧名思義,它描述的是Object,而不是Pod。例如:

type: Object
object:
   metric:
      name: requests-per-second
   describedObject:
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      name: main-route
   target:
      type: Value
      value: 2k 

修改後完整的/tmp/hpa-v2.yaml檔案如下:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
  metadata:
    name:hello-world-example
    namespace:default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: hello-world-example
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
  - type: Pods
    pods:
      metric:
        name: packets-per-second
      target:
        type: AverageValue
        averageValue: 1k
  - type: Object
    object:
      metric:
        name: requests-per-second
      describedObject:
        apiVersion: networking.k8s.io/v1beta1
        kind: Ingress
        name: main-route
      target:
        type: Value
        value: 10k
status:
  observedGeneration: 1
  lastScaleTime: <some-time>
  currentReplicas: 1
  desiredReplicas: 1
  currentMetrics:
  - type: Resource
    resource:
      name: cpu
    current:
      averageUtilization: 0
      averageValue: 0
  - type: Object
    object:
      metric:
        name: requests-per-second
      describedObject:
        apiVersion: networking.k8s.io/v1beta1
        kind: Ingress
        name: main-route
      current:
        value: 10k

4. Docs

https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/

https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands&n