Pod Spec Deep Dive
A Pod is the smallest unit Kubernetes schedules — one or more containers sharing a network namespace and storage. Understanding the spec (containers, volumes, probes, resources, security context) is the foundation for every workload kind: Deployments, Jobs, StatefulSets, DaemonSets.
containers, volumes, probes, resources
EXAMPLE
# 1) Minimal Pod
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels: { app: web }
spec:
containers:
- name: web
image: nginx:1.27-alpine
ports:
- containerPort: 80
# 2) Multi-container — sidecar pattern
apiVersion: v1
kind: Pod
metadata: { name: web-with-logs }
spec:
containers:
- name: web
image: nginx:1.27-alpine
volumeMounts:
- { name: logs, mountPath: /var/log/nginx }
- name: log-shipper
image: fluent/fluent-bit:3.0
volumeMounts:
- { name: logs, mountPath: /logs, readOnly: true }
volumes:
- name: logs
emptyDir: {}
# Containers in a Pod SHARE: network (localhost), IPC, and any mounted volumes.
# 3) Resources — requests + limits
spec:
containers:
- name: web
image: nginx
resources:
requests: # scheduler reserves this
cpu: 100m # 0.1 CPU
memory: 128Mi
limits: # enforced cap; OOMKill or throttle past this
cpu: 500m
memory: 256Mi
# Memory limit exceeded → OOMKilled. CPU limit exceeded → throttled.
# Always set requests; consider setting limits.
# 4) Probes — liveness, readiness, startup
spec:
containers:
- name: web
image: nginx
startupProbe:
httpGet: { path: /healthz, port: 80 }
failureThreshold: 30
periodSeconds: 5
readinessProbe:
httpGet: { path: /ready, port: 80 }
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet: { path: /live, port: 80 }
periodSeconds: 10
failureThreshold: 3
# startupProbe — gates other probes until startup completes (slow boots)
# readinessProbe — controls whether Service traffic is routed
# livenessProbe — restarts the container if it fails
# 5) Environment variables
spec:
containers:
- env:
- { name: NODE_ENV, value: production }
- name: DATABASE_URL
valueFrom:
secretKeyRef: { name: app-secrets, key: DATABASE_URL }
- name: LOG_LEVEL
valueFrom:
configMapKeyRef: { name: app-config, key: LOG_LEVEL }
- name: POD_IP
valueFrom: { fieldRef: { fieldPath: status.podIP } }
envFrom:
- configMapRef: { name: app-config }
- secretRef: { name: app-secrets }
# 6) Volumes — emptyDir, configMap, secret, hostPath, persistentVolumeClaim
spec:
containers:
- volumeMounts:
- { name: cache, mountPath: /cache }
- { name: config, mountPath: /etc/app, readOnly: true }
- { name: secret, mountPath: /etc/keys, readOnly: true }
- { name: persistent, mountPath: /data }
volumes:
- name: cache
emptyDir: { sizeLimit: 1Gi }
- name: config
configMap: { name: app-config, defaultMode: 0444 }
- name: secret
secret: { secretName: app-secrets, defaultMode: 0400 }
- name: persistent
persistentVolumeClaim: { claimName: app-data }
# 7) Security context — least-privilege containers
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
runAsNonRoot: true
seccompProfile: { type: RuntimeDefault }
containers:
- name: web
image: nginx
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ['ALL']
add: ['NET_BIND_SERVICE']
volumeMounts:
- { name: tmp, mountPath: /tmp }
- { name: cache, mountPath: /var/cache/nginx }
- { name: run, mountPath: /var/run }
volumes:
- { name: tmp, emptyDir: {} }
- { name: cache, emptyDir: {} }
- { name: run, emptyDir: {} }
# 8) Init containers — run BEFORE app containers, must complete successfully
spec:
initContainers:
- name: migrate
image: my-app:1.2
command: ['npm', 'run', 'migrate']
containers:
- { name: app, image: my-app:1.2 }
# 9) Scheduling — node selection
spec:
nodeSelector:
disktype: ssd
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector: { matchLabels: { app: web } }
topologyKey: kubernetes.io/hostname
tolerations:
- key: 'dedicated'
operator: 'Equal'
value: 'workload'
effect: 'NoSchedule'
priorityClassName: high-priority
# 10) Lifecycle hooks — graceful shutdown
spec:
containers:
- lifecycle:
preStop:
exec:
command: ['sh', '-c', 'sleep 5 && nginx -s quit']
terminationGracePeriodSeconds: 30
# Pod entering Termination: preStop runs → SIGTERM → grace period → SIGKILL if still alive.
# 11) Ephemeral debug — sidecar at runtime
kubectl debug -it my-pod --image=busybox:1.36 --target=web
# Attaches a temporary debug container sharing the same namespaces. No edit to spec.
# 12) Pod status — what to check when things fail
kubectl describe pod my-pod
kubectl get events --sort-by=.lastTimestamp
kubectl logs my-pod -c web --previous
kubectl exec -it my-pod -c web -- sh
# Conditions to watch:
# PodScheduled — does it have a node?
# ContainersReady — all containers passing readiness?
# Initialized — init containers complete?
# Ready — endpoint visible to Services?
# 13) Common bugs
# • requests too high → Pending: 0/N nodes available; insufficient cpu/memory
# • Missing resources.requests → noisy-neighbour evictions under pressure
# • Liveness probe too aggressive → restart loop on slow boots
# • Readiness probe missing → Service routes traffic before app is ready
# • Mount path conflicts (two volumes at /data) → silent override
# • configMap mounted as defaultMode 0644 but expects 0400 — perms wrong, secret hint
# • root user (runAsUser: 0) — fails Pod Security Admission
# • Containers can't write to /tmp because readOnlyRootFilesystem: true → mount emptyDir at /tmp
# • Image pull errors — check imagePullSecrets, registry auth, image tag exists
# • Mounted Secret in env var loaded once — restart Pod when secret rotates
Why it matters
A Pod is one or more containers sharing network and volumes. Always set resources.requests, configure readinessProbe + livenessProbe + startupProbe distinctly, run non-root with a tight securityContext, and use initContainers for ordered startup tasks. Production workloads come from Deployments/StatefulSets/Jobs, but the Pod spec inside them is what matters.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# Key fields: resources (req/limits), readinessProbe, livenessProbe, # env, volumeMounts, securityContext.Try it Yourself »
Discussion
Loading…