K8s Horizontal Pod Autoscaler

Jeff Yen
9 min readNov 18, 2019

目前在Horizontal Pod Autoscaler中最常使用的兩個api version 版本為v2beta1 和 v2beta2

autoscaling/V2beta1中是沒辦法自訂metrics,只能使用CPU and memory條件去自動擴展,你可以直接下單行的指令去啟動

autoscaling/V2beta2中是可以自訂metrics,也可以自己設定條件去自動擴展,像是requests-per-second

這是官方的說明文件
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#run-expose-php-apache-server

autoscaling/V2beta1 (GCP)
1.先下載官方的deployment-nginx
$ kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml

2.當所有Pod的平均CPU利用率超過50%會自動起一個pod
$ kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=1 --max=5

使用kubectl get hpa去檢查Horizontal Pod Autoscaler狀態

3. 然後把設定檔讀出來

在GCP上會依照不同的版本有不同的支援,像是我目前使用的版本為1.13.11-gke.9,只支援到v2beta1

$ kubectl api-versions | grep auto | head -n 10

kubectl get hpa.v2beta1.autoscaling -o yaml > /tmp/hpa-v2.ymal

在這篇Google issue就有提到GKE現在大多數的版本是不支援v2beta2
可能要等到GKE 1.15.5版本才有可能支援

https://issuetracker.google.com/issues/135624588

https://stackoverflow.com/questions/57393491/how-to-enable-autoscaling-v2beta2-in-google-cloud

假如使用minitube官方的lab
1.建立一個apache index.php
$ kubectl run php-apache --image=k8s.gcr.io/hpa-example --requests=cpu=200m --limits=cpu=500m --expose --port=80

2.一樣用指令設定hpa
$ kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

檢查 hpa狀態
$ kubectl get hpa

發現無法得到pod的CPU數值 FailedGetResourceMetric
查了資料是要改Minikube的設定

3.啟用 metrics-server 和取消 heapster in minikube

$ minikube addons disable heapster
$ minikube addons enable metrics-server

部署 metrics-server

$ git clone https://github.com/kubernetes-incubator/metrics-server/tree/master/deploy/1.8%2B
$ cd metrics-server
$ kubectl apply --filename deploy/1.7/

4.啟動一個容器去向php-apache 發送無限的查詢(另一個終端視窗)

$ kubectl run -i --tty load-generator --image=busybox /bin/sh

Hit enter for command prompt

$ while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done

我們可以看到CPU升高,php-apache 的pods數量也不斷升高

v2beta2 (Minikube)

1.生成一份v2beta2版本的設定檔來做修改

$ kubectl get hpa.v2beta2.autoscaling -o yaml > /tmp/hpa-v2.yaml

打開/tmp/hpa-v2.yaml

targetCPUUtilizationPercentage的設定被metrics 的設定所取代,resource metric 可以用來設定更高階的hpa,目前有兩種metrics可以設定,pod metricsobject metrics

2. 設定pod metrics

先描述了Pod,並在不同Pod之間做平均,透過一個標準值來決定Replicas 的數量

type: Pods
pods:
metric:
name: packets-per-second
target:
type: AverageValue
averageValue: 1k

3.設定object metrics

metric是用來描述同一個namespace的其他物件,而不是對pods做監控

type: Object
object:
metric:
name: requests-per-second
describedObject:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
name: main-route
target:
type: Value
value: 2k

4.最後可以整合成一份hpa設定檔

HorizontalPodAutoscaler會確保Pod的CPU利用率在50%以内,每秒能夠服務1000个數據封包的請求,並確保所有在Ingress的Pod每秒能夠服務的請求總數能到10000個

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
- type: Pods
pods:
metric:
name: packets-per-second
target:
type: AverageValue
averageValue: 1k
- type: Object
object:
metric:
name: requests-per-second
describedObject:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
name: main-route
target:
type: Value
value: 10k
status:
observedGeneration: 1
lastScaleTime: <some-time>
currentReplicas: 1

desiredReplicas: 1
currentMetrics:
- type: Resource
resource:
name: cpu
current:
averageUtilization: 0
averageValue: 0
- type: Object
object:
metric:
name: requests-per-second
describedObject:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
name: main-route
current:
value: 10k

5.還可以設定跟k8s不相關的object

- type: External
external:
metric:
name: queue_messages_ready
selector: "queue=worker_tasks"
target:
type: AverageValue
averageValue: 30

--

--