一、概述

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

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

這是官方的圖

這是我畫的圖(勿噴)

二、安裝Metrics-Server

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

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

1.1 下載YAML檔案,修改配置

Metrics-Server GitHub 連結:

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

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

我們需要下載components.yaml下載到本地,新增- --kubelet-insecure-tls到配置檔案中,否則會報錯

[root@k8s-master01 ]# wget https://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不驗證客戶端證書。

1.2 注意事項

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

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

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

我們在檢視該 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 \"https://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 \"https://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 \"https://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"

1.3 手動下載映象

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

當我們檢視 Pod 狀態是發現為ImagePullBackOff

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

檢視 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 https://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"

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

[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

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

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

檢查 Metrics Server

[root@k8s-master01 ~]# kubectl top nodesW0531 17:22:17.466637   97641 top_node.go:119] Using json format to get metrics. Next release will switch to protocol-buffers, switch early by passing --use-protocol-buffers flagNAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   k8s-master01   119m         5%     1198Mi          64%       k8s-node01     29m          1%     476Mi           25%       k8s-node02     32m          1%     433Mi           23%

不知道為什麼會出現這樣的提示,Metrics Server 是正常的,也可以獲取到資源使用情況,暫時不理它,後續再解決。

W0531 17:22:17.466637   97641 top_node.go:119] Using json format to get metrics. Next release will switch to protocol-buffers, switch early by passing --use-protocol-buffers flag

在 K8s Dashboard 介面檢視資源使用情況

二、建立 HPA 測試案例

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

定義DeploymentYAML檔案如下:(hap-deploy-demo.yaml)

apiVersion: apps/v1kind: Deploymentmetadata:  name: hpa-nginx-deployspec:  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 testdeployment.apps/hpa-nginx-deploy created

-n test 指定名稱空間

檢視 Pod 、Deployment 狀態

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

[root@k8s-master01 ~]# kubectl autoscale deployment hpa-nginx-deploy --cpu-percent=20 --min=1 --max=10 -n testhorizontalpodautoscaler.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 testNAME               REFERENCE                     TARGETS   MINPODS   MAXPODS   REPLICAS   AGEhpa-nginx-deploy   Deployment/hpa-nginx-deploy   0%/20%    1         10        1          37m

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

檢視 hpa-nginx-deployPod 的 IP地址

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

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- http://10.244.1.23; done" -n test

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

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

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

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

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

2.2 停止負載測試

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

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

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

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

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

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

這是 Dashboard 介面情況

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