Skip to content

Deployments

A bare Pod is unmanaged: if its node dies, nothing replaces it. A Deployment is the object that makes a workload self-healing and updatable, by owning ReplicaSets, which own Pods.

You describe the state you want — an image, a replica count, a way to update — and a controller works continuously to make the cluster match. That is the whole idea, and everything else on this page is detail about how it is done safely.

Reference

Terminology

  • Deployment — Declares a Pod template and a replica count, and manages rollouts between versions of that template.
  • ReplicaSet — Maintains a number of identical Pods. You rarely create one directly; the Deployment creates one per revision so it can roll back.
  • RollingUpdate — The default strategy. Pods are replaced gradually, bounded by maxSurge (how many extra may exist) and maxUnavailable (how many may be missing). Traffic is never fully down.
  • Recreate — Kill everything, then start the new version. Brief downtime, but necessary when two versions cannot run at once, for example against a single-writer volume.
  • Probe — A readiness or liveness check. Readiness decides whether a Pod receives traffic, which is what makes a rolling update safe; liveness decides whether it gets restarted.
  • Progress deadlineprogressDeadlineSeconds, the time a rollout may make no progress before it is marked failed. The rollout stalls rather than rolling back on its own.

The Ownership Chain

Deployment (desired state, history)
    └── ReplicaSet (revision 3, 4 replicas)
            └── Pod ─┐
            └── Pod  │  matched by label selector, not by name
            └── Pod  │
            └── Pod ─┘

Each revision gets its own ReplicaSet, which is why kubectl rollout undo is cheap: the old ReplicaSet is still there, scaled to zero. revisionHistoryLimit decides how many are kept.

Two fields are effectively permanent:

  • spec.selector is immutable. Choose labels you can live with, and put the same labels in spec.template.metadata.labels — if the template’s labels do not match the selector, the API server rejects the object.
  • Pod templates are immutable too. You do not edit Pods; you change the template and let the Deployment replace them.

Exercises

  1. Create and inspect the chain.

    kubectl create deployment web --image=docker.io/library/nginx:1.27 --replicas=3
    kubectl get deploy,rs,pods -l app=web
    kubectl rollout status deployment/web

    Note the ReplicaSet name: the Deployment name plus a hash of the Pod template. Change the template and that hash changes.

  2. Roll out and roll back.

    kubectl set image deployment/web nginx=docker.io/library/nginx:1.26
    kubectl rollout status deployment/web
    kubectl rollout history deployment/web
    kubectl rollout undo deployment/web
    kubectl rollout status deployment/web
  3. Watch a rollout stall on a bad image. Set the image to something that does not exist, then watch the new Pods sit in ImagePullBackOff while the old ones keep serving:

    kubectl set image deployment/web nginx=docker.io/library/nginx:does-not-exist
    kubectl get pods -l app=web
    kubectl rollout status deployment/web --timeout=30s
    kubectl rollout undo deployment/web

    This is the safety property worth internalising: with a rolling update and a readiness probe, a broken image never reaches users. The rollout gets stuck rather than going dark.

  4. Make readiness matter. Add a readiness probe pointing at a path that returns 200, then point it at /does-not-exist and watch the rollout hang with Pods Running but never Ready. Without a readiness probe Kubernetes assumes a running container can serve traffic, which is often wrong.

  5. Tune the rate. Edit maxSurge: 1 and maxUnavailable: 0 and roll out again — slow but never below the desired replica count. Then try maxSurge: 0, maxUnavailable: 1. Which would you use on a three-replica production service?

  6. Restart without changing anything. kubectl rollout restart deployment/web replaces all Pods. You will need it more often than you expect, because changing a ConfigMap or Secret does not trigger a rollout — the Deployment’s template has not changed, so as far as it is concerned nothing happened.

What to Take Away

  • Deployments give you self-healing and a staged, reversible update. Bare Pods give you neither.
  • spec.selector and the Pod template are immutable; changes go through a new revision.
  • Readiness probes are what make a rolling update safe. Without one, you are rolling dice.
  • ConfigMap and Secret changes are invisible to the Deployment — a rollout restart is how you pick them up.

Where This Is Practised

Lab 02 in the workbook is built around this. Run labctl list to see whether it is ready yet.