Workloads

Workload Resources

Pods, probes, Deployments, StatefulSets, DaemonSets, Jobs, and CronJobs.

Pods

Docs: K8s Docs - Pods

  • Smallest deployable unit in Kubernetes
  • A pod runs one or more containers that share the same network namespace and storage

Pod spec essentials

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  restartPolicy: Always          # Always (default), OnFailure, Never
  containers:
    - name: nginx
      image: nginx:1.25
      ports:
        - containerPort: 80
      resources:
        requests:
          cpu: "100m"
          memory: "128Mi"
        limits:
          cpu: "500m"
          memory: "256Mi"

Multi-container patterns

Init Containers — run to completion before app containers start

spec:
  initContainers:
    - name: init-db
      image: busybox
      command: ['sh', '-c', 'until nslookup db-service; do sleep 2; done']
  containers:
    - name: app
      image: myapp:1.0

Sidecar Containers — run alongside the main container for the pod's lifetime

  • Common use cases: log collectors, proxies, config reloaders
spec:
  initContainers:
    - name: log-shipper
      image: fluentd
      restartPolicy: Always       # makes it a sidecar (runs for pod's lifetime)
  containers:
    - name: app
      image: myapp:1.0

Restart Policies

  • Always (default) — always restart, used by Deployments/StatefulSets/DaemonSets
  • OnFailure — restart only on non-zero exit code, used by Jobs
  • Never — never restart

Probes

Docs: K8s Docs - Probes

  • Probes let the kubelet check container health and control traffic routing
  • Three probe types serve different purposes:
ProbePurposeFailure action
LivenessIs the container still running?Restarts the container
ReadinessIs the container ready to serve traffic?Removes pod from Service endpoints
StartupHas the container finished starting?Blocks liveness/readiness until it succeeds

Probe mechanisms

  • httpGet — HTTP GET to a path/port; 200–399 = success
  • tcpSocket — TCP connection to a port; connection established = success
  • exec — runs a command inside the container; exit code 0 = success

Common fields

initialDelaySeconds: 5      # wait before first probe (default 0)
periodSeconds: 10            # interval between probes (default 10)
timeoutSeconds: 1            # probe timeout (default 1)
failureThreshold: 3          # failures before taking action (default 3)
successThreshold: 1          # successes to be considered healthy (default 1)

Liveness probe — httpGet

spec:
  containers:
    - name: app
      image: myapp:1.0
      livenessProbe:
        httpGet:
          path: /healthz
          port: 8080
        initialDelaySeconds: 10
        periodSeconds: 5

Readiness probe — tcpSocket

spec:
  containers:
    - name: db
      image: postgres:16
      readinessProbe:
        tcpSocket:
          port: 5432
        initialDelaySeconds: 5
        periodSeconds: 10

Startup probe — exec

spec:
  containers:
    - name: legacy-app
      image: legacy:2.0
      startupProbe:
        exec:
          command: ["cat", "/tmp/started"]
        failureThreshold: 30
        periodSeconds: 10          # gives up to 30×10 = 300s to start
      livenessProbe:
        httpGet:
          path: /healthz
          port: 8080
        periodSeconds: 5
  • Use startup probes for slow-starting containers to avoid premature liveness kills
  • Liveness and readiness probes do not run until the startup probe succeeds

ReplicaSets

Docs: K8s Docs - ReplicaSet

  • Ensures a specified number of pod replicas are running at all times
  • Uses label selectors to identify which pods it manages
  • Rarely created directly — Deployments manage ReplicaSets automatically
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.25

Deployments

Docs: K8s Docs - Deployments

  • Manages ReplicaSets and provides declarative updates for pods
  • Supports rolling updates and rollbacks
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  strategy:
    type: RollingUpdate            # RollingUpdate (default) or Recreate
    rollingUpdate:
      maxSurge: 1                  # max pods above desired count during update
      maxUnavailable: 0            # max pods unavailable during update
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.25

Strategy types

  • RollingUpdate (default) — gradually replaces old pods with new ones
    • maxSurge — how many extra pods can be created (absolute number or percentage)
    • maxUnavailable — how many pods can be unavailable (absolute number or percentage)
  • Recreate — kills all existing pods before creating new ones (causes downtime)

Rolling updates & rollbacks

# update the image (triggers a rolling update)
kubectl set image deployment/nginx-deploy nginx=nginx:1.26

# check rollout status
kubectl rollout status deployment/nginx-deploy

# view rollout history
kubectl rollout history deployment/nginx-deploy

# view a specific revision
kubectl rollout history deployment/nginx-deploy --revision=2

# rollback to the previous revision
kubectl rollout undo deployment/nginx-deploy

# rollback to a specific revision
kubectl rollout undo deployment/nginx-deploy --to-revision=1

# pause and resume a rollout
kubectl rollout pause deployment/nginx-deploy
kubectl rollout resume deployment/nginx-deploy

StatefulSets

Docs: K8s Docs - StatefulSets

  • For stateful applications that require stable network identity and persistent storage
  • Pods are created in order (0, 1, 2...) and deleted in reverse order
  • Each pod gets a stable hostname: <statefulset-name>-<ordinal>
  • Requires a headless service (clusterIP: None)
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres-headless     # must reference a headless service
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:16
          ports:
            - containerPort: 5432
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:               # each pod gets its own PVC
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi
  • DNS for each pod: <pod-name>.<service-name>.<namespace>.svc.cluster.local
  • e.g., postgres-0.postgres-headless.default.svc.cluster.local

DaemonSets

Docs: K8s Docs - DaemonSet

  • Ensures a copy of a pod runs on every node (or a subset of nodes)
  • When a new node joins the cluster, the DaemonSet pod is automatically added
  • Use cases: log collectors, monitoring agents, network plugins, storage daemons
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  selector:
    matchLabels:
      app: fluentd
  template:
    metadata:
      labels:
        app: fluentd
    spec:
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          effect: NoSchedule        # allow scheduling on control plane nodes
      containers:
        - name: fluentd
          image: fluentd:v1.16

Jobs

Docs: K8s Docs - Jobs

  • Runs pods to completion — creates one or more pods and ensures they succeed
  • Pods are not restarted after successful completion
apiVersion: batch/v1
kind: Job
metadata:
  name: pi-calc
spec:
  completions: 5                    # total successful completions needed
  parallelism: 2                    # how many pods run at the same time
  backoffLimit: 4                   # max retries before marking as failed
  activeDeadlineSeconds: 300        # timeout for the entire job
  template:
    spec:
      restartPolicy: OnFailure      # must be OnFailure or Never
      containers:
        - name: pi
          image: perl:5.34
          command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]

CronJobs

Docs: K8s Docs - CronJobs

  • Creates Jobs on a repeating schedule (cron syntax)
apiVersion: batch/v1
kind: CronJob
metadata:
  name: daily-backup
spec:
  schedule: "0 2 * * *"             # minute hour day-of-month month day-of-week
  concurrencyPolicy: Forbid          # Allow (default), Forbid, Replace
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  startingDeadlineSeconds: 200       # deadline if a scheduled run is missed
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: backup
              image: busybox
              command: ["/bin/sh", "-c", "echo Running backup at $(date)"]

Schedule syntax

┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sun=0)
│ │ │ │ │
* * * * *

concurrencyPolicy

  • Allow (default) — allows concurrent Job runs
  • Forbid — skips the new run if the previous is still running
  • Replace — cancels the currently running Job and starts a new one

Useful Commands

# --- Pods ---
kubectl run nginx --image=nginx                           # create a pod
kubectl run nginx --image=nginx --dry-run=client -o yaml  # generate YAML
kubectl get pods -o wide
kubectl describe pod <pod-name>
kubectl logs <pod-name> -c <container-name>               # logs for a specific container
kubectl exec -it <pod-name> -- /bin/sh

# --- Deployments ---
kubectl create deployment nginx --image=nginx --replicas=3
kubectl scale deployment nginx --replicas=5
kubectl set image deployment/nginx nginx=nginx:1.26
kubectl rollout status deployment/nginx
kubectl rollout undo deployment/nginx

# --- StatefulSets ---
kubectl get statefulsets
kubectl describe statefulset <name>
kubectl scale statefulset <name> --replicas=5

# --- DaemonSets ---
kubectl get daemonsets -A
kubectl describe daemonset <name>

# --- Jobs & CronJobs ---
kubectl create job test-job --image=busybox -- echo "hello"
kubectl get jobs
kubectl get cronjobs
kubectl create cronjob test-cron --image=busybox --schedule="*/5 * * * *" -- echo "hello"
kubectl delete job <job-name>