What is Kubernetes?
Kubernetes (K8s — "K" + 8 letters + "s") is an open-source container orchestration platform. It automates:
- Deploying containers across a cluster of machines
- Scaling (up/down based on load)
- Self-healing (restart crashed containers, reschedule on failed nodes)
- Rolling updates and rollbacks (zero-downtime deployments)
- Service discovery and load balancing
Analogy: Docker is like a shipping container.
Kubernetes is like the global logistics system —
it decides which ships carry which containers,
reroutes around storms (node failures),
and scales the fleet when shipping volume spikes.
Why not just run Docker directly?
- Docker on one machine → single point of failure
- Manual scaling → can't handle traffic spikes automatically
- Manual recovery → a crashed container stays crashed
- No built-in networking between machines
- No rolling updates (zero-downtime deploys)
Kubernetes solves all of these at scale.
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌───────────────────────────────┐ │
│ │ Control Plane │ │
│ │ ┌──────────┐ ┌─────────┐ │ │
│ │ │ API Server│ │ etcd │ │ ← cluster state stored here │
│ │ └──────────┘ └─────────┘ │ │
│ │ ┌──────────┐ ┌──────────────┐│ │
│ │ │Scheduler │ │Ctrl Manager ││ │
│ │ └──────────┘ └──────────────┘│ │
│ └───────────────────────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Node 1 │ │ Node 2 │ │ Node 3 │ ← Worker │
│ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ Nodes │
│ │ │ Pod │ │ │ │ Pod │ │ │ │ Pod │ │ │
│ │ │ Pod │ │ │ │ Pod │ │ │ │ Pod │ │ │
│ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │
│ │ kubelet │ │ kubelet │ │ kubelet │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
- API Server: the front door — all kubectl commands and controllers go through it
- etcd: distributed key-value store — the source of truth for all cluster state
- Scheduler: decides which node runs each pod
- Controller Manager: watches state and reconciles actual → desired (e.g., restarts crashed pods)
- kubelet: agent on each node — ensures containers in pods are running
- Pod: the smallest deployable unit — one or more containers sharing network and storage
Core Objects
Pod — The Basic Unit
# pod.yaml — rarely created directly in practice; use Deployments
apiVersion: v1
kind: Pod
metadata:
name: my-app
labels:
app: my-app
version: "1.0"
spec:
containers:
- name: app
image: my-registry/my-app:1.0
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
resources:
requests:
memory: "128Mi" # minimum guaranteed
cpu: "250m" # 250 millicores = 0.25 vCPU
limits:
memory: "256Mi" # never exceed (OOMKilled if exceeded)
cpu: "500m" # throttled if exceeded (not killed)
livenessProbe: # restart pod if this fails
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe: # remove from load balancer until this passes
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
Deployment — Managing Pod Replicas
# deployment.yaml — the standard way to run stateless apps
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
spec:
replicas: 3 # run 3 pods at all times
selector:
matchLabels:
app: my-app
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # at most 1 pod down during update
maxSurge: 1 # at most 1 extra pod during update
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-registry/my-app:1.1 # update this to roll out new version
# ... (same as pod spec above)
# Deployment commands
kubectl apply -f deployment.yaml # create or update
kubectl get deployments # list deployments
kubectl get pods # list pods
kubectl describe deployment my-app # detailed status
kubectl rollout status deployment/my-app # watch rollout progress
# Rollback if something goes wrong
kubectl rollout undo deployment/my-app
kubectl rollout undo deployment/my-app --to-revision=3
# Scale manually
kubectl scale deployment my-app --replicas=5
Service — Stable Network Endpoint
Pods are ephemeral — they get new IPs when restarted. Services provide a stable IP and DNS name, and load-balance across all matching pods:
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
spec:
selector:
app: my-app # route to all pods with this label
ports:
- port: 80 # service port
targetPort: 3000 # pod port
type: ClusterIP # internal only (default)
# type: NodePort # expose on each node's IP (dev/testing)
# type: LoadBalancer # provision cloud load balancer (production)
Service types:
- ClusterIP: only accessible within the cluster. Use for internal services.
- NodePort: exposes on a high port on every node (30000-32767). Useful for dev.
- LoadBalancer: provisions a cloud load balancer (AWS ALB, GCP LB). Use for public-facing services.
- ExternalName: DNS alias to an external service.
Ingress — HTTP Routing
Ingress handles HTTP/HTTPS routing — one cloud load balancer, many services:
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- api.example.com
secretName: tls-secret
rules:
- host: api.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-svc
port:
number: 80
ConfigMap & Secret
# configmap.yaml — non-sensitive configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
APP_URL: "https://api.example.com"
# secret.yaml — sensitive data (base64 encoded, not encrypted by default — use Sealed Secrets or AWS KMS)
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
password: cGFzc3dvcmQxMjM= # base64 encode: echo -n "password123" | base64
username: cG9zdGdyZXM=
# Use in deployment
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
# Or mount entire configmap as environment
envFrom:
- configMapRef:
name: app-config
Autoscaling
Horizontal Pod Autoscaler (HPA)
# hpa.yaml — scale pods based on CPU/memory
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70 # scale out when avg CPU > 70%
- type: Resource
resource:
name: memory
target:
type: AverageValue
averageValue: 200Mi
Cluster Autoscaler
When HPA needs more pods but no nodes have capacity, the Cluster Autoscaler adds new nodes to the cluster (and removes them when idle). Configured at the cloud provider level (ASG on AWS, MIG on GCP).
Namespace — Logical Isolation
kubectl create namespace staging
kubectl create namespace production
# Deploy to a specific namespace
kubectl apply -f deployment.yaml -n production
# Switch default namespace
kubectl config set-context --current --namespace=production
Use namespaces to: separate environments (dev/staging/prod in one cluster), separate teams, apply different resource quotas and network policies.
StatefulSet — For Stateful Apps
Databases and other stateful apps need stable network identity and persistent storage. Use StatefulSet instead of Deployment:
# statefulset.yaml (e.g., for Redis cluster)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis # creates headless service (stable DNS per pod)
replicas: 3
selector:
matchLabels:
app: redis
template:
spec:
containers:
- name: redis
image: redis:7-alpine
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates: # creates a PVC for each pod
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: gp3
resources:
requests:
storage: 10Gi
# Pods get stable names: redis-0, redis-1, redis-2
# DNS: redis-0.redis.namespace.svc.cluster.local
Common Interview Questions
Practice
- Basic: Deploy a Node.js API to a local Kubernetes cluster (minikube). Create Deployment (3 replicas), Service (ClusterIP), and Ingress.
- Config: Store database connection string in a Secret and app configuration in a ConfigMap. Mount them in your Deployment as environment variables.
- HPA: Add an HPA to scale your Deployment between 2 and 10 replicas based on CPU utilization > 70%. Use
kubectl runto generate load and observe scaling. - Rolling Update: Update your Deployment to a new image version. Watch the rolling update with
kubectl rollout status. Introduce a bug (bad image), observe it, and roll back.
Next: CI/CD — automating builds, tests, and deployments.