Question 13 · Section 14

What is ReplicaSet?

In practice, ReplicaSet is rarely created directly — Deployment creates it. Deployment manages the ReplicaSet, and the ReplicaSet manages Pods.

Language versions: English Russian Ukrainian

Junior Level

Simple Explanation

ReplicaSet (RS) is a Kubernetes controller that guarantees a specified number of Pod replicas are always running. If a Pod crashes — the ReplicaSet launches a new one.

In practice, ReplicaSet is rarely created directly — Deployment creates it. Deployment manages the ReplicaSet, and the ReplicaSet manages Pods.

Simple Analogy

A ReplicaSet is like a store manager who ensures the right number of cashiers are always at the registers. If one goes on break — the manager calls another.

How Does a ReplicaSet Work?

  1. You say: “I need 3 copies of the application”
  2. ReplicaSet checks: “How many are running now?”
  3. If less than 3 — launches new Pods
  4. If more than 3 — removes extra ones
  5. Repeats constantly (Reconciliation Loop)

Example

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs
spec:
  replicas: 3              # I want 3 copies
  selector:
    matchLabels:
      app: myapp           # Finds Pods with this label
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:1.0

ReplicaSet vs Deployment

ReplicaSet vs Deployment: ReplicaSet guarantees N Pod copies. Deployment adds rolling updates, rollback, revision history. In 99% of cases, use Deployment.

In reality you almost never create a ReplicaSet manually. Instead you use Deployment — it manages ReplicaSets for you.

Deployment adds:

  • Rolling updates (update without downtime)
  • Rollback (revert to previous version)
  • Version history

What a Junior Developer Should Remember

  • ReplicaSet maintains the desired number of Pods
  • If a Pod crashes — ReplicaSet creates a new one
  • In production use Deployment, not ReplicaSet
  • Deployment manages ReplicaSets
  • Label selectors link ReplicaSet to Pods

Middle Level

Reconciliation Loop

ReplicaSet works on an infinite loop principle:

1. Read desired replicas from spec.replicas
2. Count current Pods by selector
3. If less than desired → create Pods
4. If more than desired → delete Pods
5. Wait and repeat

This loop provides self-healing: no matter how many Pods crash, the ReplicaSet always strives toward the desired state.

Relationship with Deployment

Deployment
    ↓ manages
ReplicaSet v1 (image: myapp:1.0, replicas: 0)  ← old version
ReplicaSet v2 (image: myapp:2.0, replicas: 3)  ← current version
    ↓ manages
Pod × 3

When updating a Deployment:

  1. Creates a new ReplicaSet with the new image
  2. Gradually moves Pods from the old RS to the new one
  3. Old RS is preserved for rollback

Selectors

ReplicaSet uses set-based selectors:

selector:
  matchLabels:
    app: myapp
    env: production

# Or more complex:
selector:
  matchExpressions:
  - key: app
    operator: In
    values: [myapp, myapp-v2]
  - key: env
    operator: NotIn
    values: [development]

ownerReference

Each Pod has a reference to its ReplicaSet:

metadata:
  ownerReferences:
  - apiVersion: apps/v1
    kind: ReplicaSet
    name: myapp-rs-abc123
    uid: ...

This allows K8s to automatically delete Pods when the ReplicaSet is deleted.

Why Not ReplicationController?

ReplicationController is a legacy object. ReplicaSet differs by supporting set-based selectors with In, NotIn, Exists operators.

What a Middle Developer Should Remember

  • ReplicaSet = mechanism for maintaining replica count
  • Reconciliation Loop constantly compares desired vs actual
  • Deployment manages ReplicaSets for rolling updates
  • Set-based selectors are more powerful than simple matchLabels
  • ownerReference ensures cascading deletion

Senior Level

ReplicaSet as a Fault Tolerance Primitive

ReplicaSet is a low-level controller that implements Kubernetes’ fundamental pattern: declarative state reconciliation.

ReplicaSet Controller Architecture

kube-controller-manager
    └── replicaset-controller
            ├── Watch ReplicaSet changes
            ├── Watch Pod changes
            ├── Sync: compare desired vs actual
            ├── Scale up: create Pods
            └── Scale down: delete Pods

Controller subscribes to events:

  • ReplicaSet creation/modification
  • Pod deletion (to replace them)
  • Pod changes matching the selector

Pod Disruption and ReplicaSet

During kubectl drain or node eviction:

  1. Pods are marked for deletion
  2. ReplicaSet sees a decrease in Pod count
  3. Creates new Pods on other Nodes
  4. drain completes, old Pods removed

Overlapping Selectors: Danger

# ReplicaSet A
selector:
  matchLabels:
    app: myapp
    tier: frontend

# ReplicaSet B
selector:
  matchLabels:
    app: myapp

If a Pod has labels app: myapp, tier: frontend, both RS may try to manage it. This leads to undefined behavior.

Protection: Kubernetes doesn’t prevent overlapping selectors — responsibility is on the engineer.

Adoption of Existing Pods

A ReplicaSet can “adopt” already existing Pods:

# Pod created manually
kubectl run myapp --image=myapp:1.0 --labels=app=myapp

# Create RS with the same selector
# RS "sees" the existing Pod and adopts it

This is used when migrating from manual Pods to Deployment.

Scaling a ReplicaSet

# Imperative
kubectl scale rs myapp-rs --replicas=5

# Via kubectl edit
kubectl edit rs myapp-rs

# Via patch
kubectl patch rs myapp-rs -p '{"spec":{"replicas":5}}'

When to Create a ReplicaSet Directly?

Almost never. The only scenarios:

  1. Learning/understanding K8s internals
  2. Custom controllers (based on ReplicaSet logic)
  3. Specific use cases where Deployment doesn’t fit

Troubleshooting

Pods aren’t created:

kubectl describe rs myapp-rs
# Events: Normal  SuccessfulCreate  pod/myapp-xyz created
# Warning FailedCreate      error creating pods

Too many Pods:

  • Check for overlapping selectors
  • Check if another controller is creating Pods

Pods aren’t deleted:

  • Check PodDisruptionBudget
  • Check finalizers on Pods

Summary for Senior

  • ReplicaSet guarantees N copies of the application.
  • It’s a low-level mechanism managed by Deployment.
  • Reconciliation Loop — fundamental K8s pattern.
  • RS can’t update images — that’s Deployment logic.
  • Overlapping selectors → undefined behavior.
  • ownerReference ensures cascading deletion.
  • Use labels carefully so RS doesn’t accidentally delete someone else’s Pods.

Interview Cheat Sheet

Must know:

  • ReplicaSet guarantees the specified number of Pod replicas (reconciliation loop)
  • In 99% of cases use Deployment, not ReplicaSet directly
  • Deployment manages ReplicaSets for rolling updates and rollback
  • Reconciliation Loop: desired vs actual → create/delete Pods → repeat
  • ownerReference ensures cascading Pod deletion when RS is deleted
  • Overlapping selectors → undefined behavior (two RS compete)
  • ReplicationController is legacy; ReplicaSet supports set-based selectors

Frequent follow-up questions:

  • “Why ReplicaSet if there’s Deployment?” — Deployment is a high-level abstraction; RS is the mechanism under the hood
  • “What happens if you delete a ReplicaSet?” — All Pods are deleted (ownerReference cascade)
  • “Can RS update images?” — No, that’s Deployment logic
  • “Can RS adopt existing Pods?” — Yes, if the Pod matches the selector (adoption)

Red flags (DO NOT say):

  • “I create ReplicaSet directly in production” (use Deployment)
  • “ReplicaSet does rolling updates” (that’s Deployment)
  • “Overlapping selectors aren’t a problem” (leads to race conditions)
  • “ReplicationController is the modern standard” (deprecated, use ReplicaSet)

Related topics:

  • [[What is Kubernetes and why is it needed]] — K8s controllers
  • [[How to organize rolling update in Kubernetes]] — Deployment + RS
  • [[How scaling works in Kubernetes]] — replica scaling