Kubernetes (K8s) has become the standard for container orchestration. This guide covers the essential concepts and patterns you need to get started.
Core Concepts#
Pods#
The smallest deployable unit in Kubernetes:
1# pod.yaml
2apiVersion: v1
3kind: Pod
4metadata:
5 name: web-app
6 labels:
7 app: web
8spec:
9 containers:
10 - name: app
11 image: myapp:1.0.0
12 ports:
13 - containerPort: 3000
14 resources:
15 requests:
16 memory: "128Mi"
17 cpu: "100m"
18 limits:
19 memory: "256Mi"
20 cpu: "500m"
21 env:
22 - name: NODE_ENV
23 value: "production"
24 - name: DATABASE_URL
25 valueFrom:
26 secretKeyRef:
27 name: app-secrets
28 key: database-urlDeployments#
Manage pod replicas and updates:
1# deployment.yaml
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5 name: web-app
6 labels:
7 app: web
8spec:
9 replicas: 3
10 selector:
11 matchLabels:
12 app: web
13 strategy:
14 type: RollingUpdate
15 rollingUpdate:
16 maxSurge: 1
17 maxUnavailable: 0
18 template:
19 metadata:
20 labels:
21 app: web
22 spec:
23 containers:
24 - name: app
25 image: myapp:1.0.0
26 ports:
27 - containerPort: 3000
28 readinessProbe:
29 httpGet:
30 path: /health
31 port: 3000
32 initialDelaySeconds: 5
33 periodSeconds: 10
34 livenessProbe:
35 httpGet:
36 path: /health
37 port: 3000
38 initialDelaySeconds: 15
39 periodSeconds: 20Services#
Expose pods to network traffic:
1# service.yaml
2apiVersion: v1
3kind: Service
4metadata:
5 name: web-app-service
6spec:
7 selector:
8 app: web
9 ports:
10 - protocol: TCP
11 port: 80
12 targetPort: 3000
13 type: ClusterIP
14
15---
16# LoadBalancer for external access
17apiVersion: v1
18kind: Service
19metadata:
20 name: web-app-lb
21spec:
22 selector:
23 app: web
24 ports:
25 - protocol: TCP
26 port: 80
27 targetPort: 3000
28 type: LoadBalancerIngress#
Route external traffic:
1# ingress.yaml
2apiVersion: networking.k8s.io/v1
3kind: Ingress
4metadata:
5 name: web-app-ingress
6 annotations:
7 nginx.ingress.kubernetes.io/rewrite-target: /
8 cert-manager.io/cluster-issuer: letsencrypt-prod
9spec:
10 tls:
11 - hosts:
12 - app.example.com
13 secretName: app-tls
14 rules:
15 - host: app.example.com
16 http:
17 paths:
18 - path: /
19 pathType: Prefix
20 backend:
21 service:
22 name: web-app-service
23 port:
24 number: 80
25 - path: /api
26 pathType: Prefix
27 backend:
28 service:
29 name: api-service
30 port:
31 number: 80Configuration Management#
ConfigMaps#
Non-sensitive configuration:
1# configmap.yaml
2apiVersion: v1
3kind: ConfigMap
4metadata:
5 name: app-config
6data:
7 LOG_LEVEL: "info"
8 API_URL: "https://api.example.com"
9 config.json: |
10 {
11 "features": {
12 "darkMode": true,
13 "analytics": true
14 }
15 }
16
17---
18# Using ConfigMap in a pod
19spec:
20 containers:
21 - name: app
22 envFrom:
23 - configMapRef:
24 name: app-config
25 volumeMounts:
26 - name: config-volume
27 mountPath: /app/config
28 volumes:
29 - name: config-volume
30 configMap:
31 name: app-config
32 items:
33 - key: config.json
34 path: config.jsonSecrets#
Sensitive data management:
1# secret.yaml
2apiVersion: v1
3kind: Secret
4metadata:
5 name: app-secrets
6type: Opaque
7stringData:
8 database-url: "postgresql://user:pass@host:5432/db"
9 api-key: "secret-api-key"
10
11---
12# Using secrets
13spec:
14 containers:
15 - name: app
16 env:
17 - name: DATABASE_URL
18 valueFrom:
19 secretKeyRef:
20 name: app-secrets
21 key: database-urlPersistent Storage#
PersistentVolumeClaim#
1# pvc.yaml
2apiVersion: v1
3kind: PersistentVolumeClaim
4metadata:
5 name: data-pvc
6spec:
7 accessModes:
8 - ReadWriteOnce
9 resources:
10 requests:
11 storage: 10Gi
12 storageClassName: standard
13
14---
15# Using PVC in deployment
16spec:
17 containers:
18 - name: app
19 volumeMounts:
20 - name: data
21 mountPath: /data
22 volumes:
23 - name: data
24 persistentVolumeClaim:
25 claimName: data-pvcStatefulSets#
For stateful applications:
1# statefulset.yaml
2apiVersion: apps/v1
3kind: StatefulSet
4metadata:
5 name: postgres
6spec:
7 serviceName: postgres
8 replicas: 3
9 selector:
10 matchLabels:
11 app: postgres
12 template:
13 metadata:
14 labels:
15 app: postgres
16 spec:
17 containers:
18 - name: postgres
19 image: postgres:15
20 ports:
21 - containerPort: 5432
22 volumeMounts:
23 - name: data
24 mountPath: /var/lib/postgresql/data
25 volumeClaimTemplates:
26 - metadata:
27 name: data
28 spec:
29 accessModes: ["ReadWriteOnce"]
30 resources:
31 requests:
32 storage: 20GiScaling#
Horizontal Pod Autoscaler#
1# hpa.yaml
2apiVersion: autoscaling/v2
3kind: HorizontalPodAutoscaler
4metadata:
5 name: web-app-hpa
6spec:
7 scaleTargetRef:
8 apiVersion: apps/v1
9 kind: Deployment
10 name: web-app
11 minReplicas: 2
12 maxReplicas: 10
13 metrics:
14 - type: Resource
15 resource:
16 name: cpu
17 target:
18 type: Utilization
19 averageUtilization: 70
20 - type: Resource
21 resource:
22 name: memory
23 target:
24 type: Utilization
25 averageUtilization: 80Vertical Pod Autoscaler#
1# vpa.yaml
2apiVersion: autoscaling.k8s.io/v1
3kind: VerticalPodAutoscaler
4metadata:
5 name: web-app-vpa
6spec:
7 targetRef:
8 apiVersion: apps/v1
9 kind: Deployment
10 name: web-app
11 updatePolicy:
12 updateMode: "Auto"
13 resourcePolicy:
14 containerPolicies:
15 - containerName: app
16 minAllowed:
17 cpu: 100m
18 memory: 128Mi
19 maxAllowed:
20 cpu: 2
21 memory: 4GiCommon Patterns#
Sidecar Pattern#
1spec:
2 containers:
3 - name: app
4 image: myapp:1.0.0
5 ports:
6 - containerPort: 3000
7 - name: log-shipper
8 image: fluentd:latest
9 volumeMounts:
10 - name: logs
11 mountPath: /var/log/app
12 volumes:
13 - name: logs
14 emptyDir: {}Init Containers#
1spec:
2 initContainers:
3 - name: wait-for-db
4 image: busybox
5 command:
6 - sh
7 - -c
8 - |
9 until nc -z postgres-service 5432; do
10 echo "Waiting for database..."
11 sleep 2
12 done
13 - name: run-migrations
14 image: myapp:1.0.0
15 command: ["npm", "run", "migrate"]
16 containers:
17 - name: app
18 image: myapp:1.0.0Jobs and CronJobs#
1# cronjob.yaml
2apiVersion: batch/v1
3kind: CronJob
4metadata:
5 name: backup
6spec:
7 schedule: "0 2 * * *"
8 jobTemplate:
9 spec:
10 template:
11 spec:
12 containers:
13 - name: backup
14 image: backup-tool:latest
15 env:
16 - name: S3_BUCKET
17 value: "backups"
18 restartPolicy: OnFailureNetworking Policies#
1# network-policy.yaml
2apiVersion: networking.k8s.io/v1
3kind: NetworkPolicy
4metadata:
5 name: api-network-policy
6spec:
7 podSelector:
8 matchLabels:
9 app: api
10 policyTypes:
11 - Ingress
12 - Egress
13 ingress:
14 - from:
15 - podSelector:
16 matchLabels:
17 app: web
18 ports:
19 - protocol: TCP
20 port: 3000
21 egress:
22 - to:
23 - podSelector:
24 matchLabels:
25 app: postgres
26 ports:
27 - protocol: TCP
28 port: 5432Essential Commands#
1# Get resources
2kubectl get pods
3kubectl get deployments
4kubectl get services
5
6# Describe resources
7kubectl describe pod web-app-xyz
8
9# View logs
10kubectl logs web-app-xyz
11kubectl logs -f web-app-xyz # Follow
12kubectl logs web-app-xyz -c sidecar # Specific container
13
14# Execute commands
15kubectl exec -it web-app-xyz -- /bin/sh
16
17# Apply configurations
18kubectl apply -f deployment.yaml
19kubectl apply -f ./manifests/
20
21# Scale deployments
22kubectl scale deployment web-app --replicas=5
23
24# Rolling updates
25kubectl set image deployment/web-app app=myapp:2.0.0
26kubectl rollout status deployment/web-app
27kubectl rollout undo deployment/web-app
28
29# Port forwarding
30kubectl port-forward pod/web-app-xyz 8080:3000
31kubectl port-forward service/web-app-service 8080:80
32
33# Debug
34kubectl get events
35kubectl top pods
36kubectl top nodesBest Practices#
- Always set resource requests and limits
- Use readiness and liveness probes
- Implement proper labels and selectors
- Store secrets securely (consider external secret managers)
- Use namespaces for isolation
- Implement network policies
- Set up proper monitoring and logging
- Use GitOps for deployments
Conclusion#
Kubernetes provides powerful primitives for container orchestration. Start with the basics—Pods, Deployments, Services—and gradually adopt more advanced features as your needs grow. Focus on understanding the core concepts before diving into complex patterns.