Application Deployment (20%)¶
This domain covers the full lifecycle of deploying applications on Kubernetes: creating Deployments, performing rolling updates, rollbacks, and scaling, as well as advanced deployment strategies like blue/green and canary. It also includes packaging applications with Helm and customizing manifests with Kustomize.
Key Concepts¶
Deployments¶
Deployments manage ReplicaSets and provide declarative updates for Pods. They are the most common way to run stateless applications on Kubernetes.
# Create a Deployment
kubectl create deployment nginx-deploy --image=nginx:1.27 --replicas=3
# Scale a Deployment
kubectl scale deployment nginx-deploy --replicas=5
# Update the image
kubectl set image deployment/nginx-deploy nginx=nginx:1.28
# Check rollout status
kubectl rollout status deployment/nginx-deploy
# View rollout history
kubectl rollout history deployment/nginx-deploy
# Rollback to the previous version
kubectl rollout undo deployment/nginx-deploy
# Rollback to a specific revision
kubectl rollout undo deployment/nginx-deploy --to-revision=2
# Pause and resume a rollout
kubectl rollout pause deployment/nginx-deploy
kubectl rollout resume deployment/nginx-deploy
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
Exam Tip
Always use kubectl rollout status to verify a deployment update completed successfully. When asked to update an image, use kubectl set image for speed. Record the change with --record is deprecated; instead, use annotations if you need to track the reason for a change.
Rolling Update Strategy¶
The default deployment strategy is RollingUpdate. It gradually replaces old pods with new ones.
apiVersion: apps/v1
kind: Deployment
metadata:
name: rolling-app
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
selector:
matchLabels:
app: rolling-app
template:
metadata:
labels:
app: rolling-app
spec:
containers:
- name: app
image: nginx:1.27
Key fields:
maxSurge: Maximum number of pods created above the desired count during an update (absolute number or percentage)maxUnavailable: Maximum number of pods that can be unavailable during an update (absolute number or percentage)Recreatestrategy: Terminates all existing pods before creating new ones (causes downtime)
# View the strategy of an existing Deployment
kubectl describe deployment rolling-app | grep -A 3 Strategy
# Use Recreate strategy (for stateful apps that cannot run multiple versions)
kubectl patch deployment rolling-app -p '{"spec":{"strategy":{"type":"Recreate"}}}'
Blue/Green Deployments¶
Blue/green deployments run two identical environments. Traffic is switched from the old version (blue) to the new version (green) by updating the Service selector.
# Blue deployment (current production)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-blue
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: blue
template:
metadata:
labels:
app: myapp
version: blue
spec:
containers:
- name: app
image: myapp:1.0
---
# Green deployment (new version)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-green
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: green
template:
metadata:
labels:
app: myapp
version: green
spec:
containers:
- name: app
image: myapp:2.0
---
# Service initially pointing to blue
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
spec:
selector:
app: myapp
version: blue # Change to "green" to switch traffic
ports:
- port: 80
targetPort: 8080
# Switch traffic from blue to green
kubectl patch service myapp-svc -p '{"spec":{"selector":{"version":"green"}}}'
# Verify the switch
kubectl describe svc myapp-svc | grep Selector
# If green works, delete blue
kubectl delete deployment app-blue
Canary Deployments¶
Canary deployments route a small percentage of traffic to the new version before fully rolling it out. This is achieved by running both versions behind the same Service with different replica counts.
# Stable deployment (majority of traffic)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-stable
spec:
replicas: 9
selector:
matchLabels:
app: myapp
track: stable
template:
metadata:
labels:
app: myapp
track: stable
spec:
containers:
- name: app
image: myapp:1.0
---
# Canary deployment (small fraction of traffic)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-canary
spec:
replicas: 1
selector:
matchLabels:
app: myapp
track: canary
template:
metadata:
labels:
app: myapp
track: canary
spec:
containers:
- name: app
image: myapp:2.0
---
# Service routes to both based on shared label
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
spec:
selector:
app: myapp # Matches both stable and canary pods
ports:
- port: 80
targetPort: 8080
With 9 stable replicas and 1 canary replica, approximately 10% of traffic goes to the new version. Gradually increase canary replicas and decrease stable replicas as confidence grows.
Helm Basics¶
Helm is the package manager for Kubernetes. Charts are pre-configured packages of Kubernetes resources.
# Add a chart repository
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# Search for charts
helm search repo nginx
helm search hub wordpress
# Install a chart
helm install my-release bitnami/nginx
helm install my-release bitnami/nginx --namespace web --create-namespace
# Install with custom values
helm install my-release bitnami/nginx --set replicaCount=3
helm install my-release bitnami/nginx -f custom-values.yaml
# List installed releases
helm list
helm list --all-namespaces
# Upgrade a release
helm upgrade my-release bitnami/nginx --set replicaCount=5
# Rollback a release
helm rollback my-release 1
# View release history
helm history my-release
# Uninstall a release
helm uninstall my-release
# Show chart values and documentation
helm show values bitnami/nginx
helm show chart bitnami/nginx
# Generate manifests without installing (dry-run)
helm template my-release bitnami/nginx > manifests.yaml
Exam Tip
For the CKAD, you need to know how to install, upgrade, rollback, and uninstall Helm releases. You do not need to create charts from scratch, but understanding the basic structure helps. Use helm show values to discover configurable parameters.
Kustomize¶
Kustomize is built into kubectl and lets you customize Kubernetes manifests without templating. It uses a kustomization.yaml file to define overlays and patches.
# Apply a kustomization directory
kubectl apply -k ./overlay/production/
# Preview what kustomize will generate
kubectl kustomize ./overlay/production/
# Create a kustomization.yaml
# (Kustomize does not have a full imperative creation command;
# you write the file manually)
Example directory structure:
app/
base/
kustomization.yaml
deployment.yaml
service.yaml
overlays/
dev/
kustomization.yaml
replica-patch.yaml
prod/
kustomization.yaml
replica-patch.yaml
Base kustomization.yaml:
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
Production overlay:
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namePrefix: prod-
namespace: production
patches:
- path: replica-patch.yaml
# overlays/prod/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 5
Practice Exercises¶
Exercise 1: Create and Scale a Deployment
Create a Deployment named webapp with 3 replicas using the nginx:1.27 image. Then scale it to 5 replicas. Finally, update the image to nginx:1.28 and verify the rollout completes successfully.
Solution
# Create the Deployment
kubectl create deployment webapp --image=nginx:1.27 --replicas=3
# Verify
kubectl get deployment webapp
# Scale to 5 replicas
kubectl scale deployment webapp --replicas=5
# Update the image
kubectl set image deployment/webapp nginx=nginx:1.28
# Verify rollout
kubectl rollout status deployment/webapp
kubectl get deployment webapp
Exercise 2: Rollback a Deployment
Using the webapp Deployment from Exercise 1, update the image to an invalid image nginx:invalid-tag. Watch the rollout fail, then roll back to the previous working version.
Solution
# Update to invalid image
kubectl set image deployment/webapp nginx=nginx:invalid-tag
# Watch the rollout (it will stall)
kubectl rollout status deployment/webapp --timeout=30s
# Check pod status - you'll see ImagePullBackOff
kubectl get pods -l app=webapp
# View rollout history
kubectl rollout history deployment/webapp
# Rollback to the previous revision
kubectl rollout undo deployment/webapp
# Verify the rollback succeeded
kubectl rollout status deployment/webapp
kubectl describe deployment webapp | grep Image
Exercise 3: Blue/Green Deployment Switch
Create two Deployments: app-v1 (image nginx:1.27, label version: v1) and app-v2 (image nginx:1.28, label version: v2), both with the label app: myapp and 2 replicas each. Create a Service named myapp that initially points to v1. Then switch the Service to point to v2.
Solution
# Create v1 deployment
kubectl create deployment app-v1 --image=nginx:1.27 --replicas=2 --dry-run=client -o yaml | \
kubectl label --local -f - version=v1 --dry-run=client -o yaml | \
kubectl apply -f -
# It's simpler to use YAML for precise label control:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-v1
spec:
replicas: 2
selector:
matchLabels:
app: myapp
version: v1
template:
metadata:
labels:
app: myapp
version: v1
spec:
containers:
- name: nginx
image: nginx:1.27
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-v2
spec:
replicas: 2
selector:
matchLabels:
app: myapp
version: v2
template:
metadata:
labels:
app: myapp
version: v2
spec:
containers:
- name: nginx
image: nginx:1.28
kubectl apply -f deployments.yaml
# Create service pointing to v1
kubectl create service clusterip myapp --tcp=80:80 --dry-run=client -o yaml > svc.yaml
# Edit selector to: app: myapp, version: v1
kubectl apply -f svc.yaml
# Switch to v2
kubectl patch service myapp -p '{"spec":{"selector":{"app":"myapp","version":"v2"}}}'
# Verify
kubectl describe svc myapp | grep Selector
Exercise 4: Install and Manage a Helm Release
Add the Bitnami Helm repository. Install the bitnami/nginx chart as a release named web-server in the web namespace (create the namespace if needed). Then upgrade it to set replicaCount=3. Finally, rollback to revision 1.
Solution
# Add repo
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# Install
helm install web-server bitnami/nginx --namespace web --create-namespace
# Verify
helm list -n web
# Upgrade
helm upgrade web-server bitnami/nginx -n web --set replicaCount=3
# Check history
helm history web-server -n web
# Rollback to revision 1
helm rollback web-server 1 -n web
# Verify
helm list -n web
Exercise 5: Kustomize Overlay
Create a base directory with a simple nginx Deployment (2 replicas) and a Service. Then create a production overlay that changes the namespace to production, adds the prefix prod-, and increases replicas to 5. Preview the generated manifests.
Solution
# app/base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
# app/base/service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
# app/base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
# app/overlays/prod/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 5