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伸縮過程
- 收集HPA控制下所有Pod最近的cpu使用情況(CPU utilization)
- 對比在擴容條件裏記錄的cpu限額(CPUUtilization)
- 調整實例數(必須要滿足不超過最大/最小實例數)
- 每隔30s做一次自動擴容的判斷
CPU utilization的計算方法是用cpu usage(最近一分鐘的平均值,通過metrics可以直接獲取到)除以cpu request(這裏cpu request就是我們在創建容器時制定的cpu使用核心數)得到一個平均值,這個平均值可以理解爲:平均每個Pod CPU核心的使用佔比。
我們計算在上例中的計算方法:
上例中我們的cpu request爲200m(在部署文件中定義),在負載開始時我們的cpu usage爲500m,因此上例的CPU utilization
爲500/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