Learn Kubernetes in 10 DaysDay 9: Scaling and Update Strategies
books.chapter 9Learn Kubernetes in 10 Days

Day 9: Scaling and Update Strategies

What You'll Learn Today

  • Horizontal Pod Autoscaler (HPA) for automatic scaling
  • Vertical Pod Autoscaler (VPA) overview
  • Blue/Green and Canary deployment strategies
  • StatefulSet basics

Automatic Scaling

In Day 4, you learned manual scaling with kubectl scale. Kubernetes also provides automatic Pod count adjustment based on load.

flowchart TB
    subgraph Scaling["Scaling Types"]
        HPA["Horizontal Pod Autoscaler\n(adjust Pod count)"]
        VPA["Vertical Pod Autoscaler\n(adjust resource amounts)"]
        CA["Cluster Autoscaler\n(adjust node count)"]
    end
    style HPA fill:#3b82f6,color:#fff
    style VPA fill:#8b5cf6,color:#fff
    style CA fill:#22c55e,color:#fff
Type Target Description
HPA Pod count Adjusts replicas based on CPU/memory usage
VPA Resource amounts Adjusts Pod requests/limits automatically
Cluster Autoscaler Node count Adjusts cluster node count (cloud environments)

Horizontal Pod Autoscaler (HPA)

HPA automatically scales Deployment replicas based on CPU utilization or custom metrics.

Prerequisites: Metrics Server

# Verify Metrics Server
kubectl top nodes
kubectl top pods

# For Minikube
minikube addons enable metrics-server

Creating an HPA

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 70
# Or create via command
kubectl autoscale deployment web-app \
  --min=2 --max=10 --cpu-percent=50

How HPA Works

flowchart LR
    MS["Metrics Server"] -->|"collect metrics"| HPA["HPA"]
    HPA -->|"CPU > 50%"| UP["Scale Up\n(increase Pods)"]
    HPA -->|"CPU < 50%"| DOWN["Scale Down\n(decrease Pods)"]
    UP --> DEP["Deployment"]
    DOWN --> DEP
    style HPA fill:#3b82f6,color:#fff
    style UP fill:#22c55e,color:#fff
    style DOWN fill:#f59e0b,color:#fff

Testing HPA

# Check HPA status
kubectl get hpa
# NAME      REFERENCE           TARGETS   MINPODS   MAXPODS   REPLICAS
# web-hpa   Deployment/web-app  10%/50%   2         10        2

# Generate load
kubectl run load-test --image=busybox:1.37 --rm -it -- \
  /bin/sh -c "while true; do wget -q -O- http://web-service; done"

# Watch HPA in another terminal
kubectl get hpa -w

HPA Parameters

Parameter Description
minReplicas Minimum replica count
maxReplicas Maximum replica count
averageUtilization Target usage percentage
scaleDown.stabilizationWindowSeconds Cooldown before scale-down (default 300s)

Deployments using HPA must have resources.requests set on their Pods.


Update Strategies

Beyond the rolling update from Day 4, there are several deployment strategies.

1. Recreate

Stops all Pods before starting new ones. Causes downtime.

spec:
  strategy:
    type: Recreate

2. Rolling Update

Gradual Pod replacement (default). Covered in Day 4.

3. Blue/Green Deployment

Not a native Kubernetes feature, but achievable using Service label selectors and Deployments.

flowchart TB
    SVC["Service\nselector: version=green"]
    subgraph Blue["Blue (old version)"]
        B1["Pod v1"]
        B2["Pod v1"]
    end
    subgraph Green["Green (new version)"]
        G1["Pod v2"]
        G2["Pod v2"]
    end
    SVC -->|"switch"| Green
    style Blue fill:#3b82f6,color:#fff
    style Green fill:#22c55e,color:#fff
    style SVC fill:#8b5cf6,color:#fff
# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: blue
  template:
    metadata:
      labels:
        app: myapp
        version: blue
    spec:
      containers:
        - name: app
          image: myapp:1.0
---
# green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: green
  template:
    metadata:
      labels:
        app: myapp
        version: green
    spec:
      containers:
        - name: app
          image: myapp:2.0
---
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: app-service
spec:
  selector:
    app: myapp
    version: blue  # Change to green to switch
  ports:
    - port: 80
# Switch Blue β†’ Green
kubectl patch service app-service -p '{"spec":{"selector":{"version":"green"}}}'

# Rollback to Blue
kubectl patch service app-service -p '{"spec":{"selector":{"version":"blue"}}}'

4. Canary Deployment

Deploy the new version to a small subset of Pods for testing, then gradually expand.

flowchart TB
    SVC["Service\nselector: app=myapp"]
    subgraph Stable["Stable (90%)"]
        S1["Pod v1"]
        S2["Pod v1"]
        S3["Pod v1"]
        S4["Pod v1"]
        S5["Pod v1"]
        S6["Pod v1"]
        S7["Pod v1"]
        S8["Pod v1"]
        S9["Pod v1"]
    end
    subgraph Canary["Canary (10%)"]
        C1["Pod v2"]
    end
    SVC --> Stable
    SVC --> Canary
    style Stable fill:#3b82f6,color:#fff
    style Canary fill:#f59e0b,color:#fff
# stable-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-stable
spec:
  replicas: 9
  selector:
    matchLabels:
      app: myapp
      track: stable
  template:
    metadata:
      labels:
        app: myapp
        track: stable
    spec:
      containers:
        - name: app
          image: myapp:1.0
---
# canary-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      track: canary
  template:
    metadata:
      labels:
        app: myapp
        track: canary
    spec:
      containers:
        - name: app
          image: myapp:2.0
---
# service.yaml (routes to both)
apiVersion: v1
kind: Service
metadata:
  name: app-service
spec:
  selector:
    app: myapp  # No track specified β†’ routes to both
  ports:
    - port: 80

Strategy Comparison

Strategy Downtime Rollback Resources Complexity
Recreate Yes Slow Low Low
Rolling Update No Automatic Medium Low
Blue/Green No Instant Double Medium
Canary No Instant Slightly more High

StatefulSet

Deployments are for stateless applications. For stateful applications like databases and message queues, use StatefulSets.

Deployment vs. StatefulSet

Property Deployment StatefulSet
Pod names Random (app-7f8b-abc) Sequential (app-0, app-1, app-2)
Startup order Parallel Sequential (0 β†’ 1 β†’ 2)
Storage Shared PVC Per-Pod PVC
Network Random IP Stable DNS names

StatefulSet Example

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres-headless
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:17
          ports:
            - containerPort: 5432
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
  name: postgres-headless
spec:
  clusterIP: None
  selector:
    app: postgres
  ports:
    - port: 5432

StatefulSet Pods get stable DNS names:

  • postgres-0.postgres-headless.default.svc.cluster.local
  • postgres-1.postgres-headless.default.svc.cluster.local
  • postgres-2.postgres-headless.default.svc.cluster.local

Summary

Concept Description
HPA Automatic Pod scaling based on CPU/memory
VPA Automatic Pod resource adjustment
Blue/Green Switch between two environments instantly
Canary Gradually roll out new version to a subset of Pods
StatefulSet Controller for stateful applications

Key Takeaways

  1. HPA automatically adjusts Pod count based on load. resources.requests is required
  2. Blue/Green enables instant switching; Canary enables gradual rollouts
  3. Use StatefulSets for stateful applications like databases

Practice Exercises

Exercise 1: HPA

Configure HPA for a web Deployment. Scale between 2-8 Pods at 50% CPU utilization.

Exercise 2: Blue/Green

Implement Blue/Green deployment with two app versions (nginx:1.26 and nginx:1.27). Practice switching the Service.

Challenge

Set up a 3-node Redis cluster using StatefulSet with per-Pod PVCs and stable DNS names.


References


Next up: In Day 10, you'll learn about "Production Readiness and Best Practices" β€” Namespaces, RBAC, resource management, monitoring, and comprehensive production best practices.