How-to
Horizontal pod autoscaling¶
Change the number of pods in a deployment with its CPU use, so it runs more replicas under load and fewer when it's quiet.
A HorizontalPodAutoscaler compares the deployment's average CPU use with a target, as a percentage of what each pod requests, and sets the number of replicas between a minimum and a maximum. It reads CPU use from metrics-server, which a BKS cluster doesn't include: you install it. When more pods need more nodes, cluster autoscaling adds them.
Before you start¶
- A cluster, and
kubectlconnected to it: see Create a cluster. - A deployment whose containers have a CPU request. The target is a percentage of the request, so a pod without one can't be scaled on CPU.
Install metrics-server¶
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.9.0/components.yaml
kubectl -n kube-system patch deployment metrics-server --type=json \
-p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'
The patch is needed on BKS. Each node's kubelet serves its metrics with a self-signed certificate that doesn't name the node's address, so metrics-server can't verify it, and logs x509: cannot validate certificate. --kubelet-insecure-tls skips that check for the connection from metrics-server to the kubelets, inside the cluster.
After a minute, CPU and memory use show for each node:
Create the autoscaler¶
This example runs a small web app that uses CPU for each request, with a CPU request of 200m, a fifth of a vCPU.
web.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: registry.k8s.io/hpa-example
ports:
- containerPort: 80
resources:
requests:
cpu: 200m
limits:
cpu: 500m
---
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
The autoscaler keeps average CPU use near 50% of the request, with between 1 and 5 replicas.
hpa.yaml:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
TARGETS shows the current use against the target, such as cpu: 0%/50%, once metrics-server has a reading.
Watch it scale¶
Send the app a steady stream of requests from a pod in the cluster:
kubectl run load --image=busybox:1.37 --restart=Never -- /bin/sh -c "while true; do wget -q -O- http://web >/dev/null; done"
kubectl get hpa web --watch
As CPU use passes the target, REPLICAS rises, up to the maximum. Stop the load, and the autoscaler waits 5 minutes before it removes replicas, so a short lull doesn't scale the app down only to scale it up again:
Check it worked¶
- Under load,
kubectl get hpa webshows more replicas than the minimum, andkubectl get deployment webshows them ready. - After the load stops, the replicas drop back to the minimum.
kubectl delete -f hpa.yaml -f web.yamlremoves the example.
Related¶
- Performance efficiency: capacity that follows demand.
- Cluster autoscaling: more nodes for more pods.
- Kubernetes documentation on HorizontalPodAutoscaler: scaling on memory and custom metrics.