Pages

Monday, 5 January 2026

Kubernetes ReplicaSets

 


A ReplicaSet is a Kubernetes object that ensures a specified number of identical pod replicas are running at any given time. It's a fundamental component for maintaining application availability and scalability.

Key Functions


A ReplicaSet continuously monitors your pods and takes action if the actual number differs from the desired number:
  • If pods crash or are deleted, it creates new ones to replace them
  • If there are too many pods, it terminates the excess ones
  • This self-healing behavior keeps your application running reliably

How It Works


You define a ReplicaSet with three main components:
  • Selector: Labels used to identify which pods belong to this ReplicaSet
  • Replicas: The desired number of pod copies
  • Pod template: The specification for creating new pods when needed

Example:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-app-replicaset
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: nginx:1.14

This ReplicaSet ensures 3 nginx pods are always running with the label app: my-app.



What is the relation between replicaset and deployment?


While ReplicaSets are still used internally by Kubernetes, you typically don't create them directly. Instead, you use Deployments, which manage ReplicaSets for you and provide additional features like rolling updates, rollbacks, and version history. Deployments are the recommended way to manage replicated applications in Kubernetes.

A Deployment is a higher-level Kubernetes object that manages ReplicaSets for you. Think of it as a wrapper that adds intelligent update capabilities on top of ReplicaSets.


The Relationship

When you create a Deployment, Kubernetes automatically creates a ReplicaSet underneath it. The Deployment controls this ReplicaSet to maintain your desired number of pods.
The key difference becomes apparent when you update your application:

With just a ReplicaSet: If you want to update your application (like changing the container image), you'd need to manually delete the old ReplicaSet and create a new one. This causes downtime.

With a Deployment: When you update the pod template, the Deployment intelligently manages the transition by:
  1. Creating a new ReplicaSet with the updated pod specification
  2. Gradually scaling up the new ReplicaSet while scaling down the old one
  3. Keeping both ReplicaSets around for rollback capability

Visual Example

Deployment: my-app
    │
    ├── ReplicaSet: my-app-abc123 (old version, scaled to 0)
    │
    └── ReplicaSet: my-app-xyz789 (current version, 3 replicas)
        ├── Pod: my-app-xyz789-1
        ├── Pod: my-app-xyz789-2
        └── Pod: my-app-xyz789-3

What Deployment Adds

  • Rolling updates: Gradual replacement of old pods with new ones
  • Rollback: Easy reversion to previous versions
  • Update strategies: Control how updates happen (RollingUpdate, Recreate)
  • Revision history: Track changes over time
  • Pause/resume: Control when updates are applied

In Practice


You almost always use Deployments rather than creating ReplicaSets directly. The Deployment handles the ReplicaSet management complexity, and you just declare what you want your application to look like.



Why is there many old ReplicaSets in my cluster? 


% kubectl get replicaset  -n staging | grep my-app-staging
my-app-staging-545f64d64b                   0         0         0       46d
my-app-staging-57897b6496                   0         0         0       131d
my-app-staging-57979c66c                    0         0         0       186d
my-app-staging-5974fd86f9                   0         0         0       185d
my-app-staging-5f9fbdf898                   0         0         0       173d
my-app-staging-6754c468                     0         0         0       185d
my-app-staging-695469db68                   0         0         0       144d
my-app-staging-6cd7d77789                   0         0         0       185d
my-app-staging-6f5cc5b6cf                   0         0         0       185d
my-app-staging-76f5bf4bf5                   0         0         0       186d
my-app-staging-d9c7895d9                    5         5         5       27d


This is completely normal Kubernetes behaviour — and the reason is almost always revisionHistoryLimit (or the default value of it).


Why there are many old ReplicaSets

Every time a Deployment’s pod template changes, Kubernetes:
  • Creates a new ReplicaSet
  • Scales the old one down to 0
  • Keeps the old ReplicaSet for rollback purposes

Examples of changes that trigger a new ReplicaSet:
  • Image tag change
  • Env var change
  • ConfigMap checksum change
  • Resource requests/limits change
  • Annotation change on the pod template
  • Helm re-deploy with different values

👉 Over time, this naturally accumulates ReplicaSets like the ones you see.

Why they are so old (46–186 days)

Because Kubernetes never deletes them automatically unless told to.

By default:

revisionHistoryLimit: 10


If:
  • revisionHistoryLimit is unset
  • or explicitly set high
  • or Helm chart doesn’t define it

...Kubernetes will happily keep many old ReplicaSets forever.

Your output strongly suggests:
  • Multiple deployments over months
  • Each one created a new ReplicaSet
  • All old ones were scaled to 0
  • Only the newest one is active:
            my-app-staging-d9c7895d9   5/5   27d   ← current

Why this is not usually a problem

Old ReplicaSets with 0 replicas:
  • Consume almost no resources
  • Do not schedule pods
  • Exist mainly as metadata
So:
  • Performance impact → negligible
  • Scheduler impact → none

When it does become a problem

It’s worth cleaning up if:
  • You have hundreds or thousands of old ReplicaSets
  • kubectl get rs becomes noisy
  • GitOps / audits become painful
  • You accidentally roll back to a very old revision
  • etcd size is a concern (rare, but real at scale)

The right fix: limit revision history

Set this on the Deployment:

spec:
  revisionHistoryLimit: 3


or (Helm values example):

revisionHistoryLimit: 3


This means:
  • Kubernetes keeps only the last 3 old ReplicaSets
  • Older ones are automatically deleted

Typical values:
  • 2–3 for staging
  • 5–10 for prod (depending on rollback needs)

How to confirm current setting

kubectl get deployment my-app-staging -n staging -o yaml | grep revisionHistoryLimit


If nothing shows → default behaviour applies.

Can you safely delete the old ones manually?

Yes — as long as they’re at 0 replicas.

Example:

kubectl delete rs my-app-staging-545f64d64b -n staging


But:
  • This is a one-off cleanup
  • Without fixing revisionHistoryLimit, they’ll come back

TL;DR

  • Many old ReplicaSets is normal
  • They exist for rollback history
  • They’re old because Kubernetes keeps them indefinitely
  • Fix it with revisionHistoryLimit
  • Manual deletion is safe but not a long-term solution


No comments:

Post a Comment