A Pod
A Pod wraps one or more containers that always run on the same node and share a network namespace — they share one IP, and can reach each other over localhost. Most Pods run exactly one application container.
apiVersion: v1
kind: Pod
metadata:
name: app
labels:
app: docktionary
spec:
containers:
- name: app
image: docktionary/app:1.4.0
ports:
- containerPort: 3000
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"You'll rarely create a bare Pod directly in practice — if it dies, nothing brings it back. That's what a Deployment is for.
A Deployment
A Deployment manages a ReplicaSet of identical Pods built from one template, and knows how to roll out a change to that template gradually instead of all at once.
apiVersion: apps/v1
kind: Deployment
metadata:
name: docktionary-app
spec:
replicas: 3
selector:
matchLabels:
app: docktionary
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: docktionary
spec:
containers:
- name: app
image: docktionary/app:1.4.0
ports:
- containerPort: 3000
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
livenessProbe:
httpGet:
path: /health
port: 3000
periodSeconds: 10
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"Applying and inspecting
kubectl apply -f deployment.yaml
kubectl get deployments
kubectl get pods -l app=docktionary
kubectl describe deployment docktionary-app
kubectl rollout status deployment/docktionary-appRolling out a new version
kubectl set image deployment/docktionary-app app=docktionary/app:1.5.0
kubectl rollout status deployment/docktionary-app
# Something's wrong -- go back to the previous version
kubectl rollout undo deployment/docktionary-app
# See rollout history
kubectl rollout history deployment/docktionary-appmaxUnavailable and maxSurge control the pace: with the values above, Kubernetes takes down at most one old Pod and brings up at most one extra new Pod at a time, so the Deployment always has at least replicas - 1 Pods ready to serve traffic.
Readiness vs. liveness probes
A readiness probe controls whether a Pod receives traffic from a Service — fail it, and the Pod is pulled out of rotation without being restarted. A liveness probe controls whether the kubelet restarts the container at all. Mixing these up is one of the most common causes of a Deployment that restarts in a loop under load.
More than one container in a Pod
A Pod's containers share network and, optionally, volumes — which is the whole point of putting more than one in a Pod. An init container runs to completion before the main container starts; a sidecar runs alongside it for the Pod's whole life.
spec:
initContainers:
- name: wait-for-db
image: busybox:1.36
command: ["sh", "-c", "until nc -z db 5432; do sleep 1; done"]
containers:
- name: app
image: docktionary/app:1.4.0
- name: log-shipper
image: fluent/fluent-bit:3.1
volumeMounts:
- name: logs
mountPath: /var/log/app
volumes:
- name: logs
emptyDir: {}app and log-shipper share the logs volume (an emptyDir — storage that lives only as long as the Pod) so the sidecar can tail files the main container writes, without the main container knowing or caring that shipping happens at all.
Controlling where Pods land
The scheduler picks a node based on requested resources by default, but affinity rules add further constraints: keep related Pods together, keep replicas apart, or stick to specific nodes.
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: docktionary
topologyKey: kubernetes.io/hostname
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: docktionaryThe anti-affinity rule here keeps every docktionary Pod on a different node — losing one node can’t take out two replicas at once. topologySpreadConstraints does a similar job across availability zones: with maxSkew: 1, no zone can hold more than one Pod more than the least-loaded zone.