kubernetes之HPA詳細介紹


一.HPA說明

HPA(Horizontal Pod Autoscaler)是kubernetes的一種資源對象,能夠根據某些指標對在statefulset、replicacontroller、replicaset等集合中的pod數量進行動態伸縮,使運行在上面的服務對指標的變化有一定的自適應能力。
HPA目前支持四種類型的指標,分別是Resource、Object、External、Pods。其中在穩定版本autoscaling/v1只支持對CPU指標的動態伸縮,在測試版本autoscaling/v2beta2中支持memory和自定義指標的動態伸縮,並以annotation的方式工作在autoscaling/v1版本中。
注意:Pod的自動縮放不適用於無法縮放的對象。
HPA的API有三個版本:

[root@k8s001 ~]# kubectl api-versions | grep autoscal
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
  • autoscaling/v1:只支持基於CPU指標的縮放。
  • autoscaling/v2beta1:支持Resource Metrics(資源指標,如pod的CPU)和Custom Metrics(自定義指標)的縮放。
  • autoscaling/v2beta2:支持Resource Metrics(資源指標,如pod的CPU)和Custom Metrics(自定義指標)和ExternalMetrics(額外指標)的縮放。
    參考鏈接:https://v1-17.docs.kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/

二.度量指標詳細說明

下面,基於具體的示例進行說明:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  # HPA的伸縮對象描述,HPA會動態修改該對象的pod數量
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  # HPA的最小pod數量和最大pod數量
  minReplicas: 1
  maxReplicas: 10
  # 監控的指標數組,支持多種類型的指標共存
  metrics:
  # Object類型的指標
  - type: Object
    object:
      metric:
        # 指標名稱
        name: requests-per-second
      # 監控指標的對象描述,指標數據來源於該對象
      describedObject:
        apiVersion: networking.k8s.io/v1beta1
        kind: Ingress
        name: main-route
      # Value類型的目標值,Object類型的指標只支持Value和AverageValue類型的目標值
      target:
        type: Value
        value: 10k
  # Resource類型的指標
  - type: Resource
    resource:
      name: cpu
      # Utilization類型的目標值,Resource類型的指標只支持Utilization和AverageValue類型的目標值
      target:
        type: Utilization
        averageUtilization: 50
  # Pods類型的指標
  - type: Pods
    pods:
      metric:
        name: packets-per-second
      # AverageValue類型的目標值,Pods指標類型下只支持AverageValue類型的目標值
      target:
        type: AverageValue
        averageValue: 1k
  # External類型的指標
  - type: External
    external:
      metric:
        name: queue_messages_ready
        # 該字段與第三方的指標標簽相關聯
        selector:
          matchLabels:
            env: "stage"
            app: "myapp"
      # External指標類型下只支持Value和AverageValue類型的目標值
      target:
        type: AverageValue
        averageValue: 30
  • metrics中target字段:target總共有3種類型:Utilization、Value、AverageValue。
    • Utilization:表示平均使用率
    • Value:表示實際值
    • AverageValue:表示平均值
  • metrics中type字段:type字段總共有4種類型:Object、Pods、Resource、External。
    • Object:這里指的是指定kubernetes內部對象的指標,數據需要第三方adapter提供,只提供Value和AverageValue類型的目標值。
    • Pods:這里指的是伸縮對象(stagefulSet、replicaController、replicaSet)底下的Pods的指標,數據需要第三方的adapter提供,並且只運行AverageValue類型的目標值。
    • Resource:這里指的是當前伸縮對象下的pod的cpu和memory指標,只支持Utilization和AverageValue類型的目標值。
    • External:這里指的是kubernetes外部的指標,數據需要第三方的adapter提供,只支持Value和AverageValue類型的目標值。

三.HPA動態伸縮原理


HPA在kubernetes中也由一個controller控制,controller會間隔循環HPA,檢查每個HPA中監控的指標是否觸發伸縮條件,默認的間隔時間為15s。一旦觸發伸縮條件,controller會向kubernetes發送請求,修改伸縮對象(statefulSet、replicaController、replicaSet)子對象scale中控制pod數量的字段。kubernetess響應請求,修改scale結構體,然后會刷新一次伸縮對象的pod數量。伸縮對象被修改后,自然會通過list/watch機制增加或減少pod數量,達到動態伸縮的目的。

  • 對於每個pod的資源指標(如CPU),控制器從資源指標API中獲取每一個HorizontalPodAutoscaler指定的pod的指標,如果設置了目標使用率,控制器會獲取每個Pod中的容器資源使用情況,並計算資源使用率。如果使用原始值,將直接使用原始數據,進而計算出目標副本數。這里注意的是,如果Pod某些容器不支持資源采集,那么該控制器將不會使用該pod的CPU使用率。
  • 如果pod使用自定義指標,控制器機制與資源指標類型,區別在於自定義的指標只適用原始值,而不是利用率。
  • 如果pod使用的對象指標和外部指標(每個指標描述一個對象信息),這個指標將直接跟目標指標設定值相比較,並生成一個上述的縮放比例。在最新的autoscaling/v2beta2版本API中,這個指標也可以根據pod數量平分后再進行計算。通常情況,控制器從一系列的聚合API(metrics.k8s.io,custom.metrics.k8s.io和external.metrics.k8s.io)中獲取指標數據。metrics.k8s.io API通常由metrics-server(這里需要額外啟動)提供。

四.HPA伸縮流程

HPA的主要伸縮流程如下:
1)判斷當前Pod數量是否在HPA設定的Pod數量空間中,如果不在,過小返回最小值,過大返回最大值,結束伸縮。
2)判斷指標的類型,並向api server發送對應的請求,拿到設定的監控指標。一般來說指標會從下面系列聚合API中獲取(metrics.k8s.io,custom.metrics.k8s.io和external.metrics.k8s.io)。其中metrics.k8s.io一般由kubernetes自帶的metrics-server來提供,主要是cpu、memory使用率指標。另外兩種需要第三方的adapter來提供。custom.metrics.k8s.io提供的自定義指標數據,一般與kubernetes集群有關,比如跟特定的pod相關。external.metrics.k8s.io同樣提供自定義指標數據,但一般與kubernetes集群無關,許多知名的第三方監控平台提供了adapter實現上述api(如prometheus),可以將監控和adapter一同部署在kubenetes集群中提供服務。甚至能夠替換原來的metrics-server來提供上述三類api指標,達到深度定制監控數據的目標。
3)根據獲取的指標,使用相關的算法計算出一個伸縮系數,並乘以當前pod數量以獲得期望的pod數量。這里系數是指標的期望值與目前值的比值,如果大於1表示擴容,小於1表示縮容。指數數值有平均值(AverageValue)、平均使用率(Utilization)、裸值(Value)三種類型* * 每種類型的數值都有對應的算法。注意下面事項:如果系數有小數點,統一進一;系數如果未達到某個容忍值,HPA認為變化太小,會忽略這次變化,容忍值默認為0.1。

  • 這里HPA擴容算法比較保守,如果出現獲取不到指標的情況,擴容時算最小值,縮容時算最大值。如果需要計算平均值,出現pod沒准備好的情況,我們保守地假設尚未就緒的pods消耗了試題指標的0%,從而進一步降低了伸縮的幅度。
  • 一個HPA支持多個指標的監控,HPA會循環獲取所有的指標,並計算期望的pod數量,並從期望結果中獲得最大的pod數量作為最終的伸縮的pod數量。一個伸縮對象在k8s中允許對應多個HPA,但是只是k8s不會報錯而已,事實上HPA彼此不知道自己監控的是同一個伸縮對象,在這個伸縮對象中的pod會被多個HPA無意義地來回修改pod數量,給系統增加消耗,如果想要指定多個監控指標,可以如上述所說,在一個HPA中添加多個監控指標。
    4)檢查最終pod數量是否在HPA設定的pod數量范圍的區間,如果超過最大值或不足最小值都會修改為最大值或者最小值。然后會向kubernetes發出請求,修改伸縮對象的子對象scale的pod數量,結束一個HPA的檢查,獲取下一個HPA,完成一個伸縮流程。

五.HPA適用場景

HPA適用流量波動較大,機器資源緊張,服務數量多的業務場景。

六.部署測試

這里為了演示HPA,使用一個基於php-apache鏡像來定制Docker鏡像,Dockerfile內容如下:

cat Dockerfile.php
FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php

其中,index.php頁面執行一些CPU密集型計算

cat index.php
<?php
  $x = 0.0001;
  for ($i = 0; $i <= 1000000; $i++) {
    $x += sqrt($x);
  }
  echo "OK!";
?>

6.1 構建Docker

# 構建docker鏡像
docker build -t hpa-php:test -f Dockerfile.php .
# 保存docker鏡像成tar
docker save hpa-php:test -o php.tar
# 導入docker鏡像到各個節點
docker load -i php.tar

6.2 創建php的yaml文件

[root@k8s001 php]# cat php.yaml 
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: php
spec:
  selector:
    matchLabels:
      run: php
  replicas: 1
  template:
    metadata:
      labels:
        run: php
    spec:
      containers:
      - name: php
        image: hpa-php:test
        imagePullPolicy: IfNotPresent  
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 400m
          requests:
            cpu: 200m

---
apiVersion: v1
kind: Service
metadata:
  name: php
  labels:
    run: php
spec:
  ports:
  - port: 80
  selector:
    run: php
# 部署php服務
[root@k8s001 php]# kubectl apply -f php.yaml
# 查看php服務是否部署成功
[root@k8s001 php]# kubectl get pod 
NAME                                         READY   STATUS      RESTARTS   AGE
php-58b79cd964-gxcnc                         1/1     Running     0          56s

6.3 創建HPA

由上面可見,php服務正在運行。我們使用kubectl autoscale創建自動縮放器。實現對php的deployment創建的pod的自動擴縮容。下面的命令會創建一個HPA,HPA將會根據CPU資源指標進行增加或者減少副本數:

# 給deployment創建HPA
[root@k8s001 php]# kubectl autoscale deployment php --cpu-percent=50 --min=1 --max=10

說明:這里我們讓副本數維持到1-10個,所有的Pod的平均CPU使用率維持在50%(這里我們運行時pod請求的cpu為200m核,說明平均CPU使用為100m核)

# 查看HPA創建的詳情
[root@k8s001 php]# kubectl get hpa
NAME   REFERENCE        TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php    Deployment/php   0%/50%    1         10        1          29s

說明:這里由於我們沒有給服務器增加負載,CPU當前消耗為0(TARGET列顯示了由相應deployment控制的所有Pod的平均值)。

6.4 對php進行壓測

說明:這里是針對CPU進行壓測。

# 這里啟動一個容器,並將無限查詢循環發送php服務
kubectl run v1 -it --image=busybox /bin/sh
# 登錄到容器,執行以下操作
/ # while true; do wget -q -O- http://php.default.svc.cluster.local; done

等待一分鍾左右,我們查看HPA的負載情況:

[root@k8s001 php]# kubectl get hpa
NAME   REFERENCE        TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
php    Deployment/php   264%/50%   1         10        1          16m

上面可以看到,CPU消耗已經達到264%,每個pod的目標cpu使用率是50%,因此php這個deployment創建的pod副本數將調整為6個副本,為什么是6個副本,因為264/50=5.28

[root@k8s001 php]# kubectl get pod 
NAME                                         READY   STATUS      RESTARTS   AGE
php-58b79cd964-7p9nj                         1/1     Running     0          41s
php-58b79cd964-gxcnc                         1/1     Running     0          24m
php-58b79cd964-hcnnv                         1/1     Running     0          56s
php-58b79cd964-krmgd                         1/1     Running     0          56s
php-58b79cd964-pngqw                         1/1     Running     0          56s
php-58b79cd964-s86h5                         1/1     Running     0          41s
[root@k8s001 php]# kubectl get deployment php
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
php    6/6     6            6           25m

說明: 這里需要幾分鍾來穩定副本數。因為負載情況不同,因此最終副本數可能會有差異。

6.5 停止對php服務壓測,查看HPA是否會對php縮容

這里我們停止向php這個服務發送查詢請求,在busybox鏡像創建容器的終端中,通過Ctrl+C中斷while進程,幾分鍾后查看結果:

# 此時CPU利用率已經降到0,所以HPA將自動縮減副本數量至1。
[root@k8s001 php]# kubectl get hpa -w
NAME  REFERENCE        TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php   Deployment/php   0%/50%    1         10        6          25m
php   Deployment/php   0%/50%    1         10        6          25m
php   Deployment/php   0%/50%    1         10        3          26m
php   Deployment/php   0%/50%    1         10        3          26m
php   Deployment/php   0%/50%    1         10        1          27m
# 查看deployment數
[root@k8s001 php]# kubectl get deployment php
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
php    1/1     1            1           36m

注意:這里自動縮容需要幾分鍾。

同理,基於內存的縮容也可以參考此示例進行。這里我們就不進行演示說明了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM