Skip to content

03 - Deployments

What this session is

About 45 minutes. Deployments - the resource you'll actually use most. Manages a set of identical pods (replicas), handles rolling updates, restarts dead pods.

Why deployments instead of pods

Raw pods are mortal. If a pod dies, it stays dead. If you want N copies, you create N pod manifests. If you update the image, you delete each pod and create new ones.

A Deployment does this for you. It says: "I want 3 replicas of this pod template; keep it that way." If a pod dies, the Deployment creates a new one. If you change the image version, the Deployment rolls out new pods and removes old ones one at a time.

You will write Deployments far more often than raw pods.

Your first Deployment

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.27
        ports:
        - containerPort: 80

Apply:

kubectl apply -f deployment.yaml

Check:

kubectl get deployments
kubectl get pods

You should see one deployment and three pods with names like nginx-7b85f9c-xxxxx. The hash is from the pod template; the suffix is unique per pod.

Anatomy

  • replicas: 3 - keep 3 pods running.
  • selector.matchLabels - which pods this Deployment manages. Must match the template.metadata.labels.
  • template - the pod spec for new pods. Same structure as a Pod manifest, without apiVersion/kind.

The selector + labels is how Kubernetes knows which pods "belong" to this Deployment. They must match. Page 07 covers labels in depth.

Scale up or down

kubectl scale deployment nginx --replicas=5
kubectl get pods

Now 5 pods. Scale down:

kubectl scale deployment nginx --replicas=2

Or edit the YAML's replicas: field, re-apply.

Rolling updates

Change the image:

kubectl set image deployment/nginx nginx=nginx:1.26

Or edit the YAML (image: nginx:1.26), re-apply.

Watch:

kubectl rollout status deployment/nginx

Kubernetes: 1. Creates a new pod with the new image. 2. Waits for it to be Ready. 3. Removes one old pod. 4. Repeats until all pods are the new version.

Zero downtime. The killer feature of Deployments.

Rollback

If the new version is broken:

kubectl rollout undo deployment/nginx

Goes back to the previous version. Done. (kubectl rollout history deployment/nginx shows past revisions.)

Rolling-update strategy

The default behavior is configurable:

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # at most 1 extra pod above replicas during update
      maxUnavailable: 1    # at most 1 fewer pod than replicas during update

The other strategy:

spec:
  strategy:
    type: Recreate          # kill all, then start fresh (downtime; faster for big jumps)

For most apps, the rolling default is right. Use Recreate only when the old and new versions can't coexist (database schema migrations, for example).

Readiness probes matter for rolling updates

A pod is "Ready" when its container started, and if a readiness probe is configured, the probe is passing. During a rolling update, Kubernetes waits for the new pod to be Ready before considering it healthy.

Without a readiness probe, Kubernetes assumes "Running == Ready" - which is often wrong (the container is up but the app isn't accepting requests yet).

spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:1.27
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 2
          periodSeconds: 5

Always add readiness probes to production apps.

Inspect what's happening

kubectl get deploy nginx -o yaml          # the current YAML (with status)
kubectl describe deploy nginx             # status + events
kubectl rollout status deploy/nginx       # live status of an ongoing update
kubectl rollout history deploy/nginx      # past revisions

The Deployment's status section shows: how many pods are available, ready, and updating.

ReplicaSets (a side note)

Each Deployment creates a ReplicaSet under the hood (one per image version). The ReplicaSet manages the actual pods. You can kubectl get replicasets to see them.

You almost never edit ReplicaSets directly - you edit the Deployment, which manages the ReplicaSets. Recognize the layer; don't worry about it.

Exercise

  1. Apply the Deployment above. Check kubectl get deploy and kubectl get pods.

  2. Scale to 5:

    kubectl scale deploy nginx --replicas=5
    kubectl get pods
    

  3. Update the image, watch the rolling update:

    kubectl set image deploy/nginx nginx=nginx:1.26
    kubectl rollout status deploy/nginx
    kubectl get pods           # mid-update: some old, some new
    

  4. Rollback:

    kubectl rollout undo deploy/nginx
    kubectl get pods
    

  5. Delete a pod manually:

    kubectl delete pod <some-nginx-pod>
    kubectl get pods           # the Deployment immediately replaces it
    

  6. Cleanup:

    kubectl delete -f deployment.yaml
    

What you might wonder

"What if I delete the Deployment?" The Deployment AND its pods are deleted. To keep the pods (rare), kubectl delete deploy nginx --cascade=orphan.

"What's the difference between Deployment and StatefulSet?" Deployments are for stateless pods (any pod is interchangeable). StatefulSets are for stateful pods that need stable identities (think Postgres replicas - each one has its own data). Use Deployments unless you have a clear stateful need.

"What's DaemonSet?" A controller that ensures one pod per node. Used for per-node agents (log collectors, network plugins). Different shape; recognize.

"How do horizontal autoscalers work?" HorizontalPodAutoscaler (HPA) - adjusts replicas based on CPU/memory/custom metrics. Beyond beginner; mentioned for awareness.

Done

  • Write a Deployment manifest.
  • Scale replicas up/down.
  • Trigger rolling updates with kubectl set image.
  • Rollback with kubectl rollout undo.
  • Add readiness probes.
  • Understand selector/label matching.

Next: Services →

Comments