Files
rootnode-academy/content/root/root-06-kubernetes-application-workloads/m03-jobs-cronjobs-daemonsets/01-lesson-jobs-cronjobs-daemonsets.md
T
ced4568andClaude Sonnet 5 86ea035e9b feat(root): author workloads curriculum
root-06-m02-deployments-scaling-updates — a new, full gold-standard-
pattern module: why Deployments/ReplicaSets exist, how a rolling update
actually progresses, and what rollback restores. Lesson, demonstration
(a healthy rollout vs. one stalled on ImagePullBackOff), knowledge
check, guided exercise (planning a safe rollout strategy), real Labs
(rolling-update-task, deployment-rollback), and a reflection.

root-06-m03-jobs-cronjobs-daemonsets — a new PARTIAL module: Jobs,
CronJobs, and DaemonSets as distinct workload shapes from a
Deployment's always-on model. Lesson + knowledge check + real Labs
(job-task, cronjob-task).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:06:00 -05:00

3.9 KiB

Jobs, CronJobs, and DaemonSets: The Other Workload Shapes

Everything in the previous module assumed a long-running application that should always have N replicas up. Not every workload looks like that. Kubernetes has three other primitives for genuinely different shapes of work — using a Deployment for any of these would be the wrong tool, not just a less elegant one.

Job: run to completion, exactly once (or a fixed number of times)

A Job creates one or more Pods and considers itself done when they exit successfully — it does NOT restart a Pod that exits with success, and it DOES retry one that fails, up to a configured limit. This is fundamentally different from a Deployment, which expects its Pods to run forever and treats any exit as something to replace.

Use a Job for: a database migration, a batch data-processing task, a one-off cleanup script — anything with a defined "finished" state.

apiVersion: batch/v1
kind: Job
metadata:
  name: migrate-db
spec:
  template:
    spec:
      containers:
      - name: migrate
        image: myapp:latest
        command: ["./migrate.sh"]
      restartPolicy: Never
  backoffLimit: 3

CronJob: a Job, on a schedule

A CronJob doesn't run Pods itself — it creates a new Job on a cron schedule (schedule: "0 2 * * *" for "every day at 2am"), and that Job behaves exactly as described above. Use a CronJob for anything that should run periodically and finish: nightly backups, scheduled reports, periodic cleanup.

A CronJob that reliably fails to complete (an image that always crashes, for example) will keep creating new Jobs on schedule, each failing the same way — this is a real, common way to silently exhaust cluster resources (job/pod history accumulating) if nobody's watching.

DaemonSet: exactly one Pod per node, automatically

A DaemonSet doesn't declare a replica count at all — it ensures exactly one matching Pod runs on every node in the cluster (or every node matching a selector), and automatically adds a Pod when a new node joins. Use a DaemonSet for per-node infrastructure: a log-shipping agent, a node-level monitoring exporter, a network plugin component — things that fundamentally need to exist once per machine, not "N copies somewhere."

The decision in one pass

You need... Use
Always-on, N identical copies, restarted forever Deployment
Run once (or a few times) until it finishes successfully Job
The above, but on a recurring schedule CronJob
Exactly one copy on every node DaemonSet

Instructor Notes

Approximate timing: 15 minutes read; 10 minutes live.

Demo plan (if extending this PARTIAL module later): live-create a Job with a command that deliberately fails once then succeeds (backoffLimit: 2), and watch kubectl get pods show the failed attempt alongside the eventual successful one — makes the retry-until-backoffLimit behavior concrete.

Likely misconceptions to watch for:

  • Students often assume a Job that finishes successfully gets cleaned up automatically. It doesn't by default — the completed Pod/Job objects remain until manually deleted or a ttlSecondsAfterFinished is configured (not covered here, worth a one-line mention if asked).
  • "DaemonSet" is sometimes confused with "one Pod, cluster-wide" (singular). It's the opposite — one Pod PER NODE, which can be many Pods total in a multi-node cluster.

Discussion question: "Why doesn't a Deployment support 'run once and be done'?" (Answer: a Deployment's whole contract is maintaining a standing replica count forever — repurposing it for one-shot work would fight that contract rather than use a primitive designed for it.)

Optional extension: ask what would go wrong if a CronJob's schedule ran more often than a single Job execution takes to complete (answer: overlapping Job runs, unless concurrencyPolicy is set to Forbid or Replace — a real gotcha worth naming even without building a full lab around it).