Kubernetes Intro¶
Kubernetes is the orchestrator that ate the world — it manages containers at scale , handles deployments , scaling , networking , and self-healing. It's also the most over-engineered piece of infrastructure you'll encounter in your career K8s solves problems you don't have until you have them. If Docker Compose works for your team , stick with it. But if you're running 20 microservices across 10 servers and deploying three times a day , K8s changes the game
What K8s Actually Is¶
A distributed system for running containers across a cluster of machines It handles: * Scheduling — place containers on machines with available resources * Self-healing — restart failed containers , replace unhealthy ones * Scaling — add or remove replicas based on load * Rolling updates — deploy new versions without downtime * Service discovery — containers find each other by name * Storage orchestration — mount storage of your choice * Secret management — store and expose secrets safely
Architecture — The Control Plane¶
flowchart TB
subgraph Control_Plane[Control Plane]
API[API Server]
Scheduler[Scheduler]
CM[Controller Manager]
etcd[etcd - cluster brain]
API --> etcd
end
Control_Plane --> Worker1
Control_Plane --> Worker2
Control_Plane --> Worker3
subgraph Worker1[Worker 1]
P1a[Pod]
P1b[Pod]
end
subgraph Worker2[Worker 2]
P2a[Pod]
P2b[Pod]
end
subgraph Worker3[Worker 3]
P3a[Pod]
P3b[Pod]
end Pods — The Atomic Unit¶
A pod is the smallest deployable unit — one or more containers that share network and storage Usually one container per pod (sidecar pattern is the exception)
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
environment: production
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /readyz
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
Deployments — Declarative Updates¶
A Deployment manages ReplicaSets — it handles rolling updates , rollbacks , and desired state
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Can spin up 1 extra pod during update
maxUnavailable: 0 # Zero downtime — always keep all pods serving
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 3000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: myapp-secrets
key: database_url
resources:
limits:
memory: "512Mi"
cpu: "500m"
Rolling update behavior:
flowchart LR
subgraph Before
P1[Pod1] --- P2[Pod2] --- P3[Pod3]
end
subgraph Step1
P1n[Pod1-new] --- P2a[Pod2] --- P3a[Pod3]
end
subgraph Step2
P1n2[Pod1-new] --- P2n[Pod2-new] --- P3b[Pod3]
end
subgraph Step3
P1n3[Pod1-new] --- P2n2[Pod2-new] --- P3n[Pod3-new]
end
Before --> Step1 --> Step2 --> Step3 Zero downtime throughout the process
Services — Stable Network Endpoints¶
Pods come and go — they get IPs assigned dynamically. Services provide a stable DNS name that load balances across pods
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp # Routes traffic to pods with this label
ports:
- protocol: TCP
port: 80 # Service port
targetPort: 3000 # Container port
type: ClusterIP # Internal — only accessible within cluster
Service types: * ClusterIP — internal virtual IP , only accessible inside the cluster * NodePort — exposes on each node's IP at a static port (30000-32767) * LoadBalancer — provisions a cloud load balancer (AWS ALB , GCP LB) * Ingress — not a service type , but handles HTTP routing (hostnames , paths)
# Ingress — HTTP routing
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
spec:
rules:
- host: api.myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
ConfigMaps and Secrets — Configuration Objects¶
ConfigMaps — non-sensitive config:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
NODE_ENV: "production"
LOG_LEVEL: "info"
API_URL: "https://api.example.com"
Secrets — sensitive data (base64 encoded — not encrypted):
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
database_url: cG9zdGdyZXM6Ly91c2VyOnBhc3NAZGI6NTQzMi9teWFwcA==
jwt_secret: c3VwZXJzZWNyZXRrZXkxMjM=
Using them in a pod:
spec:
containers:
- name: myapp
env:
- name: NODE_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: NODE_ENV
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database_url
envFrom:
- configMapRef:
name: app-config # Inject ALL configmap values
Namespaces — Logical Clusters¶
Namespaces partition a K8s cluster into isolated environments for different teams or projects
# List namespaces
kubectl get namespaces
# Deploy to specific namespace
kubectl apply -f deployment.yaml --namespace=production
# Or set in the YAML
metadata:
namespace: production
Common namespace structure:
default — default for resources without a namespace
kube-system — K8s system components (don't touch)
kube-public — publicly readable config
production — your production workloads
staging — staging workloads
development — dev workloads
monitoring — Prometheus, Grafana, etc.
Kubectl Basics — The Only Commands You Need¶
# Cluster info
kubectl cluster-info
kubectl get nodes
# Pod operations
kubectl get pods
kubectl get pods -o wide # More detail (node IP , pod IP)
kubectl get pods --all-namespaces
kubectl describe pod myapp-pod # Detailed status and events
kubectl logs myapp-pod
kubectl logs -f myapp-pod # Follow logs
kubectl logs --tail=50 myapp-pod # Last 50 lines
kubectl exec -it myapp-pod -- bash # Shell into container
kubectl exec myapp-pod -- env # Run command in container
# Workload operations
kubectl get deployments
kubectl get services
kubectl get configmaps
kubectl get secrets
# Apply/delete resources
kubectl apply -f deployment.yaml
kubectl delete -f deployment.yaml
kubectl delete pod myapp-pod # Deployment recreates it
# Scaling
kubectl scale deployment myapp --replicas=5
# Rolling updates
kubectl set image deployment/myapp myapp=myapp:v2
kubectl rollout status deployment/myapp
kubectl rollout undo deployment/myapp # Rollback
# Port forwarding (tunnel to a pod for debugging)
kubectl port-forward pod/myapp-pod 3000:3000
# Resource usage
kubectl top pods
kubectl top nodes
Minikube — Local K8s Cluster¶
For local development when you can't afford cloud clusters
# Install minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# Start cluster
minikube start --cpus=4 --memory=8192
# Check status
minikube status
# Open dashboard
minikube dashboard
# Get cluster IP
minikube ip
# Tunnel for LoadBalancer services
minikube tunnel
# Stop cluster
minikube stop
The Reality Check¶
K8s isn't for everyone. Here's when to use it: * Multiple microservices that need to scale independently * You're deploying multiple times per day * You need rolling updates and rollbacks * You have a team that can manage the complexity
When you don't need it: * One or two backend services — Docker Compose is fine * Small team with limited ops experience — you'll drown in YAML * Static workload that never changes — just rent a VPS * Your monthly cloud bill is under $1000 — spend the savings on dev time
next → back to DevOps home