【六】K8s-Pod 水平自動擴縮實踐(簡稱HPA)

一、概述

Pod 水平自動擴縮(Horizontal Pod Autoscaler)簡稱 HPA,HPA 可以根據 CPU 利用率進行自動伸縮 Pod 副本數量,除了 CPU 利用率,也可以基於其他應程式提供的自定義度量指標來執行自動擴縮。

通過 HPA 可以達到某個時刻業務請求量很大的時候,不需要我們人工去干涉,它會根據我們設定的指標來進行自動伸縮 Pod 數量來應付訪問量。

image-20210602110724560

這是官方的圖

1111

這是我畫的圖(勿噴)

二、安裝Metrics-Server

Heapster 官方在v1.11中已經被廢棄,Heapster 監控數據可用,但 HPA 不再從 Heapster 拿數據,所以就不能滿足我們本次實驗。

Kubernetes 版本為 v1.2 或更高採用 Metrics-Server 來獲取監控數據, HPA 根據此 Metrics API 來獲取度量數據,所以本次實驗需要安裝 Metrics-Server 插件。

1.1 下載YAML文件,修改配置

Metrics-Server GitHub 鏈接:

//github.com/kubernetes-sigs/metrics-server

image-20210531162530954

由於我的環境 K8s 版本是 1.21,直接安裝最新的 Metrics-Server 即可。

我們需要下載components.yaml下載到本地,添加- --kubelet-insecure-tls到配置文件中,否則會報錯

[root@k8s-master01 ]# wget //github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

如果 Linux 作業系統一直無法下載,可以嘗試在 Windows 上的迅雷下載好上傳。

打開components.yaml添加如下配置:

- --kubelet-insecure-tls
# kubelet 的10250埠使用的是https協議,連接需要驗證tls證書,--kubelet-insecure-tls不驗證客戶端證書。

image-20210531164407561

1.2 注意事項

如果不添加- --kubelet-insecure-tls ,可能會出現如下報錯

查看 metrics-server-xxx-xxx 詳細事件時發現報錯如下:

[root@k8s-master01 ~]# kubectl describe pod metrics-server-xxx-xxx -n kube-system

2-1

我們在查看該 Pod 詳細日誌,報錯如下:

[root@k8s-master01 ~]# kubectl logs -n kube-system metrics-server-6dfddc5fb8-f8gnd
...
I0531 07:57:33.049547       1 server.go:188] "Failed probe" probe="metric-storage-ready" err="not metrics to serve"
I0531 07:57:43.049460       1 server.go:188] "Failed probe" probe="metric-storage-ready" err="not metrics to serve"
E0531 07:57:44.458989       1 scraper.go:139] "Failed to scrape node" err="Get \"//192.168.115.11:10250/stats/summary?only_cpu_and_memory=true\": x509: cannot validate certificate for 192.168.115.11 because it doesn't contain any IP SANs" node="k8s-master01"
E0531 07:57:44.472464       1 scraper.go:139] "Failed to scrape node" err="Get \"//192.168.115.13:10250/stats/summary?only_cpu_and_memory=true\": x509: cannot validate certificate for 192.168.115.13 because it doesn't contain any IP SANs" node="k8s-node02"
E0531 07:57:44.478313       1 scraper.go:139] "Failed to scrape node" err="Get \"//192.168.115.12:10250/stats/summary?only_cpu_and_memory=true\": x509: cannot validate certificate for 192.168.115.12 because it doesn't contain any IP SANs" node="k8s-node01"

2-3

1.3 手動下載鏡像

由於k8s.gcr.io在國外,導致無法下載metrics-server鏡像問題。

當我們查看 Pod 狀態是發現為ImagePullBackOff

[root@k8s-master01 ~]# kubectl get pod -n kube-system

QQ截圖20210531155527

查看 metrics-server-xxx-xxx 詳細事件時發現報錯如下:

[root@k8s-master01 ~]# kubectl describe pod metrics-server-xxx-xxx -n kube-system
...
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  4m1s                 default-scheduler  Successfully assigned kube-system/metrics-server-87966b776-jqknh to k8s-node01
  Normal   Pulling    106s (x4 over 4m)    kubelet            Pulling image "k8s.gcr.io/metrics-server/metrics-server:v0.5.0"
  Warning  Failed     91s (x4 over 3m45s)  kubelet            Failed to pull image "k8s.gcr.io/metrics-server/metrics-server:v0.5.0": rpc error: code = Unknown desc = Error response from daemon: Get //k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
  Warning  Failed     91s (x4 over 3m45s)  kubelet            Error: ErrImagePull
  Warning  Failed     76s (x6 over 3m45s)  kubelet            Error: ImagePullBackOff
  Normal   BackOff    61s (x7 over 3m45s)  kubelet            Back-off pulling image "k8s.gcr.io/metrics-server/metrics-server:v0.5.0"

QQ截圖20210531155116

需要手動下載鏡像再進行改名(每個節點都需要下載)

[root@k8s-master01 ~]# docker pull bitnami/metrics-server:0.5.0
[root@k8s-master01 ~]# docker tag bitnami/metrics-server:0.5.0 k8s.gcr.io/metrics-server/metrics-server:v0.5.0

image-20210531172203488

注意:當你看到這篇筆記的時候,可能鏡像已經更新了,根據報錯提示來下載即可。

1.4 開始創建 Metrics-Server

只需要在 K8s-master 節點創建即可!

[root@k8s-master01 ~]# kubectl apply -f components.yaml 
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created

查看 Pod 狀態發現已經 Running

[root@k8s-master01 ~]# kubectl get pod -n kube-system

image-20210531172014101

檢查 Metrics Server

[root@k8s-master01 ~]# kubectl top nodes
NAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
k8s-master01   119m         5%     1198Mi          64%       
k8s-node01     29m          1%     476Mi           25%       
k8s-node02     32m          1%     433Mi           23%

在 K8s Dashboard 介面查看資源使用情況

image-20210531172602793

二、創建 HPA 測試案例

創建一個Deployment管理的Nginx Pod,然後利用HPA來進行自動擴縮容。

定義DeploymentYAML文件如下:(hap-deploy-demo.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hpa-nginx-deploy
spec:
  selector:
    matchLabels:
      run: hpa-nginx-deploy
  replicas: 1
  template:
    metadata:
      labels:
        run: hpa-nginx-deploy
    spec:
      containers:
      - name: nginx
        image: hub.test.com/library/mynginx:v1	# 鏡像地址
        ports:
        - containerPort: 80
        resources:
          limits:		# 最大限制
            cpu: 500m	# CPU最大是500微核
          requests: 	# 最低保證
            cpu: 200m	# CPU最小是200微核

test命名空間創建Deployment

[root@k8s-master01 hpa-test]# kubectl create -f hpa-deploy-demo.yaml -n test
deployment.apps/hpa-nginx-deploy created

-n test 指定命名空間

查看 Pod 、Deployment 狀態

image-20210602090900783

創建一個HPA,可以使用kubectl autoscale命令來創建:

[root@k8s-master01 ~]# kubectl autoscale deployment hpa-nginx-deploy --cpu-percent=20 --min=1 --max=10 -n test
horizontalpodautoscaler.autoscaling/hpa-nginx-deploy autoscaled

–cpu-percent=20 HPA 會通過 Pod 伸縮保持平均 CPU 利用率在20%以內;

–min=1 –max=10 允許 Pod 伸縮範圍,最小的 Pod 副本數為1,最大為10;

也可以使用 YAML 進行 HPA 編寫更為詳細的設置。

查看 HPA 當前狀態

[root@k8s-master01 hpa-test]# kubectl get hpa -n test
NAME               REFERENCE                     TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
hpa-nginx-deploy   Deployment/hpa-nginx-deploy   0%/20%    1         10        1          37m

image-20210602101334573

當前的 CPU 利用率是 0%,由於未發送任何請求到該 Pod。

查看 hpa-nginx-deployPod 的 IP地址

[root@k8s-master01 hpa-test]# kubectl get pod -n test -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
hpa-nginx-deploy-9f8676f85-57kg8   1/1     Running   0          42m   10.244.1.23   k8s-node01   <none>           <none>

image-20210602101424299

2.1 增加負載測試

增大負載進行測試,我們來創建一個busybox,並且循環訪問上面創建的服務。

[root@k8s-master01 ~]# kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while true; do wget -q -O- //10.244.1.23; done" -n test

image-20210602102914410

等待一小會,查看 HPA 負載情況,當前 CPU 使用率 49% 已經超出設置值

[root@k8s-master01 ~]# kubectl get hpa -n test -w

image-20210602103639835

此時來查看deployment Pod 副本數量,由原來的1個自動擴容到5個

[root@k8s-master01 ~]# kubectl get deployment hpa-nginx-deploy -n test -w

image-20210602103139578

再次查看 HPA 負載情況,可以看到一直保持在 20% 以內

image-20210602103729003

2.2 停止負載測試

在剛剛創建 busybox 容器的終端中,輸入<Ctrl> + C 來終止負載的測試即可。

等待一會,查看 HPA 負載情況和 Deployment Pod副本數是否到達收縮功能

image-20210602104030571

這是 Dashboard 介面情況,已經過去一兩分鐘了,還沒見收縮,再等等

image-20210602104256270

此時我們可以看到 Pod 副本數已經被收縮了,因為 CPU 使用率為 0,所以只保留最小副本數1個 Pod 對外提供服務

image-20210602104534604

image-20210602105308287

收縮的過程可能要等待幾分鐘;

通過上圖可以看到,Pod 副本數不是一下子回收,而是逐步的回收機制。

這是 Dashboard 介面情況

image-20210602104736237

到此 Pod 水平自動擴縮測試就到此結束了,HPA 不僅僅這些,還有多項度量指標和自定義度量指標自動擴縮等策略等著你去實踐。