Skip to content

Scale & autoscale workloads

Once your app is running (see Deploy your first app), the next question is capacity: how do you handle more traffic without over-provisioning? Kubernetes scales workloads in two ways — manually and automatically.

The simplest lever is the replica count:

Terminal window
kubectl -n demo scale deployment/web --replicas=4
kubectl -n demo get pods

Kubernetes starts new Pods and the Service load-balances across all of them immediately. Scaling back down is the same command with a smaller number.

More replicas only help availability if they don’t all land on the same node. Topology spread constraints keep them balanced:

spec:
template:
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels: { app: web }

Now a single node going away takes out at most a fraction of your Pods, and the Deployment reschedules them elsewhere.

A HorizontalPodAutoscaler adjusts the replica count for you based on observed load. This one targets 60% average CPU, between 2 and 10 replicas:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
namespace: demo
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
Terminal window
kubectl apply -f hpa.yaml
kubectl -n demo get hpa web -w

The HPA needs the metrics-server to read Pod CPU/memory — it’s included on paasbox clusters, so the autoscaler works out of the box. HPA scaling relies on the resource requests you set on the container, which is another reason to always declare them.

Pods scale in seconds; nodes scale in minutes. When the HPA wants more Pods than your nodes can fit, the cluster adds capacity from your node pool — pooled first, so you get the density (and the savings) before paying for new servers.

Terminal window
kubectl -n demo run load --rm -it --image=busybox --restart=Never -- \
/bin/sh -c "while true; do wget -q -O- http://web.demo; done"

Watch kubectl -n demo get hpa web -w and you’ll see the target replica count climb as CPU rises, then settle back down after you stop the load (Ctrl-C).

  • Set sensible requests and limits so the autoscaler and scheduler have accurate signals to work with.
  • Add a PodDisruptionBudget so voluntary disruptions (upgrades, drains) never take too many replicas down at once.