Skip to content

Pods, ReplicaSets, and Deployments

Play it

Chaos Monkey Cluster: Keep a cluster serving while pods crash, nodes drain and releases go wrong.

The game links back to this page from: Pods, ReplicaSets, Deployments.

Pods

A Pod is the smallest deployable unit — one or more containers that share a network namespace (same localhost) and can share volumes. Most Pods run exactly one container; multiple containers in one Pod are for tightly-coupled helpers (a sidecar, an init container), not for unrelated services.

kubectl apply -f examples/pod/sample-pod.yaml
kubectl get pod sample-pod
kubectl describe pod sample-pod
kubectl delete pod sample-pod

examples/pod/sample-pod.yaml is about as minimal as a Pod gets: one container, one image, one exposed port. Pods created directly like this are not self-healing — if the node dies or the container crashes past its restart policy, nothing recreates it. That's what a controller (below) is for.

ReplicaSets

A ReplicaSet keeps a specified number of identical Pod replicas running, using spec.selector to find which Pods it owns (by label) and spec.template to define what a replica looks like.

kubectl apply -f examples/replicaset/sample-replicaset.yaml
kubectl get replicaset sample-replicaset
kubectl get pods -l app=nginx        # the Pods it's managing, found by label
kubectl delete pod <one-of-the-pods> # the ReplicaSet notices and creates a replacement

Try the last two commands against examples/replicaset/sample-replicaset.yaml — deleting one Pod, watching kubectl get pods -l app=nginx -w recreate it, is the clearest way to see self-healing happen.

You rarely create a ReplicaSet directly (as this example does, for illustration) — in practice a Deployment creates and owns one for you.

Deployments

A Deployment manages ReplicaSets for you and adds rolling updates: change spec.template (e.g. bump the image tag) and re-apply, and the Deployment creates a new ReplicaSet, scales it up, and scales the old one down gradually — no downtime, and kubectl rollout undo if the new version is bad.

kubectl apply -f examples/deployment/sample-deployment.yaml
kubectl get deployment sample-deployment
kubectl get replicaset -l app=nginx     # the ReplicaSet the Deployment created
kubectl set image deployment/sample-deployment nginx=nginx:1.27
kubectl rollout status deployment/sample-deployment

examples/deployment/sample-deployment.yaml differs from the ReplicaSet example only in kind and that it's a Deployment wrapping the same Pod template — that's the normal relationship: Deployment → owns a ReplicaSet → owns Pods.

Which one to write

  • Ad-hoc debugging, a one-off tool container → a bare Pod (or kubectl run).
  • Almost everything else that should stay running → a Deployment. Reach for a ReplicaSet directly only when you specifically don't want rolling-update behavior (uncommon).

Labels and selectors tie it together

spec.selector.matchLabels (ReplicaSet/Deployment) must match spec.template.metadata. labels — this is how the controller finds "its" Pods among everything else in the namespace. The same label (app: nginx in these examples) is also what examples/services/sample-service.yaml's spec.selector matches on — see 04-services-and-networking.md.