Deployments & Strategies
A Deployment manages ReplicaSets, and ReplicaSets manage Pods. Kubernetes native Deployments support RollingUpdate and Recreate; blue/green and canary are usually built with labels, Services, Ingress/service mesh routing, Helm, Argo Rollouts, or CI/CD automation.
How Deployments Work
A Deployment is a controller-managed desired state for stateless workloads. You describe the Pod template, replica count, and rollout behavior. When the Pod template changes, the Deployment creates a new ReplicaSet and scales old/new ReplicaSets according to the strategy.
Deployment creates and manages ReplicaSets; ReplicaSets create and manage Pods.
Daily Commands
# Replace <namespace> and <deployment> before running.
kubectl get deployments -n <namespace> -o wide
kubectl describe deployment <deployment> -n <namespace>
# Show rollout progress and history.
kubectl rollout status deployment/<deployment> -n <namespace>
kubectl rollout history deployment/<deployment> -n <namespace>
# See ReplicaSets owned by the Deployment.
kubectl get rs -n <namespace> -l app=<app-label> -o wide
# Pause a rollout before multiple changes, then resume.
kubectl rollout pause deployment/<deployment> -n <namespace>
kubectl rollout resume deployment/<deployment> -n <namespace>
# Roll back to the previous revision.
kubectl rollout undo deployment/<deployment> -n <namespace>
# Roll back to a specific revision from rollout history.
kubectl rollout undo deployment/<deployment> -n <namespace> --to-revision=<revision-number>
Production Deployment YAML
This is a practical baseline for stateless web services. In real client environments, image, resources, probes, labels, security context, and annotations are usually driven by Helm values or GitOps manifests.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-api
namespace: app
labels:
app: web-api # Stable app label used by Services, dashboards, alerts, and selectors.
spec:
replicas: 4 # Desired Pod count. HPA may manage this if autoscaling is enabled.
revisionHistoryLimit: 5 # Keeps old ReplicaSets for rollback without storing unlimited history.
progressDeadlineSeconds: 600 # Rollout is marked failed if progress stalls beyond this time.
minReadySeconds: 10 # Pod must be ready for this long before counted as available.
strategy:
type: RollingUpdate # Default strategy; gradually replaces old Pods.
rollingUpdate:
maxUnavailable: 1 # At most one desired replica unavailable during rollout.
maxSurge: 1 # At most one extra Pod above desired replicas during rollout.
selector:
matchLabels:
app: web-api # Must match template labels; immutable after creation.
template:
metadata:
labels:
app: web-api # Service selectors match this label.
version: v1 # Useful for canary/blue-green routing and observability.
spec:
serviceAccountName: web-api # Use a named ServiceAccount, not default, when API access is needed.
terminationGracePeriodSeconds: 30 # Time for graceful shutdown after SIGTERM.
containers:
- name: web-api
image: registry.example.com/platform/web-api:1.0.0 # Prefer immutable tags or digests.
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
envFrom:
- configMapRef:
name: web-api-config # Non-sensitive configuration.
- secretRef:
name: web-api-secrets # Sensitive values such as passwords or tokens.
startupProbe:
httpGet:
path: /health/startup
port: http
failureThreshold: 30
periodSeconds: 2
readinessProbe:
httpGet:
path: /health/ready # Controls whether this Pod receives Service traffic.
port: http
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /health/live # Keep liveness lightweight to avoid unnecessary restarts.
port: http
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
resources:
requests:
cpu: 250m # Scheduler reserves this amount.
memory: 256Mi
limits:
cpu: 1 # CPU limit may throttle; tune using real metrics.
memory: 512Mi # Exceeding this can cause OOMKilled.
Native Strategies
| Strategy | How It Works | Use When | Tradeoff |
|---|---|---|---|
RollingUpdate | Gradually scales up new ReplicaSet and scales down old ReplicaSet. | Most stateless services. | Old and new versions run together briefly. |
Recreate | Deletes old Pods before creating new Pods. | Apps cannot run two versions at once. | Causes downtime unless another layer absorbs it. |
RollingUpdate Example
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25% # Percent or integer. Lower value protects availability.
maxSurge: 25% # Extra Pods allowed during rollout. Needs spare cluster capacity.
Recreate Example
strategy:
type: Recreate # Old Pods are terminated before new Pods are created.
Deployment Models
Kubernetes Deployments provide the primitives. Higher-level models are usually achieved by combining Deployments, labels, Services, Ingress, service mesh, CI/CD, Helm, or progressive delivery controllers.
| Model | Traffic Pattern | Typical Implementation | Best For |
|---|---|---|---|
| Rolling | Gradual replacement | Deployment RollingUpdate | Default stateless app releases. |
| Blue/Green | Switch all traffic from old to new | Two Deployments, one Service selector flip | Fast rollback and clean version separation. |
| Canary | Small percent to new version | Two Deployments plus weighted routing or replica split | Risk-reduced releases with metrics validation. |
| Shadow | Copy traffic to new version, do not return response | Service mesh/Ingress/controller support | Testing behavior under real traffic safely. |
| A/B | Route by header/user/segment | Ingress/service mesh/application gateway | Product experiments and targeted releases. |
Blue/Green Pattern
Blue/green keeps two versions live as separate Deployments. The Service points to one version using labels. Rollback is usually a Service selector flip.
apiVersion: v1
kind: Service
metadata:
name: web-api
namespace: app
spec:
selector:
app: web-api
slot: blue # Change to green to switch traffic.
ports:
- name: http
port: 80
targetPort: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-api-blue
namespace: app
spec:
replicas: 4
selector:
matchLabels:
app: web-api
slot: blue
template:
metadata:
labels:
app: web-api
slot: blue
version: v1
spec:
containers:
- name: web-api
image: registry.example.com/platform/web-api:1.0.0
ports:
- name: http
containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-api-green
namespace: app
spec:
replicas: 4
selector:
matchLabels:
app: web-api
slot: green
template:
metadata:
labels:
app: web-api
slot: green
version: v2
spec:
containers:
- name: web-api
image: registry.example.com/platform/web-api:2.0.0
ports:
- name: http
containerPort: 8080
# Preview current endpoints before switching.
kubectl get endpointslice -n app -l kubernetes.io/service-name=web-api -o wide
# Switch Service traffic from blue to green.
kubectl patch service web-api -n app -p '{"spec":{"selector":{"app":"web-api","slot":"green"}}}'
# Roll back by switching selector back to blue.
kubectl patch service web-api -n app -p '{"spec":{"selector":{"app":"web-api","slot":"blue"}}}'
Canary Pattern
Basic Kubernetes canary can be done by running two Deployments with the same Service selector and different replica counts. This is approximate weighting because kube-proxy balances across endpoints, not exact percentages. For precise weights, use Ingress/service mesh or Argo Rollouts.
apiVersion: v1
kind: Service
metadata:
name: web-api
namespace: app
spec:
selector:
app: web-api # Both stable and canary Pods share this label.
ports:
- name: http
port: 80
targetPort: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-api-stable
namespace: app
spec:
replicas: 9 # About 90% of endpoints if canary has 1 replica.
selector:
matchLabels:
app: web-api
track: stable
template:
metadata:
labels:
app: web-api
track: stable
version: v1
spec:
containers:
- name: web-api
image: registry.example.com/platform/web-api:1.0.0
ports:
- name: http
containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-api-canary
namespace: app
spec:
replicas: 1 # About 10% of endpoints when stable has 9 replicas.
selector:
matchLabels:
app: web-api
track: canary
template:
metadata:
labels:
app: web-api
track: canary
version: v2
spec:
containers:
- name: web-api
image: registry.example.com/platform/web-api:2.0.0
ports:
- name: http
containerPort: 8080
Rollout Failure Debugging
# Check if rollout is stuck.
kubectl rollout status deployment/<deployment> -n <namespace> --timeout=60s
# Describe Deployment for Progressing/Available conditions and events.
kubectl describe deployment <deployment> -n <namespace>
# Compare old and new ReplicaSets.
kubectl get rs -n <namespace> -l app=<app-label> -o wide
# Check new Pods for image, scheduling, probe, config, or crash problems.
kubectl get pods -n <namespace> -l app=<app-label> -o wide
kubectl describe pod <new-pod-name> -n <namespace>
kubectl logs <new-pod-name> -n <namespace> --previous --tail=100
# Stop a bad rollout quickly.
kubectl rollout undo deployment/<deployment> -n <namespace>
HPA And PDB
Deployments often interact with HorizontalPodAutoscalers and PodDisruptionBudgets. HPA changes replica count based on metrics. PDB protects minimum availability during voluntary disruptions such as node drains.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-api
namespace: app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api # HPA adjusts .spec.replicas on this Deployment.
minReplicas: 4
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60 # Target average CPU usage across Pods.
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-api
namespace: app
spec:
minAvailable: 3 # At least 3 matching Pods must remain available during voluntary disruption.
selector:
matchLabels:
app: web-api
GitOps And Helm Notes
- In GitOps clusters, update the manifest, Helm values, or Kustomize overlay in Git; do not rely on long-lived manual
kubectl set imagechanges. - Use
kubectl diff -f,helm template,helm diff, or ArgoCD app diff before rollout when possible. - Keep selectors stable. Changing
spec.selectoron a Deployment is not allowed and usually indicates a label design problem. - Use immutable image tags or digests so rollback points are reliable.
Common Gotchas
- Selector mismatch: Deployment selector must match Pod template labels. Bad labels can create orphaned or unmanaged Pods.
- Readiness blocks rollout: new Pods may run but never become available, causing rollout progress to stall.
- maxUnavailable too high: can drop capacity during rollout. Lower it for critical services.
- HPA and manual scaling: manual replica changes may be overwritten by HPA.
- Blue/green selector flip: validate the target Deployment is Ready before switching Service selectors.