Deploying to Kubernetes
Deployment Workflow
Deploying applications to Kubernetes involves preparing container images, creating deployment manifests, and managing the deployment lifecycle. Understanding this process is crucial for reliable production deployments.
Why this matters: Improper deployment practices lead to downtime, data loss, or performance issues. Kubernetes provides mechanisms for rolling updates, canary deployments, and automatic rollbacks to prevent these problems.
Building and Pushing Images
graph LR
A["Source Code"] -->B["Build Image
docker build"]
B -->C["Tag Image
registry/app:v1.0"]
C -->D["Push to Registry
docker push"]
D -->E["Kubernetes
Pulls Image"]
style D fill:#e1f5ff
style E fill:#fff3e0
# Build image
docker build -t myregistry.azurecr.io/myapp:v1.0 .
# Push to registry
docker push myregistry.azurecr.io/myapp:v1.0
Why private registries: Kubernetes pulls images from registries. Using private registries ensures only authorized images run in production and provides security scanning capabilities.
Creating Deployment Manifests
A complete deployment manifest defines the application, resources, networking, and policies.
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
labels:
app: api
version: v1
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: myregistry.azurecr.io/api:v1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5000
name: http
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 5000
initialDelaySeconds: 5
periodSeconds: 5
Key fields:
replicas- Number of pod copiesstrategy- How to update pods (rolling, recreate)livenessProbe- Detects if pod is healthy (kill and restart if failing)readinessProbe- Detects if pod is ready to receive trafficresources.requests- Minimum resources requiredresources.limits- Maximum resources allowed
Rolling Updates
Why rolling updates matter: Updating all pods simultaneously causes downtime. Rolling updates gradually replace old pods with new versions, maintaining availability.
# Update image version
kubectl set image deployment/api-server api=myregistry.azurecr.io/api:v1.1
# Monitor rollout progress
kubectl rollout status deployment/api-server
# View rollout history
kubectl rollout history deployment/api-server
# Rollback if issues detected
kubectl rollout undo deployment/api-server
Control update behavior:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # One extra pod during update
maxUnavailable: 0 # Never remove pods (maintain availability)
Canary Deployments
Deploy new version to small subset of traffic first, gradually increasing if stable.
# Version 1 (current production)
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-v1
spec:
replicas: 9
template:
metadata:
labels:
app: api
version: v1
spec:
containers:
- name: api
image: myregistry.azurecr.io/api:v1.0
---
# Version 2 (canary - 10% of traffic)
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-v2
spec:
replicas: 1
template:
metadata:
labels:
app: api
version: v2
spec:
containers:
- name: api
image: myregistry.azurecr.io/api:v2.0
Both deployments use the same service selector app: api, so the service load balances between both versions. Monitor v2 for errors. If stable, increase v2 replicas and decrease v1.
Why canary deployments: Limit blast radius of bugs. If new version has issues, only small user subset is affected.
Environment Configuration
Use ConfigMaps and Secrets for different environments without changing images.
# ConfigMap for development
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: development
data:
LOG_LEVEL: "DEBUG"
DATABASE_URL: "postgres://dev-db:5432/myapp"
---
# ConfigMap for production
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
LOG_LEVEL: "INFO"
DATABASE_URL: "postgres://prod-db:5432/myapp"
Use in deployment:
envFrom:
- configMapRef:
name: app-config
Why ConfigMaps: Build once, deploy anywhere. Same image runs in dev, staging, and production with different configurations.
Blue-Green Deployments
Run two complete production versions simultaneously. Switch traffic between them instantly.
# Deploy new version (green)
kubectl apply -f deployment-green.yaml
# Both versions running
kubectl get deployment
# blue-deployment 3/3
# green-deployment 3/3
# Test green version
kubectl port-forward svc/green-service 8080:80
# Switch traffic
kubectl patch service api-service -p '{"spec":{"selector":{"version":"green"}}}'
# or shorter: kubectl patch svc api-service -p '{"spec":{"selector":{"version":"green"}}}'
# Keep blue for instant rollback if needed
# Switch back: kubectl patch service api-service -p '{"spec":{"selector":{"version":"blue"}}}'
Why blue-green: Zero-downtime deployments with instant rollback capability.
Deployment Checklist
# 1. Build and test image locally
docker build -t myapp:v1.0 .
docker run myapp:v1.0
# 2. Push to registry
docker push myregistry.azurecr.io/myapp:v1.0
# 3. Update deployment manifest
# - Update image tag
# - Verify resource limits
# - Check health probes
# 4. Deploy to staging first
kubectl apply -f deployment.yaml -n staging
# 5. Verify staging deployment
kubectl rollout status deployment/myapp -n staging
# or shorter: kubectl rollout status deploy/myapp -n staging
# 6. Test staging version thoroughly
# 7. Deploy to production
kubectl apply -f deployment.yaml -n production
# 8. Monitor rollout
kubectl rollout status deployment/myapp -n production
# or shorter: kubectl rollout status deploy/myapp -n production
# 9. Monitor metrics and logs
kubectl logs -f deployment/myapp -n production
# or shorter: kubectl logs -f deploy/myapp -n production
Common Pitfalls
- Not setting resource requests - Kubernetes can't schedule pods properly
- Forgetting health checks - Dead containers keep running
- Immediate full deployment - Use rolling updates or canary for safety
- Using latest image tag - Unpredictable versions; always use specific tags
- No rollback plan - Always keep previous version available
Key Takeaways
- Build and push container images to registries before Kubernetes deployment
- Deployment manifests define desired state; Kubernetes ensures it's maintained
- Rolling updates gradually replace pods, maintaining availability
- Probes (liveness, readiness) enable Kubernetes to detect and recover from failures
- Canary deployments limit blast radius by testing with small traffic subset first
- Blue-green deployments enable zero-downtime updates with instant rollback
- ConfigMaps and Secrets enable same image to run across environments
Next Steps: Create deployment manifests for applications, practice rolling updates on test cluster, implement canary deployments for safer production changes.