Deployments Basics
A Deployment is the standard way to run a stateless app on Kubernetes: you declare the desired image, replica count, and update strategy, and the controller keeps that state true. This page walks through the everyday operations with runnable examples.
Prerequisites
- kubectl matching your cluster (skew within one minor of Kubernetes 1.36.2).
- Access to a cluster (kind, minikube, or a managed cluster) with a default namespace you can write to.
- A container image in a registry the cluster can pull. Nodes run containerd via CRI; you build images with Docker Engine 29.x locally.
- Optional:
kubectl config set-context --current --namespace=demoto avoid typing-n demoevery time.
Basic Examples
1. A minimal Deployment
The smallest useful Deployment declares replicas, a selector, and a Pod template.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: registry.example.com/web:1.4.0
ports:
- containerPort: 8080apiVersion: apps/v1andkind: Deploymentidentify the object type.spec.replicasis the desired count of Pods.spec.selector.matchLabelsmust matchspec.template.metadata.labels, or the API rejects it.- The
templateis the blueprint for every Pod the Deployment creates.
2. Create and inspect
Apply the manifest and watch the Deployment roll out.
kubectl apply -f web.yaml
kubectl rollout status deployment/web
kubectl get deploy,rs,pods -l app=webapplyis declarative and idempotent; re-running it reconciles differences.rollout statusblocks until the Deployment reaches its desired state or fails.- Listing
deploy,rs,podsshows the full ownership chain the Deployment created.
3. Pin an image by digest
Tags are mutable; digests are immutable and reproducible.
containers:
- name: web
image: registry.example.com/web@sha256:0f5a...c91- A digest guarantees every node pulls the exact same bytes.
- This removes ambiguity when the same tag is repushed.
- Combine with
imagePullPolicy: IfNotPresentto avoid needless re-pulls.
4. Update the image (a rolling update)
Changing the Pod template triggers a controlled rollout.
kubectl set image deployment/web web=registry.example.com/web:1.5.0
kubectl rollout status deployment/web- Editing any template field creates a new ReplicaSet and shifts Pods to it.
- The default
RollingUpdatestrategy keeps the app serving during the change. set imageis convenient, but committing the change to your YAML in Git is the durable practice.
5. Scale up or down
Scaling changes only the replica count, not the template.
kubectl scale deployment/web --replicas=5- Scaling does not create a new ReplicaSet or a new revision.
- The active ReplicaSet adds or removes Pods to match.
- For production, prefer a HorizontalPodAutoscaler over manual scaling.
6. Add health probes
Probes tell Kubernetes when a Pod is ready for traffic and when to restart it.
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /livez
port: 8080
periodSeconds: 15- The readiness probe gates whether a Pod receives Service traffic.
- The liveness probe restarts a container that is running but wedged.
- Rolling updates wait for new Pods to pass readiness before removing old ones.
7. Set requests and limits
Resource requests drive scheduling; limits cap consumption.
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
memory: "256Mi"requestsreserve capacity so the scheduler places Pods sensibly.- A memory
limitprotects the node from a leaking container being OOM-killed unbounded. - Many teams omit CPU limits to avoid throttling but always set a memory limit.
Intermediate Examples
8. Harden the security context
Run as non-root with a read-only root filesystem to satisfy the restricted Pod Security Standard.
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: web
image: registry.example.com/web@sha256:0f5a...c91
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]runAsNonRootrefuses to start a container whose image runs as UID 0.- Dropping all capabilities removes Linux privileges the app almost never needs.
- A read-only root filesystem blocks tampering; mount an
emptyDirfor any writable path.
9. Spread Pods across nodes for availability
Topology spread constraints keep replicas from piling onto one node.
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: webmaxSkew: 1keeps per-node counts within one of each other.topologyKeychooses the failure domain; use zone keys for multi-zone spread.- This turns "3 replicas" into real fault tolerance instead of 3 Pods on one node.
10. Roll out safely and roll back
Watch a rollout, and undo it if it goes wrong.
kubectl set image deployment/web web=registry.example.com/web:1.6.0
kubectl rollout status deployment/web --timeout=120s
# If the new version misbehaves:
kubectl rollout undo deployment/webrollout status --timeoutfails fast instead of hanging on a broken deploy.rollout undoreturns to the previous revision using retained ReplicaSet history.- Keep
spec.revisionHistoryLimitat a sane value (default 10) so rollbacks stay possible.
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).