Home/Learn/Kubernetes/Autoscaling — HPA, VPA & Cluster Autoscaler

Autoscaling — HPA, VPA & Cluster Autoscaler

Advanced
Scaling

Kubernetes has three autoscaling dimensions: HPA scales pod replicas based on CPU/memory/custom metrics, VPA adjusts pod resource requests, and Cluster Autoscaler adds/removes nodes based on pending pods.

Overview

Manual scaling is reactive and error-prone. Kubernetes's autoscaling stack handles it automatically: HPA (Horizontal Pod Autoscaler) adds or removes pod replicas when CPU or custom metrics cross thresholds — the most common form of autoscaling. VPA (Vertical Pod Autoscaler) adjusts the resource requests/limits of pods based on actual usage — useful for right-sizing without over-provisioning. Cluster Autoscaler watches for pods that cannot be scheduled due to insufficient nodes and adds nodes to the node group (ASG on AWS, MIG on GCP); it also removes underutilised nodes to reduce cost.

HPA — Horizontal Pod Autoscaler

HPA scales pod replicas based on observed metrics. It requires the Metrics Server to be installed. Custom metrics (HTTP requests/second, queue depth) need Prometheus Adapter or KEDA.

hpa.yaml — HPA with CPU and custom metrics
# Prerequisite: install metrics-server

# kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml



# hpa.yaml — scale on CPU utilization

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

  name: my-app-hpa

spec:

  scaleTargetRef:

    apiVersion: apps/v1

    kind: Deployment

    name: my-app

  minReplicas: 2

  maxReplicas: 20

  metrics:

    - type: Resource

      resource:

        name: cpu

        target:

          type: Utilization

          averageUtilization: 70    # target: keep avg CPU at 70%

    - type: Resource

      resource:

        name: memory

        target:

          type: AverageValue

          averageValue: 400Mi       # keep avg memory usage under 400Mi



# Scale on custom metric (Prometheus via prometheus-adapter)

    - type: External

      external:

        metric:

          name: http_requests_per_second

          selector:

            matchLabels:

              app: my-app

        target:

          type: AverageValue

          averageValue: "1000"      # 1000 req/s per pod



kubectl get hpa

# NAME         REFERENCE            TARGETS        MINPODS  MAXPODS  REPLICAS

# my-app-hpa   Deployment/my-app    45%/70%        2        20       3

#                                   ↑ current/target



kubectl describe hpa my-app-hpa    # see scale events and reasoning

KEDA — Event-Driven Autoscaling

KEDA (Kubernetes Event-Driven Autoscaling) extends HPA with 50+ built-in scalers including Kafka lag, SQS queue depth, Redis list length, and Prometheus queries. It can scale to zero.

KEDA — event-driven autoscaling
# Install KEDA

# helm install keda kedacore/keda --namespace keda --create-namespace



# ScaledObject — scale based on Kafka consumer lag

apiVersion: keda.sh/v1alpha1

kind: ScaledObject

metadata:

  name: kafka-consumer-scaler

spec:

  scaleTargetRef:

    name: order-processor-deployment

  minReplicaCount: 0        # scale to ZERO when no messages!

  maxReplicaCount: 30

  cooldownPeriod: 60        # seconds before scaling down

  triggers:

    - type: kafka

      metadata:

        bootstrapServers: kafka.production.svc.cluster.local:9092

        consumerGroup: order-processors

        topic: orders

        lagThreshold: "100"        # 1 replica per 100 messages of lag



# Scale on AWS SQS queue depth

    - type: aws-sqs-queue

      authenticationRef:

        name: keda-aws-credentials

      metadata:

        queueURL: https://sqs.us-east-1.amazonaws.com/123456/my-queue

        queueLength: "50"          # 1 replica per 50 messages

        awsRegion: us-east-1



# Scale on Prometheus query (HTTP latency p99 > 500ms → scale up)

    - type: prometheus

      metadata:

        serverAddress: http://prometheus.monitoring.svc.cluster.local

        metricName: http_request_duration_p99

        query: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[2m]))

        threshold: "0.5"           # 500ms

Cluster Autoscaler & VPA

Cluster Autoscaler adds nodes when pods are pending (not enough capacity) and removes underutilised nodes. VPA right-sizes resource requests based on actual usage.

Cluster Autoscaler and VPA
# Cluster Autoscaler (EKS example)

# Install: managed by cloud providers or helm chart

# Needs IAM permissions to modify Auto Scaling Groups



# What triggers scale-up: pods in Pending state (no node has capacity)

kubectl get events | grep "FailedScheduling"

# FailedScheduling: 0/3 nodes available: insufficient memory



# What triggers scale-down: node utilization < 50% for > 10 min

# Cluster Autoscaler annotations to prevent node scale-down:

kubectl annotate node my-node cluster-autoscaler.kubernetes.io/scale-down-disabled=true



# VPA — Vertical Pod Autoscaler

# Install: separate component from VPA project

# Mode: "Off"(recommend only), "Initial"(apply at creation), "Auto"(live update)



apiVersion: autoscaling.k8s.io/v1

kind: VerticalPodAutoscaler

metadata:

  name: my-app-vpa

spec:

  targetRef:

    apiVersion: apps/v1

    kind: Deployment

    name: my-app

  updatePolicy:

    updateMode: "Off"        # only recommend, don't apply automatically



# After running for a while:

kubectl describe vpa my-app-vpa

# Recommendation:

#   Container Recommendations:

#     Container Name: app

#     Lower Bound:    cpu: 50m    memory: 64Mi

#     Target:         cpu: 100m   memory: 128Mi   ← use these as your requests

#     Upper Bound:    cpu: 500m   memory: 512Mi

Key Points to Remember

  • 1HPA scales pod count based on CPU/memory/custom metrics — requires Metrics Server.
  • 2KEDA extends HPA to 50+ event sources (Kafka lag, SQS depth, Redis) and can scale to zero.
  • 3Cluster Autoscaler adds nodes for Pending pods and removes underutilised nodes — reduces cloud cost.
  • 4VPA recommends right-sized resource requests based on observed usage — start with updateMode: Off.
  • 5Never run HPA and VPA in Auto mode on the same deployment — they conflict. VPA: Off mode + HPA is safe.
  • 6Scale-to-zero with KEDA dramatically reduces costs for batch/event-driven workloads with idle periods.

Interview Questions

Sign in to ask Aria
1

How does HPA decide when to scale?

2

What is the difference between HPA and Cluster Autoscaler?

Ask Aria about Autoscaling — HPA, VPA & Cluster Autoscaler

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…