Cloud Native 47 min read

Kubernetes HPA & VPA Auto-Scaling: Elastic Strategies for Traffic Spikes

An in‑depth comparison of Kubernetes Horizontal and Vertical Pod Autoscalers—including algorithms, configurations, performance benchmarks, mixed‑mode trade‑offs, custom‑metric integrations, and real‑world case studies—demonstrates how to choose and tune HPA, VPA, and KEDA for rapid traffic spikes while avoiding conflicts.

Raymond Ops
Raymond Ops
Raymond Ops
Kubernetes HPA & VPA Auto-Scaling: Elastic Strategies for Traffic Spikes

Overview

Comparison of Kubernetes Horizontal Pod Autoscaler (HPA) and Vertical Pod Autoscaler (VPA) from algorithm, deployment, performance and scenario perspectives. All examples run on Kubernetes 1.32+.

Scaling dimensions

Direction : HPA – horizontal (adds/removes Pods); VPA – vertical (adjusts Pod resources).

Target objects : HPA works on Deployment/StatefulSet/ReplicaSet; VPA works on Pod resources (requests/limits).

API version : HPA – autoscaling/v2 (stable); VPA – autoscaling.k8s.io/v1 (CRD required).

Response time : HPA evaluates metrics every 15 s (configurable) and can scale within seconds‑minutes; VPA needs minutes because it recreates Pods.

Typical workloads : HPA – stateless, request‑driven services; VPA – stateful or single‑instance services where long‑term profiling is needed.

Interaction with Cluster Autoscaler : HPA triggers node provisioning directly; VPA changes requests which may cause evictions that the Cluster Autoscaler handles indirectly.

Test environment

A simple Go HTTP service ( autoscale-test) exposing /compute, /memory and /healthz is deployed with 2 replicas, CPU request 200 m, limit 500 m, memory request 128 Mi, limit 256 Mi. Load is generated with k6 using a staged ramp‑up profile (warm‑up, steady, peak, cooldown).

HPA v2 algorithm

desiredReplicas = ceil[currentReplicas * (currentMetricValue / desiredMetricValue)]

The controller runs in kube‑controller‑manager and evaluates metrics every --horizontal-pod-autoscaler-sync-period (default 15 s). A tolerance window ( --horizontal-pod-autoscaler-tolerance, default 0.1) prevents oscillation; scale‑down uses a stabilization window (default 5 min).

HPA metric types (v2)

Resource – CPU/Memory utilization from Metrics Server.

Pods – per‑Pod custom metric (requires Prometheus Adapter or KEDA).

Object – custom metric on a Kubernetes object (also via Adapter/KEDA).

External – metric from outside the cluster (e.g., queue depth, via KEDA).

Sample HPA configuration (CPU 60 % target)

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: autoscale-test
  namespace: autoscale-lab
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: autoscale-test
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 60
      selectPolicy: Max
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60
      selectPolicy: Min

VPA component architecture

Recommender – analyses historical CPU/Memory usage and produces target, lower‑bound and upper‑bound recommendations (P95, P50, P99).

Updater – compares current requests with recommendations; if deviation exceeds a threshold it evicts the Pod so that the Admission Controller can inject the new resources.

Admission Controller – intercepts Pod creation and injects the recommended resources.requests and resources.limits.

VPA modes

Off – only calculates recommendations; never changes Pods.

Initial – injects recommendations only at Pod creation.

Recreate – evicts Pods with out‑of‑range requests and recreates them.

Auto – automatically selects the best strategy (currently equivalent to Recreate).

Sample VPA configuration (Off mode)

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: autoscale-test-vpa
  namespace: autoscale-lab
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: autoscale-test
  updatePolicy:
    updateMode: "Off"
  resourcePolicy:
    containerPolicies:
    - containerName: app
      minAllowed:
        cpu: 50m
        memory: 64Mi
      maxAllowed:
        cpu: "4"
        memory: 4Gi
      controlledResources:
      - cpu
      - memory

Performance test results (summary)

Time to first new Pod (peak) : HPA 45 s, VPA N/A, HPA+VPA 45 s, KEDA 30 s.

Maximum replicas during peak : HPA 12, VPA 2, HPA+VPA 12, KEDA 10.

P99 latency (peak) : HPA 850 ms, VPA 2800 ms, HPA+VPA 780 ms, KEDA 650 ms.

Error rate (peak) : HPA 0.3 %, VPA 8.5 %, HPA+VPA 0.2 %, KEDA 0.1 %.

Stabilization time after load : HPA 8 min, VPA N/A, HPA+VPA 8 min, KEDA 6 min.

Key findings

VPA Auto cannot keep up with sudden traffic spikes because Pod recreation introduces latency; it is best used for long‑term resource profiling.

Combining HPA (real‑time scaling) with VPA in Off mode yields the most stable and efficient scaling.

KEDA, driven by business metrics such as RPS, reacts earlier than CPU‑based HPA and achieves the lowest latency.

KEDA configuration example (RPS‑based scaling)

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: autoscale-test-keda
  namespace: autoscale-lab
spec:
  scaleTargetRef:
    name: autoscale-test
  pollingInterval: 10
  cooldownPeriod: 300
  minReplicaCount: 2
  maxReplicaCount: 50
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus.monitoring:9090
      query: sum(rate(http_requests_total{namespace="autoscale-lab",deployment="autoscale-test"}[2m]))
      threshold: "200"
    authenticationRef:
      name: prometheus-auth
  - type: cpu
    metadata:
      value: "70"
    authenticationRef:
      name: cpu-auth
  advanced:
    horizontalPodAutoscalerConfig:
      behavior:
        scaleUp:
          stabilizationWindowSeconds: 0
          policies:
          - type: Percent
            value: 200
            periodSeconds: 15
          selectPolicy: Max
        scaleDown:
          stabilizationWindowSeconds: 300
          policies:
          - type: Percent
            value: 5
            periodSeconds: 60
          selectPolicy: Min

Real‑world case studies

E‑commerce flash sale (HPA with multiple metrics)

During a 618 promotion the product‑detail API saw P99 latency up to 5 s. The original HPA (CPU 70 % target, scale‑up limited to 2 Pods per minute) was too conservative. Increasing scaleUp.policies to a 300 % increase every 15 s and raising minReplicas to 5 eliminated the latency spikes.

GPU‑based inference service (VPA Off for profiling)

A single‑instance inference service was initially allocated 4 CPU / 16 Gi. Actual usage was 0.8 CPU / 6 Gi. VPA Off recommended ~1.1 CPU and 7 Gi. Updating the Deployment requests to the VPA target reduced cluster CPU consumption by ~30 % without downtime.

Message queue consumer (KEDA with SQS trigger)

An SQS consumer scaled on queue depth. With HPA (CPU 70 %) the queue grew to 50 000 messages because CPU remained low. Replacing HPA with a KEDA ScaledObject that watches aws_sqs_queue_messages_visible (threshold 100 messages → 1 replica) kept the queue empty and allowed scaling to zero when idle.

HPA + VPA conflict (pod thrashing)

Deploying HPA (CPU 70 %) together with VPA in Auto mode caused VPA to raise CPU requests, which lowered the utilization percentage and triggered HPA to scale down, creating a feedback loop. Switching VPA to Off mode (or limiting VPA to Memory only) resolved the thrashing.

Best‑practice matrix

Stateless Web API – use HPA (CPU + custom RPS metric) with aggressive scale‑up and conservative scale‑down.

Message consumer – use KEDA with a queue‑depth trigger; supports scale‑to‑zero.

Stateful single instance – use VPA Auto (or Off with manual adjustments) for resource optimization.

Mixed workloads – combine HPA for real‑time scaling with VPA Off for periodic recommendation updates.

Flash‑sale / scheduled traffic – use KEDA cron trigger together with HPA; pre‑increase minReplicas during the event window.

GPU inference – use VPA Off for profiling; adjust requests manually.

Batch workers – use HPA with an external metric (e.g., queue length) or KEDA to enable scale‑to‑zero.

Full microservice fleet – HPA + VPA Off + Cluster Autoscaler (three‑layer autoscaling chain).

HPA parameter tuning guide

Conservative profile (core transaction paths)

behavior:
  scaleUp:
    stabilizationWindowSeconds: 30
    policies:
    - type: Pods
      value: 2
      periodSeconds: 60
  scaleDown:
    stabilizationWindowSeconds: 600
    policies:
    - type: Pods
      value: 1
      periodSeconds: 120

Aggressive profile (flash sales)

behavior:
  scaleUp:
    stabilizationWindowSeconds: 0
    policies:
    - type: Percent
      value: 300
      periodSeconds: 15
    selectPolicy: Max
  scaleDown:
    stabilizationWindowSeconds: 900
    policies:
    - type: Percent
      value: 5
      periodSeconds: 120

Balanced profile (daily operations)

behavior:
  scaleUp:
    stabilizationWindowSeconds: 0
    policies:
    - type: Percent
      value: 100
      periodSeconds: 30
    - type: Pods
      value: 4
      periodSeconds: 30
    selectPolicy: Max
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
    - type: Percent
      value: 10
      periodSeconds: 60

Monitoring and alerts

Prometheus alert rules (excerpt):

# HPA reached maxReplicas
- alert: HPAMaxedOut
  expr: kube_horizontalpodautoscaler_status_current_replicas == kube_horizontalpodautoscaler_spec_max_replicas
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: "HPA {{ $labels.horizontalpodautoscaler }} has reached max replicas"
    description: "Namespace {{ $labels.namespace }} HPA {{ $labels.horizontalpodautoscaler }} has been at max replicas for >10m. Consider increasing maxReplicas or optimizing performance."

# HPA utilization >130 % of target
- alert: HPAHighUtilization
  expr: kube_horizontalpodautoscaler_status_target_metric / kube_horizontalpodautoscaler_spec_target_metric > 1.3
  for: 15m
  labels:
    severity: warning
  annotations:
    summary: "HPA {{ $labels.horizontalpodautoscaler }} utilization >130 % of target"
    description: "Consider increasing resources or maxReplicas."

# VPA recommendation drift
- alert: VPARecommendationDrift
  expr: (vpa_recommendation_target{resource="cpu"} / kube_pod_container_resource_requests{resource="cpu"} > 2) or (kube_pod_container_resource_requests{resource="cpu"} / vpa_recommendation_target{resource="cpu"} > 3)
  for: 1h
  labels:
    severity: info
  annotations:
    summary: "Pod {{ $labels.pod }} CPU request deviates >2× from VPA recommendation"

Conclusion

HPA is the primary mechanism for handling sudden traffic spikes on stateless services; proper behavior settings can achieve scaling within 30‑60 s.

VPA excels at long‑term resource profiling; use Off mode together with HPA for optimal efficiency without service interruption.

Business‑metric‑driven scaling (Prometheus Adapter or KEDA) provides more precise scaling for I/O‑bound or event‑driven workloads.

Never let HPA and VPA control the same resource dimension simultaneously – this creates feedback loops and pod thrashing.

Cluster Autoscaler is the downstream engine that provisions nodes for new Pods; expect 3‑8 min from HPA decision to a ready Pod in a cold cluster.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

cloud-nativeKubernetesperformance-testingautoscalingHPAVPAKEDA
Raymond Ops
Written by

Raymond Ops

Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.