Kubernetes
ReplicaSet & ReplicationController

Published: October 26, 2026 · 8 min read

Kubernetes ReplicaSet vs ReplicationController Explained

So far we created Pods by hand. That was fine for learning.

In a real cluster you never do that.

Here is the short version:

  • A Pod you create by hand has nobody watching it. It dies, it stays dead.
  • Always create Pods through a controller.
  • A ReplicationController keeps a fixed number of Pods running. It is the old one.
  • A ReplicaSet does the same job. It is the replacement.
  • Both replace any Pod that dies, and both let you scale up and down.
  • The real difference is the selector.
  • ReplicationController matches one value. ReplicaSet can match many.

Why you should never create a Kubernetes Pod by hand instead of using a ReplicaSet controller

The Problem With a Hand Made Pod

Run kubectl apply -f pod.yaml and you get one Pod. That is all you get.

Now the node fails. Or the container crashes badly. Or somebody runs kubectl delete pod.

The Pod is gone. Nothing brings it back. Your app is down until you notice and run the command again.

🚫

A Pod created by hand is a one off. Kubernetes does not remember that you wanted it.

You need something that remembers.

What a Controller Does

You stop telling Kubernetes "create this Pod".

You start telling it "always keep 3 of these Pods running".

That is the whole idea. You give a number, and something watches it forever.

How a Kubernetes ReplicaSet controller compares desired and current Pods and heals the difference

The controller holds two numbers:

  • desired — what you asked for
  • current — what is actually running

It compares them all the time. Different? It fixes the difference.

Too few Pods, it creates more. Too many, it deletes some. You never ask it to.

ReplicationController — The Old One

This is the original controller. It still works, and you should know it.

rc.yaml
# rc.yaml  -  the old way

apiVersion: v1
kind: ReplicationController
metadata:
  name: hotel-app-rc
spec:
  replicas: 3                     # how many Pods you want
  selector:                       # equality only
    app: hotel-app
  template:                       # the Pod to create
    metadata:
      labels:
        app: hotel-app
    spec:
      containers:
        - name: hotel-app
          image: srinudev645/hotel-app:v1
          ports:
            - containerPort: 8080

Three parts matter here:

FieldWhat it means
replicashow many Pods you want, always
selectorwhich Pods belong to it, matched by label
templatethe Pod to create when it needs one
terminal — create it
kubectl apply -f rc.yaml
# replicationcontroller/hotel-app-rc created

kubectl get rc
# NAME           DESIRED   CURRENT   READY   AGE
# hotel-app-rc   3         3         3       20s

kubectl get pods
# NAME                 READY   STATUS    RESTARTS   AGE
# hotel-app-rc-4xk2p   1/1     Running   0          20s
# hotel-app-rc-9mt7r   1/1     Running   0          20s
# hotel-app-rc-pz3wq   1/1     Running   0          20s

You asked for 3 and you got 3. Notice the Pod names: the controller added a random suffix to each.

Watch It Heal

Delete one Pod on purpose and see what happens.

terminal — delete a pod
# delete one on purpose

kubectl delete pod hotel-app-rc-9mt7r
# pod "hotel-app-rc-9mt7r" deleted

kubectl get pods
# NAME                 READY   STATUS              RESTARTS   AGE
# hotel-app-rc-4xk2p   1/1     Running             0          2m
# hotel-app-rc-pz3wq   1/1     Running             0          2m
# hotel-app-rc-tb8vn   0/1     ContainerCreating   0          1s

# a new one is already coming up

A replacement was already being created. You did nothing.

The new Pod has a new name and a new IP. This is exactly why Pods need a Service in front of them.

ReplicaSet — The Replacement

The ReplicaSet does the same job. Keep a count, heal, scale.

Two things changed in the file.

replicaset.yaml
# replicaset.yaml  -  the one you should write

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: hotel-app-rs
  labels:
    app: hotel-app
spec:
  replicas: 3
  selector:
    matchLabels:                  # the simple form
      app: hotel-app
  template:
    metadata:
      labels:
        app: hotel-app
    spec:
      containers:
        - name: hotel-app
          image: srinudev645/hotel-app:v1
          ports:
            - containerPort: 8080
ReplicationControllerReplicaSet
apiVersionv1apps/v1
kindReplicationControllerReplicaSet
selector written asselector: directlyselector.matchLabels
terminal — create it
kubectl apply -f replicaset.yaml
# replicaset.apps/hotel-app-rs created

kubectl get rs
# NAME           DESIRED   CURRENT   READY   AGE
# hotel-app-rs   3         3         3       15s

kubectl describe rs hotel-app-rs      # events, selector, Pod template
kubectl get pods -l app=hotel-app     # the Pods it owns

The Real Difference Is the Selector

This is the part people get asked in interviews.

The selector difference between a Kubernetes ReplicationController and a ReplicaSet

A ReplicationController has an equality based selector. It can only ask one thing:

is this label equal to this value?

app: hotel-app and nothing more.

A ReplicaSet also has a set based selector. It can ask much more:

replicaset.yaml — matchExpressions
# the part a ReplicationController cannot do

spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend              # plain equals, still allowed
    matchExpressions:
      - key: app
        operator: In              # In, NotIn, Exists, DoesNotExist
        values:
          - hotel-app
          - hotel-admin

# this one selector matches BOTH hotel-app and hotel-admin
# a ReplicationController can only match one value
OperatorWhat it asks
Inis the label one of these values
NotInis the label none of these values
Existsdoes this label exist at all
DoesNotExistis this label missing

One ReplicaSet selector can match several values at once. A ReplicationController cannot do that.

⚠️

The labels in template.metadata.labels must match the selector. If they do not agree, the controller creates Pods it cannot see, then creates more, forever.

Scale Up and Scale Down

Scaling a Kubernetes ReplicaSet up and down by changing the replicas number

terminal — scale
# scale up

kubectl scale rs hotel-app-rs --replicas=5
# replicaset.apps/hotel-app-rs scaled

kubectl get rs
# NAME           DESIRED   CURRENT   READY   AGE
# hotel-app-rs   5         5         5       3m

# scale down

kubectl scale rs hotel-app-rs --replicas=2
# replicaset.apps/hotel-app-rs scaled

# or edit replicas in the file and apply it again
kubectl apply -f replicaset.yaml

Two ways, same result:

  • kubectl scale — fast, good for a quick change
  • edit replicas and kubectl apply — the file stays true, so use this for real work
⚠️

Scale with the command and your YAML file now says something different. The next apply will undo your change. Keep the file honest.

Deleting

terminal — delete
# delete the ReplicaSet and its Pods
kubectl delete rs hotel-app-rs

# or with the file
kubectl delete -f replicaset.yaml

# delete the ReplicaSet but KEEP the Pods running
kubectl delete rs hotel-app-rs --cascade=orphan

The ReplicaSet owns its Pods, so deleting it deletes them too. --cascade=orphan keeps the Pods but leaves nothing watching them.

Where This Breaks Down

A ReplicaSet keeps Pods alive. That is all it does.

Now change the image to version 2.0 and apply it.

Nothing happens. The running Pods keep version 1.0. A ReplicaSet does not know how to update Pods, only how to count them.

To get the new version you would have to delete the Pods yourself. Delete them all at once and your app goes down while they restart.

That is the gap a Deployment fills. It manages ReplicaSets for you and updates Pods a few at a time, with no downtime. That is the next article.

ReplicaSet Quick Reference

commands
# ReplicationController
kubectl get rc                            # list them
kubectl describe rc <name>                # details and events
kubectl scale rc <name> --replicas=5      # scale
kubectl delete rc <name>                  # delete

# ReplicaSet
kubectl get rs                            # list them
kubectl get rs -o wide                    # plus images and selector
kubectl describe rs <name>                # details and events
kubectl scale rs <name> --replicas=5      # scale up
kubectl scale rs <name> --replicas=2      # scale down
kubectl get pods -l app=hotel-app         # the Pods it owns
kubectl delete rs <name>                  # delete it and its Pods
CommandWhat it does
kubectl get rslist ReplicaSets with desired and current
kubectl get rclist ReplicationControllers
kubectl describe rs <name>selector, template and events
kubectl get pods -l app=hotel-appthe Pods a selector owns
kubectl scale rs <name> --replicas=5scale up
kubectl scale rs <name> --replicas=2scale down
kubectl delete rs <name>delete it and its Pods
kubectl delete rs <name> --cascade=orphandelete it, keep the Pods

What's Next

A controller is what turns a Pod from a one off into something that stays alive. The official ReplicaSet documentation (opens in a new tab) and the labels and selectors page (opens in a new tab) go deeper on set based matching.

← Back to Kubernetes Namespace

Continue to Kubernetes Deployment →


Frequently Asked Questions

Why should you not create a Pod directly in Kubernetes?

Because nothing is watching it. A Pod you create by hand is a one off. The node fails, the container crashes badly, or somebody deletes it. That Pod is gone and nobody brings it back. Your app is simply down. A controller such as a ReplicaSet is different. You tell it how many Pods you want, and it keeps that number alive. Create Pods through a controller, not by hand.

What is a ReplicationController in Kubernetes?

A ReplicationController is the older Kubernetes object that creates Pods and keeps a fixed number of them running. You give it a replicas number and a Pod template. It watches the Pods all the time. If one is deleted or crashes, it creates a replacement, so the count always matches. You can also scale up and scale down with it. It has been replaced by the ReplicaSet.

What is a ReplicaSet in Kubernetes?

A ReplicaSet is the replacement for the ReplicationController. It does the same job. It creates Pods and keeps the number you asked for running. It replaces any Pod that dies. It lets you scale up or down. The difference is the selector. A ReplicaSet supports set based selectors, so it can match several label values at once. Its apiVersion is apps/v1 rather than v1.

What is the difference between ReplicationController and ReplicaSet?

The real difference is the selector. A ReplicationController only supports equality based selectors, so it can ask whether a label equals one value and nothing more. A ReplicaSet also supports set based selectors through matchExpressions, with operators In, NotIn, Exists and DoesNotExist. That means one ReplicaSet selector can match several values at once. Everything else is the same, and ReplicaSet is what you should write today.

How does a ReplicaSet know which Pods belong to it?

By labels, not by name. The selector in the ReplicaSet is matched against the labels on the Pods. Any running Pod whose labels match the selector is counted as one of its replicas. This is why the labels in the Pod template must match the selector. If they do not agree, the ReplicaSet creates Pods it does not recognise and keeps creating more forever.

How do you scale up and scale down a ReplicaSet?

Two ways. The quick way is kubectl scale rs followed by the name and --replicas with the new number. The repeatable way is to change the replicas field in your YAML file and run kubectl apply again. Both reach the same result. The controller compares the new desired count with the current count, then creates or deletes Pods until they match.

What happens when you delete a ReplicaSet?

By default its Pods are deleted with it. The ReplicaSet owns those Pods, so removing the owner removes them too. To remove only the ReplicaSet and leave the Pods running, add --cascade=orphan to the delete command. The Pods then keep running with nothing watching them, which is rarely what you want.

Should I use a ReplicaSet directly in production?

Usually not. A ReplicaSet keeps Pods alive, but it has no idea how to update them safely. Changing the image in a ReplicaSet does not restart the existing Pods. For real applications you use a Deployment, which creates and manages ReplicaSets for you and adds rolling updates and rollback. Learning the ReplicaSet still matters, because it is the thing a Deployment is built on.