Deployments and ReplicaSets
The idea in one sentence
Section titled “The idea in one sentence”A ReplicaSet keeps a fixed number of Pods matching a label selector running at all times, and a Deployment manages ReplicaSets for you to provide declarative, versioned rolling updates and rollback history on top.
ReplicaSets: a fixed count of matching Pods
Section titled “ReplicaSets: a fixed count of matching Pods”A ReplicaSet’s job is narrow: given a Pod template and a label selector, it makes sure exactly replicas Pods matching that selector exist. If a Pod matching the selector disappears, the ReplicaSet creates a replacement; if there are too many, it deletes the extras. A ReplicaSet will even adopt existing Pods it did not create, as long as their labels match its selector.
apiVersion: apps/v1kind: ReplicaSetmetadata: name: web-rsspec: replicas: 3 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: web image: myregistry/web:1.0.0 ports: - containerPort: 8080In everyday use you do not write ReplicaSets like this yourself — you create a Deployment, and the Deployment creates and owns the ReplicaSet for you.
Deployments: rolling updates on top of ReplicaSets
Section titled “Deployments: rolling updates on top of ReplicaSets”A Deployment wraps a ReplicaSet with a rollout strategy, a revision history, and rollback support. When you change the Pod template in a Deployment (a new image tag, an updated env var), the Deployment creates a new ReplicaSet with that template and gradually shifts replicas from the old ReplicaSet to the new one.
apiVersion: apps/v1kind: Deploymentmetadata: name: webspec: replicas: 3 selector: matchLabels: app: web strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 1 template: metadata: labels: app: web spec: containers: - name: web image: myregistry/web:1.1.0 ports: - containerPort: 8080The ownership chain is always Deployment → ReplicaSet → Pod: the Deployment owns one or more ReplicaSets (the current one, plus old ones kept for rollback history), and each ReplicaSet owns its Pods.
flowchart LR dep["Deployment web"] --> rsOld["ReplicaSet web-abc123 (old): 3 -> 0"] dep --> rsNew["ReplicaSet web-def456 (new): 0 -> 3"] rsOld --> p1["Pod (terminating)"] rsNew --> p2["Pod (running)"] rsNew --> p3["Pod (running)"] rsNew --> p4["Pod (running)"]
Rollout strategy: RollingUpdate vs Recreate
Section titled “Rollout strategy: RollingUpdate vs Recreate”maxUnavailable caps how many of the desired replicas can be unavailable at once during the rollout, and maxSurge caps how many extra Pods above the desired count are allowed to exist temporarily while new ones come up. Together they tune the trade-off between rollout speed and available capacity — the values above allow one Pod down and one extra Pod at a time for a Deployment of 3 replicas.
The alternative strategy is Recreate, which terminates every old Pod before creating any new one:
spec: strategy: type: RecreateRecreate causes a brief outage, so it is reserved for cases where the old and new versions genuinely cannot run side by side — for example, an application that cannot tolerate two schema versions hitting the same database at once.
Operating a rollout
Section titled “Operating a rollout”# Trigger a rollout by changing the Pod template (e.g. a new image), then watch itkubectl set image deployment/web web=myregistry/web:1.2.0kubectl rollout status deployment/web
# See every revision this Deployment has keptkubectl rollout history deployment/web
# Roll back to the previous revisionkubectl rollout undo deployment/web
# Scale independently of a rolloutkubectl scale deployment/web --replicas=5