DaemonSets and Jobs

5 minute read

Not every workload fits the Deployment or StatefulSet model. DaemonSets ensure a Pod runs on every node (or a subset of nodes), while Jobs and CronJobs handle one-off and scheduled tasks that run to completion.

DaemonSets

What is a DaemonSet?

A DaemonSet ensures that all (or some) nodes run a copy of a Pod. As nodes are added to the cluster, Pods are automatically added to them. As nodes are removed, Pods are garbage collected.

Common use cases:

  • Log collection (Fluentd, Filebeat)
  • Node monitoring (Prometheus Node Exporter, Datadog agent)
  • Cluster storage (Ceph, GlusterFS)
  • Network plugins (Calico, Cilium)
  • Security agents (Falco)

DaemonSet YAML

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  labels:
    app: fluentd
spec:
  selector:
    matchLabels:
      app: fluentd
  template:
    metadata:
      labels:
        app: fluentd
    spec:
      containers:
      - name: fluentd
        image: fluentd:v1.16
        resources:
          limits:
            memory: "200Mi"
            cpu: "100m"
          requests:
            memory: "100Mi"
            cpu: "50m"
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: containers
          mountPath: /var/lib/docker/containers
          readOnly: true
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: containers
        hostPath:
          path: /var/lib/docker/containers
kubectl apply -f daemonset.yaml

# One Pod per node
kubectl get pods -l app=fluentd -o wide

Target Specific Nodes

Use nodeSelector or affinity to run on specific nodes:

spec:
  template:
    spec:
      nodeSelector:
        disk: ssd          # Only nodes with label disk=ssd

      # Or with tolerations for control plane nodes
      tolerations:
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule

DaemonSet Update Strategies

Strategy Behavior
RollingUpdate (default) Updates Pods one node at a time
OnDelete Only updates when you manually delete old Pods
spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1     # Update 1 node at a time

DaemonSet Commands

kubectl get daemonsets          # List DaemonSets
kubectl describe ds fluentd    # Detailed info
kubectl rollout status ds fluentd  # Rollout status
kubectl delete ds fluentd      # Delete

Jobs

What is a Job?

A Job creates one or more Pods and ensures they run to completion. Unlike Deployments (which keep Pods running forever), Jobs exit when the work is done.

Use cases:

  • Database migrations
  • Batch processing
  • Data import/export
  • Sending bulk emails
  • Report generation

Basic Job

apiVersion: batch/v1
kind: Job
metadata:
  name: pi-calculator
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never     # Required: Never or OnFailure
  backoffLimit: 4              # Retry up to 4 times on failure
kubectl apply -f job.yaml

# Watch the Job
kubectl get jobs
kubectl get pods

# View the output
kubectl logs job/pi-calculator

Output:

NAME             COMPLETIONS   DURATION   AGE
pi-calculator    1/1           15s        20s

Parallel Jobs

Run multiple Pods in parallel:

apiVersion: batch/v1
kind: Job
metadata:
  name: batch-process
spec:
  completions: 10        # Total tasks to complete
  parallelism: 3         # Run 3 Pods at a time
  template:
    spec:
      containers:
      - name: worker
        image: busybox
        command: ["sh", "-c", "echo Processing item && sleep 5"]
      restartPolicy: Never

This runs 3 Pods in parallel until all 10 completions are done.

Job Completion Modes

Field Description
completions Number of successful completions needed
parallelism Max Pods running at the same time
backoffLimit Max retries before marking Job as failed (default: 6)
activeDeadlineSeconds Max time the Job can run
ttlSecondsAfterFinished Auto-delete completed Job after N seconds

Auto-Cleanup Completed Jobs

spec:
  ttlSecondsAfterFinished: 300   # Delete Job 5 minutes after completion

Job Failure Handling

spec:
  backoffLimit: 4                  # Retry up to 4 times
  activeDeadlineSeconds: 600       # Timeout after 10 minutes
  template:
    spec:
      restartPolicy: OnFailure     # Restart container in same Pod on failure
restartPolicy Behavior
Never Create a new Pod for each retry (old Pods preserved for debugging)
OnFailure Restart the container within the same Pod

CronJobs

What is a CronJob?

A CronJob creates Jobs on a schedule — like Unix cron. Perfect for periodic tasks.

CronJob YAML

apiVersion: batch/v1
kind: CronJob
metadata:
  name: daily-backup
spec:
  schedule: "0 2 * * *"           # Every day at 2:00 AM
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: my-backup-tool:1.0
            command: ["/backup.sh"]
            env:
            - name: BACKUP_TARGET
              value: "s3://my-bucket/backups"
          restartPolicy: OnFailure
  successfulJobsHistoryLimit: 3    # Keep last 3 successful Jobs
  failedJobsHistoryLimit: 1        # Keep last 1 failed Job
  concurrencyPolicy: Forbid        # Don't start new if previous is running

Cron Schedule Syntax

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

Common schedules:

Schedule Meaning
*/5 * * * * Every 5 minutes
0 * * * * Every hour
0 2 * * * Daily at 2:00 AM
0 0 * * 0 Weekly on Sunday at midnight
0 0 1 * * Monthly on the 1st at midnight

Concurrency Policies

Policy Behavior
Allow (default) Allows concurrent Jobs
Forbid Skips new Job if previous is still running
Replace Cancels running Job and starts a new one

CronJob Commands

kubectl get cronjobs              # List CronJobs
kubectl describe cronjob daily-backup
kubectl get jobs --watch          # Watch Jobs created by CronJob

# Manually trigger a CronJob
kubectl create job --from=cronjob/daily-backup manual-backup

Hands-On Example

Let’s create a DaemonSet, a Job, and a CronJob in Minikube:

# daemonset-monitor.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-monitor
spec:
  selector:
    matchLabels:
      app: node-monitor
  template:
    metadata:
      labels:
        app: node-monitor
    spec:
      containers:
      - name: monitor
        image: busybox
        command: ["sh", "-c", "while true; do echo $(hostname) - $(date) - Mem: $(cat /proc/meminfo | head -1); sleep 30; done"]
        resources:
          limits:
            cpu: "50m"
            memory: "32Mi"
---
# job-hello.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: hello-job
spec:
  completions: 3
  parallelism: 2
  ttlSecondsAfterFinished: 120
  template:
    spec:
      containers:
      - name: hello
        image: busybox
        command: ["sh", "-c", "echo Hello from $(hostname) at $(date) && sleep 3"]
      restartPolicy: Never
---
# cronjob-report.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: minutely-report
spec:
  schedule: "*/1 * * * *"
  successfulJobsHistoryLimit: 2
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: reporter
            image: busybox
            command: ["sh", "-c", "echo Report generated at $(date)"]
          restartPolicy: Never
kubectl apply -f daemonset-monitor.yaml
kubectl apply -f job-hello.yaml
kubectl apply -f cronjob-report.yaml

# Watch everything
kubectl get ds,jobs,cronjobs
kubectl get pods -w

Summary

Controller Purpose Runs Until
Deployment Stateless apps Forever (keeps running)
StatefulSet Stateful apps Forever (keeps running)
DaemonSet One Pod per node Forever (per node)
Job One-off tasks Completion
CronJob Scheduled tasks Completion (repeatedly)

What’s Next?

Now let’s learn about Ingress — the Kubernetes resource that provides HTTP/HTTPS routing to your Services, enabling you to expose multiple services through a single entry point with path-based and host-based routing.

Next: Ingress →

Updated: