一、概述
HPA全稱Horizontal Pod Autoscaling,即pod的水平自動擴展。HPA的操作對象是RC、RS或Deployment對應的Pod,根據觀察到的CPU實際使用量與用戶的期望值進行比對,做出是否需要增減實例數量的決策。
它根據Pod當前系統的負載來自動水平擴容,如果系統負載超過預定值,就開始增加Pod的個數,如果低於某個值,就自動減少Pod的個數。目前K8S的HPA只能根據CPU和內存去度量系統的負載,而且目前還依賴heapster去收集CPU的使用情況。
HPA通過定期(定期輪詢的時間通過–horizontal-pod-autoscaler-sync-period選項來設置,默認的時間爲30秒)通過Status.PodSelector來查詢pods的狀態,獲得pod的CPU使用率。然後,通過現有pods的CPU使用率的平均值(計算方式是最近的pod使用量除以設定的每個Pod的CPU使用率限額,例最近一分鐘從heapster中獲得的平均值除以Pod的CPU limits值)跟目標使用率進行比較,並且在擴容時,還要遵循預先設定的副本數限制:MinReplicas <= Replicas <= MaxReplicas。
計算擴容後Pod的個數:sum(最近一分鐘內某個Pod的CPU使用率/量的平均值)/CPU使用上限的整數+1
考慮到自動擴展的決策可能需要一段時間纔會生效,甚至在短時間內會引入一些噪聲。例如當pod所需要的CPU負荷過大,從而運行一個新的pod進行分流,在創建過程中,系統的CPU使用量可能會有一個攀升的過程。所以,在每一次作出決策後的一段時間內,將不再進行擴展決策。對於ScaleUp而言,這個時間段爲3分鐘,Scaledown爲5分鐘。
HPA允許一定範圍內的CPU使用量的不穩定,只有avg(CurrentPodsConsumption) / Target小於90%或者大於110%時纔會觸發擴容或縮容,避免頻繁擴容、縮容造成顛簸。
爲了簡便,選用了相對比率(90%的CPU資源)而不是0.6個CPU core來描述擴容、縮容條件。如果選擇使用絕對度量,用戶需要保證目標(限額)要比請求使用的低,否則,過載的Pod未必能夠消耗那麼多,從而自動擴容永遠不會被觸發:假設設置CPU爲1個核,那麼這個pod只能使用1個核,可能Pod在過載的情況下也不能完全利用這個核,所以擴容不會發生。在修改申請資源時,還有同時調整擴容的條件,比如將1個core變爲1.2core,那麼擴容條件應該同步改爲1.2core,真是太麻煩了,與自動擴容的目標相悖。
例1:
[root@docker79 ~]# kubectl get pods
No resources found.
[root@docker79 ~]# kubectl run myapp --image=ikubernetes/myapp:v1 --replicas=1 --requests='cpu=50m,memory=256Mi' --limits='cpu=50m,memory=256Mi' --labels='app=myapp' --expose --port=80
service/myapp created
deployment.apps/myapp created
[root@docker79 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-6985749785-l4c87 1/1 Running 0 15s
[root@docker79 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 20d
myapp ClusterIP 10.100.44.181 <none> 80/TCP 20s
[root@docker79 ~]# kubectl autoscale deployment myapp --min=1 --max=4 --cpu-percent=40
horizontalpodautoscaler.autoscaling/myapp autoscaled
[root@docker79 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
myapp Deployment/myapp <unknown>/40% 1 4 0 6s
[root@docker79 ~]#
[root@docker79 ~]# kubectl patch svc myapp -p '{"spec":{"type":"NodePort"}}'
service/myapp patched
[root@docker79 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 20d
myapp NodePort 10.100.44.181 <none> 80:30193/TCP 4m
[root@docker79 ~]#
[root@docker79 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
myapp Deployment/myapp 0%/40% 1 4 1 6m
[root@docker79 ~]#
以上創建hap,並定義了CPU使用率達到40%時進行擴展,下面開啓 ab壓測,然後使其自動擴展
[root@docker79 ~]# ab -c 100 -n 50000 http://docker78:30193/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking docker78 (be patient)
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
......
[root@docker79 ~]# kubectl describe hpa
Name: myapp
Namespace: default
Labels: <none>
Annotations: <none>
CreationTimestamp: Mon, 17 Sep 2018 16:40:26 +0800
Reference: Deployment/myapp
Metrics: ( current / target )
resource cpu on pods (as a percentage of request): 102% (51m) / 40%
Min replicas: 1
Max replicas: 4
Deployment pods: 1 current / 3 desired
Conditions:
Type Status Reason Message
---- ------ ------ -------
AbleToScale True SucceededRescale the HPA controller was able to update the target scale to 3
ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
ScalingLimited False DesiredWithinRange the desired count is within the acceptable range
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulRescale 14s horizontal-pod-autoscaler New size: 3; reason: cpu resource utilization (percentage of request) above target
[root@docker79 ~]#
[root@docker79 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-6985749785-fvxbz 1/1 Running 0 1m
myapp-6985749785-l4c87 1/1 Running 0 14m
myapp-6985749785-xdmnw 1/1 Running 0 1m
[root@docker79 ~]#
例2,接上以manifests yaml的格式定義HorizontalPodAutoscaler ,並同時定義CPU、Memory資源的閥值,以便pod擴展:
[root@docker79 ~]# cd manifests/
[root@docker79 manifests]# mkdir hpa
[root@docker79 manifests]# cd hpa
[root@docker79 hpa]# vim hpa-demo-v2.yaml
[root@docker79 hpa]# cat hpa-demo-v2.yaml
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa-v2
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 55
- type: Resource
resource:
name: memory
targetAverageValue: 50Mi
[root@docker79 hpa]#
[root@docker79 hpa]# kubectl delete hpa myapp
horizontalpodautoscaler.autoscaling "myapp" deleted
[root@docker79 hpa]#
[root@docker79 hpa]# kubectl apply -f hpa-demo-v2.yaml
horizontalpodautoscaler.autoscaling/myapp-hpa-v2 created
[root@docker79 hpa]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
myapp-hpa-v2 Deployment/myapp <unknown>/50Mi, <unknown>/55% 1 5 0 6s
[root@docker79 hpa]#
再次開啓壓測
[root@docker79 ~]# ab -c 100 -n 30000 http://docker77:30193/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking docker77 (be patient)
Completed 3000 requests
Completed 6000 requests
......
[root@docker79 hpa]# kubectl describe hpa
Name: myapp-hpa-v2
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"autoscaling/v2beta1","kind":"HorizontalPodAutoscaler","metadata":{"annotations":{},"name":"myapp-hpa-v2","namespace":"default"},"spec":{...
CreationTimestamp: Mon, 17 Sep 2018 17:30:53 +0800
Reference: Deployment/myapp
Metrics: ( current / target )
resource memory on pods: 3442688 / 50Mi
resource cpu on pods (as a percentage of request): 68% (34m) / 55%
Min replicas: 1
Max replicas: 5
Deployment pods: 2 current / 3 desired
Conditions:
Type Status Reason Message
---- ------ ------ -------
AbleToScale True SucceededRescale the HPA controller was able to update the target scale to 3
ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
ScalingLimited False DesiredWithinRange the desired count is within the acceptable range
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulRescale 5m horizontal-pod-autoscaler New size: 2; reason: cpu resource utilization (percentage of request) above target
Normal SuccessfulRescale 9s horizontal-pod-autoscaler New size: 3; reason: cpu resource utilization (percentage of request) above target
[root@docker79 hpa]#
仔細觀察hpa 的信息,發現已經擴展了兩個new pods。
例3:
pods 可以自定義一些資源指標,並將其輸出成Restful風格的API,並支持讓prometheus 讀取、認識這些自定義的指標值 ,然後hpa 就可以根據這些指標值 進行擴展或收縮。如下所示:
[root@docker79 hpa]# cat hpa-demo-custom.yaml
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa-v2
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 1
maxReplicas: 5
metrics:
- type: Pods
pods:
metricName: http_requests
targetAverageValue: 800m
[root@docker79 hpa]#
由於hpa 我使用還不是特別熟練,所以簡單總結這麼多,後續慢慢補充。大家勿噴。