Busy evenings: scaling your application
- Published
- Read
- 6 minutes
- Tags
Give your application more Pods when things get busy, then let Kubernetes adjust the numbers.
Give your application more Pods when things get busy, then let Kubernetes adjust the numbers.
A quiet evening in the house becomes a party. Two people handling drinks were plenty an hour ago. Now there’s a queue in the hallway. Getting a few more people to help is usually easier than asking those two to move six times faster.
Your application can work the same way. A Deployment can run several copies of a Pod, called replicas. Adding replicas is horizontal scaling. A Service sends traffic to the ready Pods behind it, so callers keep using the same address as the numbers change.
Those extra Pods still need somewhere to run. Scaling a Deployment adds Pods to your existing Nodes. It doesn’t add Nodes or conjure more CPU out of your laptop.
Set up a temporary workspace
Use the Docker Desktop cluster from the earlier chapters, with Kubernetes running and kubectl connected to it. The commands below work in macOS Terminal and Windows PowerShell.
For this exercise, I use a small demo from the Kubernetes HPA walkthrough. It does CPU work for each request, which makes changes in load easy to see.
Give it its own namespace:
kubectl create namespace scaling-demoKeep the exercise files in a separate folder too. Save this as scaling-demo.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 2
selector:
matchLabels:
app: scaling-web
template:
metadata:
labels:
app: scaling-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: scaling-web
ports:
- port: 80
targetPort: 80The CPU settings will matter when the autoscaler takes over. For now, apply the file and wait for both replicas to become available:
kubectl apply -n scaling-demo -f scaling-demo.yaml
kubectl rollout status deployment/web -n scaling-demo
kubectl get pods -n scaling-demoYou should see two Pods with 1/1 in the READY column. All workload commands use -n scaling-demo, so you can leave your current namespace setting alone.
Scale it yourself
Ask the Deployment for four replicas:
kubectl scale deployment/web -n scaling-demo --replicas=4
kubectl get pods -n scaling-demo --watchTwo more Pods should appear and become ready. Press Ctrl+C to stop watching; the Pods keep running.
The Service still has the same name and address. Its selector matches the new Pods too, so they join the pool serving requests. You don’t need another Service for every replica.
Return to two before moving on:
kubectl scale deployment/web -n scaling-demo --replicas=2This changes the running Deployment. The replicas value in your saved YAML stays as it was.
Let Kubernetes adjust the numbers
A Horizontal Pod Autoscaler, or HPA, watches a metric and adjusts a Deployment’s replica count. Here, that metric is CPU usage. More requests make this demo consume more CPU, giving the HPA a reason to add replicas.
First, it needs measurements.
Install Metrics Server
The HPA needs CPU measurements from Metrics Server. On my MacBook, I had to install it separately in Docker Desktop.
Install it once for your cluster using the commands below. If you already have Metrics Server running and kubectl top pods -n scaling-demo returns CPU and memory figures, skip ahead to “Give the HPA a target”.
This pinned Metrics Server version supports Kubernetes 1.34 and newer, including the 1.36 cluster used in this guide. Check your server version with kubectl version if yours differs.
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.9.0/components.yamlOn my Docker Desktop setup, Metrics Server also failed to validate the kubelet certificates. For this local exercise, configure it to skip that check. Save this as metrics-server-local.json:
[
{
"op": "add",
"path": "/spec/template/spec/containers/0/args/-",
"value": "--kubelet-insecure-tls"
}
]Apply the configuration and wait for Metrics Server to become ready:
kubectl patch deployment metrics-server -n kube-system --type=json --patch-file=metrics-server-local.json
kubectl rollout status deployment/metrics-server -n kube-system --timeout=120sThe flag disables verification of kubelet serving certificates. Use it only for this local learning cluster; production needs properly trusted certificates.
Give Metrics Server a minute to collect measurements, then check:
kubectl top pods -n scaling-demoYou should see CPU and memory figures for the demo Pods. If measurements still fail, or the rollout times out, inspect the logs:
kubectl logs -n kube-system deployment/metrics-serverContinue once kubectl top pods -n scaling-demo returns measurements. Metrics Server is cluster infrastructure: installing it creates shared resources outside the exercise namespace.
Give the HPA a target
Each Pod requests 200m of CPU. The m stands for millicores: 1000m equals one CPU core, so 200m is one fifth of a core. Our 50% target tells the HPA to aim for half the requested amount (100m) per Pod on average. When usage stays above the target, it adds more Pods to share the work.
Save this as hpa.yaml:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 6
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50Apply it:
kubectl apply -n scaling-demo -f hpa.yaml
kubectl get hpa -n scaling-demoThe HPA now manages the replica count within those bounds. Leave manual scaling alone while it is active. Also avoid reapplying scaling-demo.yaml during the exercise: its replicas: 2 would reset the count until the HPA adjusts it again.
Make it a busy evening
Start a load-generator Pod:
kubectl run load-generator -n scaling-demo --image=busybox:1.37 --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://web; done"The loop runs inside that container, so the same command works from PowerShell or macOS. It sends requests through the demo’s Service.
Watch the HPA:
kubectl get hpa web -n scaling-demo --watchThe TARGETS column shows measured CPU utilisation alongside the 50% target. As load rises, the replica count should increase above two, up to the maximum of six. It may take a few minutes, and the exact count depends on the load and available resources.
Press Ctrl+C to stop watching, then inspect the Pods:
kubectl get pods -n scaling-demoIf TARGETS stays <unknown>, check kubectl top pods -n scaling-demo and kubectl describe hpa web -n scaling-demo. If new Pods remain Pending, use kubectl describe pod <pod-name> -n scaling-demo to see whether the cluster lacks capacity. An HPA can request more replicas than your laptop can run.
Let the evening settle down
Stop the traffic by deleting the load generator:
kubectl delete pod load-generator -n scaling-demo
kubectl get hpa web -n scaling-demo --watchCPU usage should drop, followed by the replica count returning to two. Give it time: the default scale-down stabilisation window is five minutes. That delay helps avoid repeatedly removing and recreating Pods whenever the load briefly dips.
The HPA reacts to measurements. Starting extra Pods also takes time, so autoscaling helps absorb demand without promising an instant response to every traffic spike.
Tidy up
Press Ctrl+C to stop watching, then remove the temporary workspace:
kubectl delete namespace scaling-demoDeleting the namespace removes its Deployment, Pods, Service, and HPA, including the load generator if you left it running. Your dev and prod resources remain ready for the next exercise.
If you installed Metrics Server, leave it running as shared cluster infrastructure. You can also remove the local exercise folder once you’re finished.
