Kubernetes (K8s) is the industry-standard platform for container orchestration. It automates deployment, scaling, and management of containerized applications across clusters of machines.
What is Kubernetes?
Kubernetes is an open-source container orchestration platform originally developed by Google. It solves several critical problems:
- Automated deployment: Deploy containers across multiple machines automatically
- Self-healing: Restart failed containers and replace unhealthy instances
- Scaling: Scale applications up or down based on demand
- Load balancing: Distribute network traffic efficiently
- Rolling updates: Update applications without downtime
- Resource management: Optimize CPU and memory usage across clusters
Think of Kubernetes as an operating system for your datacenter or cloud infrastructure.
Kubernetes Architecture
Kubernetes follows a master-worker architecture with two main components:
Control Plane (Master Node)
The control plane manages the entire cluster and makes decisions about scheduling, scaling, and maintaining desired state.
Key components:
- API Server: Frontend for Kubernetes control plane; all communications go through this
- etcd: Distributed key-value store; stores all cluster data
- Scheduler: Assigns pods to nodes based on resource requirements
- Controller Manager: Runs controllers that handle routine tasks (replication, endpoints, service accounts)
- Cloud Controller Manager: Integrates with cloud provider APIs (AWS, Azure, GCP)
Worker Nodes
Worker nodes run your application containers.
Key components:
- kubelet: Agent that ensures containers are running as expected
- kube-proxy: Maintains network rules for pod communication
- Container Runtime: Software that runs containers (Docker, containerd, CRI-O)
Core Kubernetes Objects
1. Pods
A Pod is the smallest deployable unit in Kubernetes. It represents one or more containers that share storage and network resources.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
Key characteristics:
- Pods are ephemeral (temporary)
- Each pod gets its own IP address
- Containers in a pod share the same network namespace
- Usually you don’t create pods directly (use Deployments instead)
2. Deployments
Deployments manage ReplicaSets and provide declarative updates for Pods.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
Deployments handle:
- Rolling updates and rollbacks
- Scaling (manual and automatic)
- Self-healing (restart failed pods)
- Version management
3. Services
Services provide stable networking endpoints for Pods. Since Pod IPs change when pods restart, Services act as a stable abstraction layer.
ClusterIP (default)
Internal-only service, accessible within the cluster.
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: ClusterIP
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
NodePort
Exposes service on each node’s IP at a static port.
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
LoadBalancer
Exposes service externally using cloud provider’s load balancer.
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
4. ConfigMaps and Secrets
ConfigMaps store non-sensitive configuration data.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_url: "postgres://db.example.com:5432/mydb"
log_level: "info"
Secrets store sensitive information (base64 encoded).
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4= # base64 encoded "admin"
password: cGFzc3dvcmQ= # base64 encoded "password"
Using ConfigMap and Secret in a Pod:
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:1.0
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: app-config
key: database_url
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
5. Namespaces
Namespaces provide logical isolation within a cluster. They’re useful for multi-tenancy and environment separation.
apiVersion: v1
kind: Namespace
metadata:
name: production
Common namespace pattern:
kubectl create namespace development
kubectl create namespace staging
kubectl create namespace production
Deploy to specific namespace:
kubectl apply -f deployment.yaml -n production
6. Persistent Volumes and Claims
PersistentVolume (PV): Cluster-level storage resource.
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-data
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /mnt/data
PersistentVolumeClaim (PVC): Request for storage by a user.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
Using PVC in a Pod:
apiVersion: v1
kind: Pod
metadata:
name: app-with-storage
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- mountPath: /data
name: app-data
volumes:
- name: app-data
persistentVolumeClaim:
claimName: pvc-data
7. Ingress
Ingress manages external HTTP/HTTPS access to services in the cluster.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
Ingress provides:
- SSL/TLS termination
- Name-based virtual hosting
- Path-based routing
- Load balancing
Kubernetes Networking
Pod-to-Pod Communication
All pods can communicate with each other without NAT, regardless of which node they’re on. Kubernetes assigns a unique IP to each pod.
# From one pod, ping another pod
kubectl exec -it pod1 -- ping <pod2-ip>
Service Discovery
Kubernetes provides DNS-based service discovery. Services are automatically registered in cluster DNS.
Format: <service-name>.<namespace>.svc.cluster.local
Example:
# From any pod in the same namespace
curl http://nginx-service:80
# From pod in different namespace
curl http://nginx-service.production.svc.cluster.local:80
Network Policies
Control traffic flow between pods using Network Policies.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
This policy allows only pods with label app: frontend to access pods with label app: backend on port 8080.
Resource Management
Resource Requests and Limits
resources:
requests:
memory: "256Mi"
cpu: "500m"
limits:
memory: "512Mi"
cpu: "1000m"
- Requests: Minimum guaranteed resources
- Limits: Maximum allowed resources
Quality of Service (QoS) Classes
Based on requests and limits, pods are assigned QoS classes:
- Guaranteed: requests = limits for all containers
- Burstable: requests < limits
- BestEffort: no requests or limits set
Horizontal Pod Autoscaling (HPA)
Automatically scale pods based on metrics.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx-deployment
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Practical kubectl Commands
Cluster Information
# Cluster info
kubectl cluster-info
# Node information
kubectl get nodes
kubectl describe node <node-name>
Working with Pods
# List pods
kubectl get pods
kubectl get pods -n production
kubectl get pods --all-namespaces
# Detailed pod info
kubectl describe pod <pod-name>
# Pod logs
kubectl logs <pod-name>
kubectl logs -f <pod-name> # follow logs
kubectl logs <pod-name> -c <container-name> # specific container
# Execute command in pod
kubectl exec -it <pod-name> -- /bin/bash
kubectl exec <pod-name> -- ls /app
Working with Deployments
# List deployments
kubectl get deployments
# Create/update deployment
kubectl apply -f deployment.yaml
# Scale deployment
kubectl scale deployment nginx-deployment --replicas=5
# Update image
kubectl set image deployment/nginx-deployment nginx=nginx:1.26
# Rollout status
kubectl rollout status deployment/nginx-deployment
# Rollout history
kubectl rollout history deployment/nginx-deployment
# Rollback
kubectl rollout undo deployment/nginx-deployment
kubectl rollout undo deployment/nginx-deployment --to-revision=2
Working with Services
# List services
kubectl get services
kubectl get svc
# Describe service
kubectl describe svc nginx-service
# Port forwarding (for testing)
kubectl port-forward svc/nginx-service 8080:80
Debugging
# Get events
kubectl get events --sort-by=.metadata.creationTimestamp
# Debug with ephemeral container (K8s 1.23+)
kubectl debug -it <pod-name> --image=busybox --target=<container-name>
# Copy files from pod
kubectl cp <pod-name>:/path/to/file /local/path
# Get resource usage
kubectl top nodes
kubectl top pods
Common Deployment Patterns
1. Multi-Container Pod Pattern (Sidecar)
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
- name: main-app
image: myapp:1.0
ports:
- containerPort: 8080
- name: log-shipper
image: fluent-bit:2.0
volumeMounts:
- name: logs
mountPath: /var/log
volumes:
- name: logs
emptyDir: {}
2. Init Containers
Run before main containers start, useful for setup tasks.
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
spec:
initContainers:
- name: db-migration
image: myapp-migration:1.0
command: ['sh', '-c', 'run-migrations.sh']
containers:
- name: app
image: myapp:1.0
3. Blue-Green Deployment
Maintain two identical environments and switch traffic between them.
# Blue deployment
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
---
# Service pointing to blue
apiVersion: v1
kind: Service
metadata:
name: app-service
spec:
selector:
app: myapp
version: blue # Switch to green when ready
ports:
- port: 80
4. Canary Deployment
Gradually roll out new version to a small subset of users.
# Stable deployment (90%)
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 (10%)
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
apiVersion: v1
kind: Service
metadata:
name: app-service
spec:
selector:
app: myapp # Matches both stable and canary
ports:
- port: 80
Health Checks
Liveness Probe
Checks if container is running. Kubernetes restarts unhealthy containers.
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
Readiness Probe
Checks if container is ready to accept traffic.
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 2
successThreshold: 1
failureThreshold: 3
Startup Probe
Checks if application has started (useful for slow-starting containers).
startupProbe:
httpGet:
path: /startup
port: 8080
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 30
Best Practices
Security
- Use specific image tags, not
latest - Run containers as non-root
- Use read-only root filesystems when possible
- Set resource limits to prevent resource exhaustion
- Use Network Policies to restrict traffic
- Enable RBAC (Role-Based Access Control)
- Scan images for vulnerabilities
- Use Secrets for sensitive data, not ConfigMaps
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
Resource Management
- Always set resource requests and limits
- Use Horizontal Pod Autoscaler for variable workloads
- Use PodDisruptionBudgets for high availability
- Configure appropriate QoS classes
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: myapp
Configuration Management
- Use ConfigMaps for environment-specific configuration
- Use Secrets for sensitive data
- Version your manifests in Git
- Use Helm or Kustomize for templating
- Separate concerns: one manifest per resource type
Monitoring and Logging
- Implement health checks (liveness, readiness, startup)
- Collect logs centrally (ELK, Loki, etc.)
- Use Prometheus for metrics
- Set up alerts for critical conditions
- Monitor resource usage (kubectl top, metrics-server)
Deployment Strategy
- Use rolling updates as default
- Implement proper health checks before declaring pod ready
- Use appropriate update strategy (RollingUpdate vs Recreate)
- Test in lower environments first
- Have rollback plan ready
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
Namespace Organization
- Use namespaces to separate environments
- Apply resource quotas per namespace
- Use labels consistently
- Implement network policies per namespace
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: production
spec:
hard:
requests.cpu: "50"
requests.memory: "100Gi"
limits.cpu: "100"
limits.memory: "200Gi"
persistentvolumeclaims: "10"
Troubleshooting Common Issues
Pod Not Starting
# Check pod status
kubectl get pods
kubectl describe pod <pod-name>
# Common reasons:
# - Image pull errors (check image name/tag)
# - Insufficient resources
# - Volume mount issues
# - Init container failures
Service Not Reachable
# Check service endpoints
kubectl get endpoints <service-name>
# Test service from another pod
kubectl run test-pod --rm -it --image=busybox -- sh
wget -qO- http://<service-name>:<port>
# Check selector labels match
kubectl get pods --show-labels
High Memory/CPU Usage
# Check resource usage
kubectl top pods
kubectl top nodes
# Check if HPA is configured
kubectl get hpa
# Scale manually if needed
kubectl scale deployment <name> --replicas=<number>
CrashLoopBackOff
# Check logs from crashed container
kubectl logs <pod-name> --previous
# Common causes:
# - Application errors
# - Missing dependencies
# - Failed health checks
# - Configuration issues
Production Checklist
Before deploying to production:
- Resource requests and limits defined
- Health checks configured (liveness, readiness)
- Secrets used for sensitive data
- Images use specific tags (not
latest) - Security context configured (non-root user)
- Network policies in place
- PodDisruptionBudget configured for HA
- Monitoring and logging enabled
- Backup strategy for persistent data
- Resource quotas set for namespace
- RBAC rules configured
- Ingress/LoadBalancer configured properly
- SSL/TLS certificates managed
- Update strategy tested
- Rollback procedure documented
References
- https://kubernetes.io/docs/home/
- https://kubernetes.io/docs/concepts/
- https://kubernetes.io/docs/reference/kubectl/
- https://kubernetes.io/docs/tasks/