Chapter 8: Application Deployment
Authored by syscook.dev
What is Application Deployment in Kubernetes?
Application deployment in Kubernetes involves packaging, configuring, and deploying applications to the cluster. This includes managing application lifecycle, updates, rollbacks, and ensuring high availability and scalability.
Key Concepts:
- Deployment Strategies: Rolling updates, blue-green, canary
- Application Lifecycle: Build, package, deploy, update, rollback
- Configuration Management: Environment-specific configurations
- Health Checks: Liveness, readiness, startup probes
- Scaling: Horizontal and vertical scaling
- Monitoring: Application metrics and logging
Why Use Different Deployment Strategies?
1. Rolling Updates
Zero-downtime updates with gradual replacement of pods.
# Example: Rolling update deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-deployment
namespace: production
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 2
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-server
image: nginx:1.20
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
2. Blue-Green Deployment
Instant switch between two identical production environments.
# Example: Blue deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-blue
namespace: production
labels:
app: web-app
version: blue
spec:
replicas: 3
selector:
matchLabels:
app: web-app
version: blue
template:
metadata:
labels:
app: web-app
version: blue
spec:
containers:
- name: web-server
image: nginx:1.20
ports:
- containerPort: 80
3. Canary Deployment
Gradual rollout to a subset of users for testing.
# Example: Canary deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-canary
namespace: production
labels:
app: web-app
version: canary
spec:
replicas: 1
selector:
matchLabels:
app: web-app
version: canary
template:
metadata:
labels:
app: web-app
version: canary
spec:
containers:
- name: web-server
image: nginx:1.21
ports:
- containerPort: 80
How to Deploy Applications?
1. Complete Application Stack
Database Deployment
# Example: PostgreSQL database deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-deployment
namespace: production
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:13
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: "myapp"
- name: POSTGRES_USER
value: "user"
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-pvc
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
namespace: production
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
API Deployment
# Example: API service deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: myapp/api:latest
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: postgres-secret
key: database-url
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: log_level
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: api-service
namespace: production
spec:
selector:
app: api
ports:
- port: 8080
targetPort: 8080
Frontend Deployment
# Example: Frontend deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-deployment
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: myapp/frontend:latest
ports:
- containerPort: 80
env:
- name: API_URL
value: "http://api-service:8080"
- name: ENVIRONMENT
value: "production"
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
namespace: production
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 80
type: LoadBalancer
2. Deployment with Ingress
Ingress Configuration
# Example: Ingress for application
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: production
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls-secret
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
Practical Examples
1. Complete Application Deployment
Step 1: Create Namespace and Secrets
#!/bin/bash
# create-namespace-secrets.sh
# Create namespace
kubectl create namespace production
# Create secrets
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
namespace: production
type: Opaque
stringData:
password: "password123"
database-url: "postgres://user:password123@postgres-service:5432/myapp"
EOF
# Create configmap
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
log_level: "info"
environment: "production"
EOF
echo "Namespace, secrets, and configmap created successfully!"
Step 2: Deploy Database
#!/bin/bash
# deploy-database.sh
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: production
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-deployment
namespace: production
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:13
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: "myapp"
- name: POSTGRES_USER
value: "user"
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-pvc
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
namespace: production
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
EOF
echo "Database deployed successfully!"
Step 3: Deploy Application
#!/bin/bash
# deploy-application.sh
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: myapp/api:latest
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: postgres-secret
key: database-url
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: log_level
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: api-service
namespace: production
spec:
selector:
app: api
ports:
- port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-deployment
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: myapp/frontend:latest
ports:
- containerPort: 80
env:
- name: API_URL
value: "http://api-service:8080"
- name: ENVIRONMENT
value: "production"
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
namespace: production
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 80
type: LoadBalancer
EOF
echo "Application deployed successfully!"
Best Practices
1. Health Checks
# Good: Comprehensive health checks
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
2. Resource Management
# Good: Proper resource limits
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
3. Deployment Strategy
# Good: Rolling update strategy
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 2
Common Pitfalls and Solutions
1. Missing Health Checks
# ❌ Bad: No health checks
spec:
containers:
- name: app
image: myapp:latest
# ✅ Good: Proper health checks
spec:
containers:
- name: app
image: myapp:latest
livenessProbe:
httpGet:
path: /health
port: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
2. Inadequate Resource Limits
# ❌ Bad: No resource limits
spec:
containers:
- name: app
image: myapp:latest
# ✅ Good: Proper resource limits
spec:
containers:
- name: app
image: myapp:latest
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
Conclusion
Application deployment in Kubernetes requires careful planning and configuration. By understanding:
- What different deployment strategies are and their use cases
- Why proper configuration is crucial for application reliability
- How to deploy applications with health checks and resource management
You can create robust, scalable applications that run reliably in production environments. Proper deployment practices ensure that your applications are maintainable, secure, and performant.
Next Steps
- Practice with different deployment strategies
- Learn about monitoring and logging
- Move on to Chapter 9: Monitoring & Logging
This tutorial is part of the Kubernetes Mastery series by syscook.dev