What's the difference between a ReplicaSet and a Deployment?

6 minintermediatereplicasetdeploymentworkload-controllers

Quick Answer

A ReplicaSet's only job is ensuring a specified number of identical Pod replicas are running at all times, replacing any that die. A Deployment sits one layer above a ReplicaSet and adds rollout management — it creates and manages ReplicaSets on your behalf, and knows how to perform a rolling update (creating a new ReplicaSet for the new version, scaling it up while scaling the old one down) and how to roll back to a previous version. In practice, you almost always create Deployments directly and let them manage ReplicaSets for you, rather than creating a ReplicaSet by hand.

Detailed Answer

ReplicaSet — maintains a stable count of identical Pods

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: myapp:1.0

The ReplicaSet controller's reconciliation loop (see the control loop question) continuously ensures exactly 3 Pods matching the app: web label selector exist — if one is deleted or its node dies, a replacement is created; if you manually create a 4th matching Pod, it will be deleted to bring the count back down to 3.

What a ReplicaSet cannot do: change the Pod template's image version in a controlled, gradual way. If you edit a running ReplicaSet's image field, nothing happens to existing Pods — the new template only applies to future Pods it creates, so you'd have to manually delete old Pods one by one to see them replaced with the new version, with no coordination, health checking, or rollback built in.

Deployment — adds rollout management on top

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: myapp:1.0

A Deployment creates and owns a ReplicaSet with this spec. When you update the Deployment's image (kubectl set image deployment/web web=myapp:2.0), the Deployment controller creates a new ReplicaSet with the updated template, and gradually scales the new one up while scaling the old one down — according to the configured strategy — rather than mutating Pods in place (see the rolling update question for the mechanics).

The layering, visualized

Deployment (rollout/rollback logic, revision history)
   └── ReplicaSet (maintains N identical replicas of one Pod template)
         └── Pod, Pod, Pod, ...

A Deployment update creates a new ReplicaSet rather than editing the existing one — this is precisely what enables rollback: the old ReplicaSet (scaled down to 0, but not deleted) still exists with its original template, so rolling back is just re-scaling it back up while scaling the current one down (kubectl rollout undo deployment/web).

You should essentially never create a bare ReplicaSet directly in production — always create a Deployment, and let it manage the underlying ReplicaSet(s) for you. Direct ReplicaSet management is mostly useful to understand conceptually, since it's the mechanism Deployments build on, and occasionally shows up when debugging why kubectl get replicasets shows old, scaled-to-zero ReplicaSets lingering after several rollouts (this is expected — it's the Deployment's revision history, bounded by the revisionHistoryLimit field).

Related Resources