Kubernetes Pods and Deployments
Kubernetes has a reputation for complexity that's only half-deserved. The complexity is mostly in operating a cluster, not in using one. From a developer's perspective, k8s is a small set of YAML resource types and a control loop that keeps the cluster matching what you declared. Once you internalize the loop, the rest follows.
The control loop, in one sentence
You write desired state (YAML); controllers compare desired state to observed state and act to make them match.
Pod: the smallest deployable unit
A pod is one or more containers sharing a network namespace and (usually) a couple of volumes. You almost never create raw pods — you let a higher-level resource manage them. But understanding the pod is the foundation.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
resources:
requests: { cpu: 50m, memory: 64Mi }
limits: { cpu: 200m, memory: 128Mi }
Deployment: manage pods at scale
Deployments wrap a ReplicaSet which manages a set of identical pods. You specify how many replicas you want; the controller scales up or down to match.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels: { app: web }
strategy:
type: RollingUpdate
rollingUpdate: { maxSurge: 1, maxUnavailable: 0 }
template:
metadata:
labels: { app: web }
spec:
containers:
- name: web
image: ghcr.io/myorg/web:v1.2.3
readinessProbe:
httpGet: { path: /healthz, port: 8080 }
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
initialDelaySeconds: 10
Roll out by changing image: and applying. Rolling update keeps capacity up during the change.
Service: stable network identity
Pods come and go; their IPs change. A Service is a stable virtual IP that load-balances across all pods matching a label selector.
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector: { app: web }
ports:
- port: 80
targetPort: 8080
type: ClusterIP # internal only; use LoadBalancer for external
ConfigMap and Secret
apiVersion: v1
kind: ConfigMap
metadata: { name: web-config }
data:
LOG_LEVEL: info
CACHE_TTL: "300"
---
apiVersion: v1
kind: Secret
metadata: { name: web-secrets }
type: Opaque
stringData:
DATABASE_URL: postgres://...
What kubectl gives you
kubectl apply -f deployment.yaml
kubectl get pods -l app=web
kubectl describe pod web-7f9c-abcde # events, conditions, why it's not ready
kubectl logs -f web-7f9c-abcde -c web
kubectl exec -it web-7f9c-abcde -- sh
kubectl port-forward svc/web 8080:80
kubectl rollout status deploy/web
kubectl rollout undo deploy/web
When k8s isn't worth it
If you have one server and three services, docker-compose is fine. If you have ten servers and you'd otherwise be writing scripts to keep them in sync, k8s is paying for itself. The break-even is somewhere between "small" and "annoying to operate by hand."