Skip to content

🎓 Mission Debrief: ReplicaSet Without Deployment

What Happened

You had a standalone ReplicaSet, which is a low-level Kubernetes resource that doesn't provide update management capabilities.

While ReplicaSets ensure the right number of pods are running, they don't handle: - Rolling updates - Rollbacks - Declarative version changes - Rollout history

Deployments are the recommended abstraction that manages ReplicaSets for you and provides all these features!

How Kubernetes Behaved

Standalone ReplicaSet (the problem):

You create: ReplicaSet (web-app-rs)
    ↓
ReplicaSet creates: 3 pods
    ↓
Pod crashes? ReplicaSet recreates it ✅
    ↓
Want to update image?
    ↓
Option 1: Edit ReplicaSet spec (pods don't update!) ❌
Option 2: Delete all pods manually (downtime!) ❌
Option 3: Create new ReplicaSet, delete old (manual work!) ❌
    ↓
No automatic rollouts, no rollback, manual management

Deployment (the solution):

You create: Deployment (web-app)
    ↓
Deployment creates: ReplicaSet-v1
    ↓
ReplicaSet-v1 creates: 3 pods (v1)
    ↓
You update: Change image in Deployment spec
    ↓
Deployment creates: ReplicaSet-v2
Deployment orchestrates:
  - Start new pods from ReplicaSet-v2
  - Gradually terminate pods from ReplicaSet-v1
  - Rolling update with zero downtime ✅
    ↓
Want to rollback?
    ↓
kubectl rollout undo deployment/web-app
    ↓
Deployment switches back to ReplicaSet-v1 ✅

The Correct Mental Model

Kubernetes Resource Hierarchy

┌─────────────────────────────────────┐
│         Deployment                   │  ← YOU manage this
│  (High-level, declarative)           │
│  - Rolling updates                   │
│  - Rollback                          │
│  - Version history                   │
└───────────────┬─────────────────────┘
                │ Creates & manages
                ↓
┌─────────────────────────────────────┐
│         ReplicaSet                   │  ← Deployment manages this
│  (Mid-level)                         │     (you don't touch it)
│  - Ensures N pods running            │
│  - Replaces crashed pods             │
└───────────────┬─────────────────────┘
                │ Creates & manages
                ↓
┌─────────────────────────────────────┐
│         Pods                         │  ← ReplicaSet manages this
│  (Low-level, ephemeral)              │     (you don't touch it)
│  - Runs containers                   │
└─────────────────────────────────────┘

Abstraction levels:

Resource Managed by You interact? Purpose
Deployment You ✅ YES Declarative updates, rollouts
ReplicaSet Deployment ❌ NO Maintain replica count
Pod ReplicaSet ❌ NO Run containers

What Happens During an Update

With standalone ReplicaSet:

1. You create ReplicaSet (v1)
   Pods: pod-abc, pod-xyz, pod-mno (all v1)

2. You want v2. Your options:

   Option A: Edit ReplicaSet spec
     kubectl set image replicaset/web-app-rs web=v2
     Result: ReplicaSet spec updated, but PODS STAY v1! ❌
     (ReplicaSet doesn't recreate pods for spec changes)

   Option B: Delete pods manually
     kubectl delete pod pod-abc pod-xyz pod-mno
     Result: ReplicaSet recreates with v2 ✅
     Problem: Complete downtime during recreation! ❌

   Option C: Create new ReplicaSet manually
     kubectl apply -f replicaset-v2.yaml
     Now you have TWO ReplicaSets (v1 and v2) running!
     You must manually delete the old one
     You must manually orchestrate rolling update
     Lots of manual work! ❌

With Deployment (automatic!):

1. You create Deployment (v1)
   Deployment creates: ReplicaSet-abc123 (v1)
   Pods: pod-abc, pod-xyz, pod-mno (all v1)

2. You want v2:
   kubectl set image deployment/web-app web=v2

   Deployment automatically:
   - Creates ReplicaSet-xyz789 (v2)
   - Starts 1 pod from RS-xyz789
   - Waits for it to be ready
   - Terminates 1 pod from RS-abc123
   - Repeats until all pods are v2
   - Keeps RS-abc123 for rollback (scaled to 0)

   Result: Zero-downtime rolling update! ✅

3. Want to rollback?
   kubectl rollout undo deployment/web-app

   Deployment automatically:
   - Scales up RS-abc123 (v1) again
   - Scales down RS-xyz789 (v2)

   Result: Instant rollback! ✅

Deployment Manages ReplicaSet Versions

After 3 deployments:

kubectl get replicasets
NAME                DESIRED   CURRENT   READY
web-app-7d8f9c      0         0         0      # v1 (old, kept for history)
web-app-6c5b8d      0         0         0      # v2 (old, kept for history)
web-app-5a4e7f      3         3         3      # v3 (current, active)
                    ↑ Current version has replicas
                    ↑ Old versions kept at 0 for quick rollback

Real-World Incident Example

Company: E-commerce startup (Series A, 50K daily users) Impact: 2-hour downtime during critical product launch Cost: $200K in lost sales + failed launch event

What happened:

A junior DevOps engineer was tasked with deploying the new product catalog service. They found an example of a ReplicaSet in a tutorial and used it.

Initial deployment (worked fine):

apiVersion: apps/v1
kind: ReplicaSet  # ❌ Should have used Deployment
metadata:
  name: catalog-v1
spec:
  replicas: 10
  selector:
    matchLabels:
      app: catalog
  template:
    metadata:
      labels:
        app: catalog
    spec:
      containers:
      - name: catalog
        image: catalog:1.0

Service was running fine for 2 weeks.

The incident (product launch day):

10:00 AM - Product launch event starts (press, customers, investors)
10:00 AM - Marketing drives massive traffic to site
10:15 AM - Critical bug discovered in catalog service (wrong pricing!)
10:15 AM - Emergency fix developed (catalog:1.0.1)
10:20 AM - DevOps tries to update:
           kubectl set image replicaset/catalog-v1 catalog=catalog:1.0.1
10:20 AM - Command succeeds ✅
10:21 AM - DevOps checks: kubectl get pods
           Pods still running catalog:1.0 ❌
10:21 AM - "Why didn't it update??"
10:25 AM - Realizes: ReplicaSet doesn't update existing pods!
10:25 AM - Decision: Delete all pods, let ReplicaSet recreate
10:26 AM - kubectl delete pods -l app=catalog
10:26 AM - ALL 10 catalog pods deleted
10:26 AM - Site shows "Catalog Unavailable" for ALL users
10:27 AM - ReplicaSet starts creating new pods
10:28 AM - Pods starting up (30-second initialization)
10:29 AM - First pods ready
10:31 AM - All 10 pods ready
10:31 AM - Service restored
           But 5 minutes of complete downtime during launch event! ❌
11:00 AM - Another bug found (!)
11:00 AM - Team hesitant to update (last update caused downtime)
11:15 AM - Finally update (catalog:1.0.2)
11:15 AM - Again: Delete all pods → downtime
11:20 AM - Service back
12:00 PM - Launch event ends
12:00 PM - Post-mortem: "Why do we have downtime on every update??"

Why it was catastrophic: - Product launch event - Press, investors, customers watching - Multiple updates needed - Bugs found during high-visibility event - Downtime every update - 5 minutes each time - Manual process - Delete pods, wait for recreation - No rollback - Had to fix forward (couldn't rollback to v1.0) - Reputation damage - "Unreliable platform" perception

What users experienced:

10:00 - Excited for launch
10:26 - "Catalog Unavailable" error
10:27 - Social media complaints start
10:31 - Site back up
11:15 - "Catalog Unavailable" AGAIN
11:20 - "Is this company even ready for production?"

Root cause: 1. Using ReplicaSet instead of Deployment - No rolling update capability 2. No testing of update process - Never practiced updating in staging 3. Knowledge gap - Engineer didn't know ReplicaSets vs Deployments 4. No rollback plan - Couldn't revert to working version quickly

The fix:

# Convert to Deployment
apiVersion: apps/v1
kind: Deployment  # ✅ CORRECT
metadata:
  name: catalog
spec:
  replicas: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1  # Keep 9 pods running during update
      maxSurge: 2        # Can create 2 extra pods
  selector:
    matchLabels:
      app: catalog
  template:
    metadata:
      labels:
        app: catalog
    spec:
      containers:
      - name: catalog
        image: catalog:1.0.2
        readinessProbe:  # ✅ Added
          httpGet:
            path: /healthz
            port: 8080

Post-incident actions: 1. Training - Team learned Deployment vs ReplicaSet 2. Linting - CI/CD rejects standalone ReplicaSets 3. Testing - Practice deployments in staging 4. Documentation - "Never use ReplicaSets directly" rule 5. Monitoring - Alert if ReplicaSets created without owning Deployment

Lessons learned: 1. Always use Deployments - Never create ReplicaSets directly 2. Test deployment process - Practice in staging before production 3. Use rolling updates - Zero-downtime deployments 4. Have rollback plan - kubectl rollout undo 5. Training matters - Ensure team knows best practices

Commands You Mastered

# Create Deployment (recommended)
kubectl create deployment web-app --image=myapp:v1 --replicas=3

# Update Deployment image (triggers rolling update)
kubectl set image deployment/web-app myapp=myapp:v2

# Check rollout status
kubectl rollout status deployment/web-app

# See rollout history
kubectl rollout history deployment/web-app

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

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

# Pause rollout (for testing canary)
kubectl rollout pause deployment/web-app

# Resume rollout
kubectl rollout resume deployment/web-app

# Check Deployment's ReplicaSets
kubectl get replicasets -l app=webapp

# Edit Deployment (declarative update)
kubectl edit deployment web-app

# Scale Deployment
kubectl scale deployment web-app --replicas=5

# DON'T do this (create standalone ReplicaSet)
kubectl create -f replicaset.yaml  # ❌ Use Deployment instead!

Best Practices

✅ DO:

  1. Always use Deployments (not ReplicaSets):

    kind: Deployment  # ✅
    

  2. Let Deployment manage ReplicaSets:

    # You manage Deployments
    kubectl create deployment ...
    
    # Deployment manages ReplicaSets (you don't touch them)
    

  3. Use declarative updates:

    # Update deployment.yaml
    kubectl apply -f deployment.yaml
    

  4. Configure rolling update strategy:

    strategy:
      type: RollingUpdate
      rollingUpdate:
        maxUnavailable: 1
        maxSurge: 1
    

  5. Use rollout commands:

    kubectl rollout status/history/undo deployment/<name>
    

❌ DON'T:

  1. Don't create standalone ReplicaSets:

    kind: ReplicaSet  # ❌ Use Deployment instead
    

  2. Don't manually edit ReplicaSets:

    # ❌ Don't do this
    kubectl edit replicaset web-app-abc123
    
    # ✅ Do this instead
    kubectl edit deployment web-app
    

  3. Don't delete Deployment's ReplicaSets:

    # ❌ Don't manually delete
    kubectl delete replicaset web-app-abc123
    
    # ✅ Let Deployment manage them
    

  4. Don't update pods directly:

    # ❌ Don't edit individual pods
    kubectl edit pod web-app-abc123-xyz
    
    # ✅ Update Deployment spec instead
    kubectl edit deployment web-app
    

When Would You Use ReplicaSet Directly?

Almost never!

The only rare cases: - Custom controllers - Building your own operator that needs to manage ReplicaSets - Learning/debugging - Understanding how Kubernetes works internally - Legacy systems - Maintaining very old configurations (migrate to Deployment!)

For 99.9% of use cases: Use Deployment!

Resource Comparison

Feature ReplicaSet Deployment
Maintains replica count ✅ ✅
Replaces crashed pods ✅ ✅
Rolling updates ❌ ✅
Rollback capability ❌ ✅
Update strategy config ❌ ✅
Rollout history ❌ ✅
Declarative updates ❌ ✅
Recommended for production ❌ ✅

Congratulations! 🎉

You've completed WORLD 2: Deployments & Scaling!

You've mastered: - Deployment rollbacks - Liveness and readiness probes - HorizontalPodAutoscaler - Rollout strategies - PodDisruptionBudgets - Blue-green deployments - Canary deployments - StatefulSets for stateful workloads - Why to use Deployments (not ReplicaSets)

Total XP earned in World 2: 2,000 XP Total career XP: 3,450 XP Levels completed: 20/50

Next up: World 3 - Networking & Services (Levels 21-30)

You'll learn: - Service types (ClusterIP, NodePort, LoadBalancer) - Ingress controllers - Network policies - DNS issues - Service mesh basics

Key takeaway: Deployments are the abstraction you should use. They manage ReplicaSets for you and provide rolling updates, rollbacks, and declarative management. Never create ReplicaSets directly!