Learn Kubernetes in 10 DaysDay 4: ReplicaSets and Deployments

Day 4: ReplicaSets and Deployments

What You'll Learn Today

  • How ReplicaSets maintain Pod redundancy
  • Managing applications with Deployments
  • Rolling updates and rollbacks
  • Basic scaling operations

Why Not Create Pods Directly?

In Day 3, we created Pods directly. In production, you almost never do this.

Problem Description
Single point of failure One Pod means service outage on failure
No self-healing Directly created Pods don't come back when deleted
No scaling Must manually create Pods one by one
Difficult updates Application updates cause downtime

ReplicaSets and Deployments solve these problems.

flowchart TB
    DEP["Deployment"] --> RS["ReplicaSet"]
    RS --> P1["Pod 1"]
    RS --> P2["Pod 2"]
    RS --> P3["Pod 3"]
    style DEP fill:#8b5cf6,color:#fff
    style RS fill:#3b82f6,color:#fff
    style P1 fill:#22c55e,color:#fff
    style P2 fill:#22c55e,color:#fff
    style P3 fill:#22c55e,color:#fff

ReplicaSet

A ReplicaSet ensures a specified number of Pod replicas are always running.

How ReplicaSets Work

flowchart LR
    RS["ReplicaSet\nreplicas: 3"] -->|"monitor"| CHECK{"Current Pod count?"}
    CHECK -->|"2 (too few)"| CREATE["Create 1 Pod"]
    CHECK -->|"3 (correct)"| OK["Do nothing"]
    CHECK -->|"4 (too many)"| DELETE["Delete 1 Pod"]
    CREATE --> RS
    OK --> RS
    DELETE --> RS
    style RS fill:#3b82f6,color:#fff
    style CREATE fill:#22c55e,color:#fff
    style DELETE fill:#ef4444,color:#fff

ReplicaSet YAML

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: web-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27
          ports:
            - containerPort: 80
Field Description
replicas Number of Pods to maintain
selector Label selector to identify managed Pods
template Template for creating Pods

Important: selector.matchLabels and template.metadata.labels must match.

Self-Healing in Action

# Create ReplicaSet
kubectl apply -f web-rs.yaml

# Check Pods (3 running)
kubectl get pods

# Delete one Pod
kubectl delete pod web-rs-abc12

# A new Pod is created immediately!
kubectl get pods
# web-rs-xyz78 appears with AGE: 5s

Deployment

In practice, you use Deployments instead of creating ReplicaSets directly. Deployments manage ReplicaSets and provide rolling updates and rollbacks.

Deployment YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "250m"
              memory: "256Mi"

Creating and Verifying

# Create Deployment
kubectl apply -f web-deployment.yaml

# Check Deployments
kubectl get deployments

# ReplicaSet is auto-created
kubectl get replicasets

# 3 Pods running
kubectl get pods
flowchart TB
    D["Deployment\nweb-deployment"] --> RS["ReplicaSet\nweb-deployment-7f8b9c6d4"]
    RS --> P1["Pod\nweb-deployment-7f8b9c6d4-abc12"]
    RS --> P2["Pod\nweb-deployment-7f8b9c6d4-def34"]
    RS --> P3["Pod\nweb-deployment-7f8b9c6d4-ghi56"]
    style D fill:#8b5cf6,color:#fff
    style RS fill:#3b82f6,color:#fff

Rolling Updates

The biggest advantage of Deployments is zero-downtime application updates.

Performing an Update

# Update the image
kubectl set image deployment/web-deployment web=nginx:1.27-alpine

# Or edit YAML and apply
kubectl apply -f web-deployment.yaml

# Watch the rollout progress
kubectl rollout status deployment/web-deployment

Rolling Update Flow

flowchart TB
    subgraph Step1["Step 1"]
        RS1a["Old ReplicaSet\n(3 Pods)"]
        RS2a["New ReplicaSet\n(0 Pods)"]
    end
    subgraph Step2["Step 2"]
        RS1b["Old ReplicaSet\n(2 Pods)"]
        RS2b["New ReplicaSet\n(1 Pod)"]
    end
    subgraph Step3["Step 3"]
        RS1c["Old ReplicaSet\n(1 Pod)"]
        RS2c["New ReplicaSet\n(2 Pods)"]
    end
    subgraph Step4["Step 4"]
        RS1d["Old ReplicaSet\n(0 Pods)"]
        RS2d["New ReplicaSet\n(3 Pods)"]
    end
    Step1 --> Step2 --> Step3 --> Step4
    style RS1a fill:#f59e0b,color:#fff
    style RS1b fill:#f59e0b,color:#fff
    style RS1c fill:#f59e0b,color:#fff
    style RS1d fill:#f59e0b,color:#fff
    style RS2a fill:#22c55e,color:#fff
    style RS2b fill:#22c55e,color:#fff
    style RS2c fill:#22c55e,color:#fff
    style RS2d fill:#22c55e,color:#fff

Update Strategy Configuration

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1        # Extra Pods allowed during update
      maxUnavailable: 1  # Pods that can be unavailable during update
Parameter Description Default
maxSurge Pods allowed beyond replicas (count or %) 25%
maxUnavailable Pods that can be unavailable (count or %) 25%

Rollbacks

If an update causes issues, easily revert to a previous version.

# View rollout history
kubectl rollout history deployment/web-deployment

# Details of a specific revision
kubectl rollout history deployment/web-deployment --revision=2

# Rollback to previous version
kubectl rollout undo deployment/web-deployment

# Rollback to specific revision
kubectl rollout undo deployment/web-deployment --to-revision=1

# Pause/resume rollout
kubectl rollout pause deployment/web-deployment
kubectl rollout resume deployment/web-deployment

Scaling

Manual Scaling

# Change replica count
kubectl scale deployment/web-deployment --replicas=5

# Verify
kubectl get deployment web-deployment

Scaling via YAML

spec:
  replicas: 5  # Changed from 3 to 5
kubectl apply -f web-deployment.yaml

Complete Deployment Example

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: web
        version: v1.0
    spec:
      containers:
        - name: web
          image: nginx:1.27
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "250m"
              memory: "256Mi"
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 3
            periodSeconds: 5
Setting Value Meaning
replicas: 3 3 Always maintain 3 Pods
maxSurge: 1 1 Allow up to 4 Pods during updates
maxUnavailable: 0 0 Zero downtime during updates

Summary

Concept Description
ReplicaSet Maintains a specified number of Pod replicas
Deployment Manages ReplicaSets with rolling updates and rollbacks
Rolling Update Gradually updates Pods for zero downtime
Rollback Reverts to a previous version when issues arise
Scaling Adjusts the number of Pod replicas

Key Takeaways

  1. In production, use Deployments instead of creating Pods directly
  2. Rolling updates enable zero-downtime application updates
  3. Setting maxUnavailable: 0 ensures service continuity during updates

Practice Exercises

Exercise 1: Basics

Create a Deployment YAML with:

  • Name: api-server
  • Image: node:20-alpine
  • Replicas: 3
  • CPU request: 200m, limit: 500m

Exercise 2: Updates

Update the Deployment image to node:22-alpine, watch the rollout, then perform a rollback.

Challenge

Compare the behavior of maxSurge: 0, maxUnavailable: 1 vs. maxSurge: 1, maxUnavailable: 0 during updates.


References


Next up: In Day 5, you'll learn about "Networking with Services" β€” managing Pod-to-Pod communication and external access through Services.