Deployment Manifest
YAMLdeployment.yaml — 3 replicas of a Node.js app
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: default
spec:
replicas: 3 # Run 3 identical pods
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myregistry.azurecr.io/myapp:v1
ports:
- containerPort: 3000
resources:
requests:
cpu: "250m" # 0.25 vCPU minimum
memory: "256Mi" # 256 MB minimum
limits:
cpu: "500m" # 0.5 vCPU maximum
memory: "512Mi" # 512 MB maximum
env:
- name: NODE_ENV
value: production
Service Manifest
YAMLservice.yaml — expose app with Azure Load Balancer
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: LoadBalancer # Creates Azure Load Balancer with public IP
selector:
app: myapp # Routes to pods with this label
ports:
- protocol: TCP
port: 80 # External port
targetPort: 3000 # Container port
Applying Manifests
kubectlApply manifests and check status
# Apply deployment and service
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
# Or apply all YAMLs in a directory
kubectl apply -f ./k8s/
# Check deployment status
kubectl get deployments
kubectl get pods
kubectl get services
# Wait for external IP (may take 1-2 minutes)
kubectl get service myapp-service --watch
# Output when ready:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# myapp-service LoadBalancer 10.0.1.5 20.1.2.3 80:30000/TCP
Secrets and ConfigMaps
YAMLSecret and ConfigMap — inject into pod
# Secret (base64 encoded values)
apiVersion: v1
kind: Secret
metadata:
name: myapp-secrets
type: Opaque
stringData: # stringData auto-encodes to base64
DATABASE_URL: "mongodb://user:pass@host/db"
API_KEY: "mysecretkey"
---
# ConfigMap (plain text)
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
data:
NODE_ENV: "production"
LOG_LEVEL: "info"
YAMLReference Secret and ConfigMap in Deployment
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: myapp-secrets
key: DATABASE_URL
- name: NODE_ENV
valueFrom:
configMapKeyRef:
name: myapp-config
key: NODE_ENV
Health Probes
YAMLLiveness and readiness probes
livenessProbe: # Is the container alive? Restart if fails.
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe: # Is the container ready for traffic? Remove from LB if fails.
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
| Probe | Fails → Action | Purpose |
|---|---|---|
| Liveness | Container restarted | Detect deadlocked/stuck containers |
| Readiness | Removed from Service endpoints | Prevent traffic before app is ready |
Rolling Updates
kubectlUpdate image and roll back
# Update image to new version
kubectl set image deployment/myapp myapp=myregistry.azurecr.io/myapp:v2
# Watch rollout progress
kubectl rollout status deployment/myapp
# Check rollout history
kubectl rollout history deployment/myapp
# Rollback to previous version
kubectl rollout undo deployment/myapp
Viewing Logs and Debugging
kubectlDebugging commands
# View pod logs
kubectl logs myapp-pod-xyz
# Follow logs in real time
kubectl logs -f myapp-pod-xyz
# View logs for all pods with label
kubectl logs -l app=myapp
# Describe a pod (events, status, config)
kubectl describe pod myapp-pod-xyz
# Execute command inside pod
kubectl exec -it myapp-pod-xyz -- /bin/sh
# Get events (useful for troubleshooting)
kubectl get events --sort-by=.lastTimestamp
AZ-104 Exam Tip Know that kubectl apply -f deploys manifests. Know the difference between liveness (restart) and readiness (remove from load balancer) probes. Know that rolling updates update pods one at a time. Know kubectl rollout undo rolls back to the previous version.