k8s (二十一) --- kubernetes HPA簡介及實例

一、HPA簡介

Horizontal Pod Autoscaler 可以根據CPU利用率自動伸縮 replication controller、deployment 或者 replica set 中的Pod數量 (也可以基於其他應用程序提供的度量指標,目前這一功能處於 beta 版本)。

官方文檔:https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/

本文示例需要一個1.2或者更高版本的可運行的 Kubernetes 集羣以及 kubectl。 metrics-server 也需要部署到集羣中, 它可以通過 resource metrics API 對外提供度量數據,Horizontal Pod Autoscaler 正是根據此 API 來獲取度量數據,部署方法請參考 https://blog.csdn.net/qq_35887546/article/details/106016712

二、HPA實例

第一步:運行 php-apache 服務器並暴露服務

爲了演示 Horizontal Pod Autoscaler,我們將使用一個基於 php-apache 鏡像的定製 Docker 鏡像。 Dockerfile 內容如下:

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

它定義一個 index.php 頁面來執行一些 CPU 密集型計算:

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

首先,我們先啓動一個 deployment 來運行這個鏡像並暴露一個服務:

[root@server1 hpa]# vim php-apache.yaml 
[root@server1 hpa]# cat php-apache.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: hpa-example
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m

---

apiVersion: v1
kind: Service
metadata:
  name: php-apache
  labels:
    run: php-apache
spec:
  ports:
  - port: 80
  selector:
    run: php-apache

其中需要的鏡像hpa-example可以在docker hub拉取,先在運行這個部署文件:

[root@server1 hpa]# kubectl apply -f php-apache.yaml 
deployment.apps/php-apache created
service/php-apache created

查看狀態,可以看出該部署文件創建了一個由deployment控制器維護的pod,以及一個service:

[root@server1 hpa]# kubectl get all
NAME                                          READY   STATUS    RESTARTS   AGE
pod/nfs-client-provisioner-6b66ddf664-rxw77   1/1     Running   0          15m
pod/php-apache-dfb6d784b-jvntc                1/1     Running   0          2m7s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   23d
service/php-apache   ClusterIP   10.99.210.255   <none>        80/TCP    2m7s

NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nfs-client-provisioner   1/1     1            1           4d1h
deployment.apps/php-apache               1/1     1            1           2m8s

NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/nfs-client-provisioner-6b66ddf664   1         1         1       4d1h
replicaset.apps/php-apache-dfb6d784b                1         1         1       2m8s

NAME                   READY   AGE
statefulset.apps/web   0/0     4d

創建 Horizontal Pod Autoscaler

現在,php-apache服務器已經運行,我們將通過 kubectl autoscale 命令創建 Horizontal Pod Autoscaler。 以下命令將創建一個 Horizontal Pod Autoscaler 用於控制我們上一步驟中創建的 deployment,使 Pod 的副本數量在維持在1到10之間。 大致來說,HPA 將通過增加或者減少 Pod 副本的數量(通過 Deployment )以保持所有 Pod 的平均CPU利用率在50%以內 (由於每個 Pod 通過 yaml文件 申請了200 milli-cores CPU,所以50%的 CPU 利用率意味着平均 CPU 利用率爲100 milli-cores)。

[root@server1 hpa]# kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
horizontalpodautoscaler.autoscaling/php-apache autoscaled
horizontalpodautoscaler.autoscaling/php-apache autoscaled

我們可以通過以下命令查看 autoscaler 的狀態:

[root@server1 hpa]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         10        1          19s
kubectl get hpa

請注意在上面的命令輸出中,當前的CPU利用率是0%,這是由於我們尚未發送任何請求到服務器 (CURRENT 列顯示了相應 deployment 所控制的所有 Pod 的平均 CPU 利用率)。

增加負載

現在,我們將看到 autoscaler 如何對增加負載作出反應。 我們將啓動一個容器,並通過一個循環向 php-apache 服務器發送無限的查詢請求:

[root@server1 hpa]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   23d
php-apache   ClusterIP   10.99.210.255   <none>        80/TCP    4m32s
[root@server1 hpa]# kubectl run test --image=busybox -it --rm --restart=Never
If you don't see a command prompt, try pressing enter.
/ # while true; do wget -q -O- http://10.99.210.255; done

注意需要訪問的是svc的ip地址:
在這裏插入圖片描述在幾分鐘時間內,通過以下命令,我們可以看到CPU負載升高了(在另一個終端查看):

[root@server1 ~]# kubectl get hpa
NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   250%/50%   1         10        1          4m22s

這時,由於請求增多,CPU利用率已經升至250%。 可以看到,deployment 的副本數量已經增長到了5:

[root@server1 ~]# kubectl get hpa
NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   250%/50%   1         10        5          5m1s

查看pod的資源使用情況:

[root@server1 ~]# kubectl top pod
NAME                                      CPU(cores)   MEMORY(bytes)   
nfs-client-provisioner-6b66ddf664-rxw77   1m           3Mi             
php-apache-dfb6d784b-jvntc                500m         14Mi            
test                                      5m           1Mi             
[root@server1 ~]# kubectl top pod
NAME                                      CPU(cores)   MEMORY(bytes)   
nfs-client-provisioner-6b66ddf664-rxw77   1m           7Mi             
php-apache-dfb6d784b-jvntc                147m         21Mi            
php-apache-dfb6d784b-lsfgp                150m         12Mi            
php-apache-dfb6d784b-vx8rn                134m         11Mi            
test                                      4m           1Mi             
[root@server1 ~]# kubectl top pod
NAME                                      CPU(cores)   MEMORY(bytes)   
nfs-client-provisioner-6b66ddf664-rxw77   1m           7Mi             
php-apache-dfb6d784b-7zb9t                0m           0Mi             
php-apache-dfb6d784b-jvntc                147m         21Mi            
php-apache-dfb6d784b-lsfgp                150m         12Mi            
php-apache-dfb6d784b-pprhd                0m           0Mi             
php-apache-dfb6d784b-vx8rn                134m         11Mi            
test                                      4m           1Mi            
注意: 有時最終副本的數量可能需要幾分鐘才能穩定下來。 由於環境的差異,不同環境中最終的副本數量可能與本示例中的數量不同。

停止負載

我們將通過停止負載來結束我們的示例。

在我們創建 busybox 容器的終端中,輸入<Ctrl> + C來終止負載的產生。

然後我們可以再次查看負載狀態(等待幾分鐘時間):

[root@server1 ~]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         10        1          13m

這時,CPU利用率已經降到0,所以 HPA 將自動縮減副本數量至1。

注意: 自動伸縮完成副本數量的改變可能需要幾分鐘的時間。

三、HPA的伸縮過程

HPA伸縮過程

  1. 收集HPA控制下所有Pod最近的cpu使用情況(CPU utilization)
  2. 對比在擴容條件裏記錄的cpu限額(CPUUtilization)
  3. 調整實例數(必須要滿足不超過最大/最小實例數)
  4. 每隔30s做一次自動擴容的判斷

CPU utilization的計算方法是用cpu usage(最近一分鐘的平均值,通過metrics可以直接獲取到)除以cpu request(這裏cpu request就是我們在創建容器時制定的cpu使用核心數)得到一個平均值,這個平均值可以理解爲:平均每個Pod CPU核心的使用佔比。

我們計算在上例中的計算方法:

上例中我們的cpu request爲200m(在部署文件中定義),在負載開始時我們的cpu usage爲500m,因此上例的CPU utilization500/200=2.5.

HPA進行伸縮算法

目標pod數量計算公式:TargetNumOfPods = ceil(sum(CurrentPodsCPUUtilization) / Target)

ceil()表示取大於或等於某數的最近一個整數。

  • 爲了保持集羣的穩定,每次擴容後冷卻3分鐘才能再次進行擴容,而縮容則要等5分鐘後。
  • 當前Pod Cpu使用率與目標使用率接近時,不會觸發擴容或縮容:
  • 觸發條件:avg(CurrentPodsConsumption) / Target >1.1 或 <0.9

上例中的target我們定義的是50%,因此TargetNumOfPods = ceil(2.5 /0.5)=5

因此目標pod數量應該爲5,最後的結果也驗證了我們的計算。

上例中在擴展pod數量時中間還有一個過程:

[root@server1 ~]# kubectl top pod
NAME                                      CPU(cores)   MEMORY(bytes)   
nfs-client-provisioner-6b66ddf664-rxw77   1m           7Mi             
php-apache-dfb6d784b-jvntc                147m         21Mi            
php-apache-dfb6d784b-lsfgp                150m         12Mi            
php-apache-dfb6d784b-vx8rn                134m         11Mi            
test                                      4m           1Mi         

可以看出此時有三個pod,cpu利用率爲147,150,134

這時avg(CurrentPodsConsumption)=((147+150+134)/3)/200=0.718,觸發條件爲0.718/0.5=1.43 > 1.1,因此還會觸發擴容,擴容的目標pod數量爲((147+150+134)/200)/0.5=4.31,取整爲5,因此我們再次查看時副本數變成了5個。

四、引入其他度量指標

利用autoscaling/v2beta2API版本,您可以在自動伸縮 php-apache 這個 Deployment 時引入其他度量指標。

[root@server1 hpa]# vim hpav2.yaml 
[root@server1 hpa]# cat hpav2.yaml 
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        averageUtilization: 60
        type: Utilization
  - type: Resource
    resource:
      name: memory
      target:
        averageValue: 50Mi
        type: AverageValue

[root@server1 hpa]# kubectl apply -f hpav2.yaml 
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
horizontalpodautoscaler.autoscaling/php-apache configured

[root@server1 hpa]# kubectl get hpa
NAME         REFERENCE               TARGETS                 MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   13824512/50Mi, 0%/60%   1         10        8          26m

查看hpa時可以看出已經有了cpu的指標,單位時字節。

這裏就不進行演示。

實驗後刪除:

[root@server1 hpa]# kubectl delete -f php-apache.yaml 
deployment.apps "php-apache" deleted
service "php-apache" deleted
[root@server1 hpa]# kubectl delete -f hpav2.yaml
horizontalpodautoscaler.autoscaling "php-apache" deleted
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章