• Smallest deployable unit; usually 1 container per Pod
  • Creation flow: create → schedule → pull image → run container

Choose the right workload resource

ResourceUse WhenKey Fields
PodOne-off debugging, static single podspec.containers
DeploymentStateless app, rolling updates, scalingspec.replicas, spec.strategy
ReplicaSetRarely directly; Deployment manages itspec.replicas, spec.selector
StatefulSetDatabases, stable identity, ordered scalingspec.serviceName, volumeClaimTemplates
DaemonSetOne pod per node: logging, monitoring, networkingNo replicas field
JobRun-to-completion: batch, migrationsspec.completions, spec.parallelism
CronJobScheduled tasks: backups, reportsspec.schedule, spec.jobTemplate

Pod phases

PhaseMeaning
PendingAccepted; image/container not ready
RunningAt least one container running/starting
SucceededAll containers exited OK
FailedAt least one container failed
UnknownState unavailable
  • Container states (separate): Waiting, Running, Terminated

kubectl: Pods

kubectl run hazelcast --image=hazelcast:5.1.7 --port=5701 \
  --env="DNS_DOMAIN=cluster" --labels="app=hazelcast,env=prod"
kubectl apply -f pod.yaml
kubectl get po / kubectl get po <n> -o wide / -o yaml
kubectl describe po <n>          # events for debugging
kubectl logs <n> -f / kubectl logs <n> -p   # -p = previous instance
kubectl exec -it <n> -- /bin/sh
kubectl exec <n> -- env
kubectl run busybox --image=busybox:1.36.1 --rm -it --restart=Never -- wget <ip>:80
kubectl delete po <n> / kubectl delete po <n> --now   # exam time-saver

Pod configuration

env:
- name: SPRING_PROFILES_ACTIVE
  value: prod
kubectl run mypod --image=busybox:1.36.1 -o yaml --dry-run=client > pod.yaml -- <cmd>
# everything after -- becomes args (overrides CMD)

Lifecycle hooks

HookWhenTypical use
postStartImmediately after container startsRegister with service, send notification
preStopBefore container receives SIGTERMDrain connections, flush buffers
spec:
  containers:
  - name: app
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo started > /tmp/ready"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "sleep 15"]   # delay SIGTERM so LB drains traffic
  • Hooks run in the container: must be available in the image
  • postStart runs async with the main process (not before it)
  • preStop must complete before SIGTERM is sent to the main process

Graceful termination

  1. Pod marked Terminating; removed from Service endpoints
  2. preStop hook runs (if defined)
  3. SIGTERM sent to main process
  4. Kubernetes waits terminationGracePeriodSeconds (default 30s)
  5. SIGKILL if still running
spec:
  terminationGracePeriodSeconds: 60
  containers:
  - name: app
    image: nginx
    lifecycle:
      preStop:
        exec:
          command: ["/usr/sbin/nginx", "-s", "quit"]

Namespaces

NSPurpose
defaultUser workloads without explicit NS
kube-systemSystem components (CoreDNS, etc.)
kube-public, kube-node-leaseSystem: don't use
kubectl create namespace code-red
kubectl run pod --image=nginx -n code-red
kubectl get po -n code-red
kubectl config set-context --current --namespace=code-red
kubectl config view --minify | grep namespace:
kubectl delete namespace code-red   # cascades: deletes all objects in NS

Exam gotchas

  • Set namespace with config set-context if specified
  • kubectl logs -p after CrashLoopBackOff: previous container logs
  • Graceful shutdown: preStop hook + increase terminationGracePeriodSeconds if app needs more drain time
  • postStart is not a readiness check: use readinessProbe for traffic gating

References

Kubectl run