DaemonSets & Jobs/CronJobs
Kubernetes Intermediate/Advanced
Chapter 2 · DaemonSets & Jobs/CronJobs
Chapter 1 covered StatefulSets for identity/storage-sensitive workloads. This chapter covers two more specialized controllers, each genuinely different from anything covered so far: DaemonSets (one pod per node) and Jobs/CronJobs (run to completion, not forever).
DaemonSets — One Pod Per Node, Guaranteed
A DaemonSet ensures exactly one copy of a pod runs on every node in the cluster (or a selected subset via node selectors) — genuinely different from a Deployment's "N replicas, scheduler decides where" model. A DaemonSet's desired count is inherently tied to the number of nodes, not an arbitrary number you specify. When a new node joins the cluster, the DaemonSet automatically schedules a pod there too — another instance of Chapter 2 (Course 1)'s reconciliation loop, just with desired state defined as "one per node" rather than a fixed number.
What DaemonSets Are Actually Used For
- Log collection agents (e.g. Fluentd/Fluent Bit) — needs to run on every node to collect logs from that node's own containers (
k8s2-7's upcoming observability chapter builds on this). - Monitoring/metrics agents (e.g. Prometheus's node-exporter) — needs per-node system-level metrics, also feeding into
k8s2-7. - Networking/CNI plugin pods — some cluster networking implementations run as DaemonSets themselves, tying back to
k8s1-2's own architecture material.
The common thread: infrastructure-level concerns that are inherently per-node, not per-application.
A Concrete DaemonSet YAML, Explained
Same apps/v1 group as Deployment/StatefulSet — Chapter 1's own "sibling controller" point holds again. Critically: no replicas field at all, since the count is implicitly "one per matching node," not something specified directly.
Jobs — Run to Completion, Not Forever
A completely different category: Deployments, StatefulSets, and DaemonSets are all about keeping something running indefinitely. A Job is for a task that should run once (or a specified number of times) and then stop — directly tying back to k8s1-3's own Pod lifecycle material (Succeeded/Failed terminal states) and k8s1-11's OnFailure restart policy, which exists specifically for this use case. Genuinely common real uses: a database migration script, a one-off batch data-processing task, sending a batch of emails.
Job Completion & Parallelism
spec.completions — how many successful pod completions are needed for the Job to be considered done. spec.parallelism — how many pods can run at once working toward that count. A Job processing 100 queue items could run completions: 100, parallelism: 10, processing 10 items concurrently until all 100 finish — a genuinely different kind of "scaling" concept from Course 2's own upcoming k8s2-6 autoscaling material, worth not conflating.
CronJobs — Scheduled Jobs
A CronJob is, in a sense, to a Job what a Deployment is to a Pod — it creates Jobs on a recurring schedule, using standard cron syntax. Genuinely common real uses: nightly database backups, periodic cleanup tasks, scheduled report generation. Each scheduled run creates a new Job object, which then creates pods per that Job's own completion/parallelism settings — worth being explicit about the layering: CronJob creates Jobs, Jobs create Pods, three distinct layers.
A Concrete CronJob YAML, Explained
Yet another distinct API group — batch/v1 — reinforcing the recurring "apiVersion differs by kind" lesson from Chapters 5, 6, and 9. Note the genuinely deep nesting: spec.jobTemplate.spec.template.spec — a CronJob spec containing a Job spec containing a pod spec, three layers deep, worth reading carefully rather than being intimidated by.
k8s2-8): a failed backup could mean the CronJob never triggered, the Job it created failed, or the Pod that Job spawned crashed — three genuinely different places to look.
A Genuinely Common Gotcha — Missed & Overlapping Schedules
What happens if a CronJob's previous run is still executing when the next scheduled time arrives? spec.concurrencyPolicy controls this: Allow (default, runs can overlap), Forbid (skip the new run if the previous is still going), Replace (cancel the old run, start the new one). Genuinely important to configure deliberately for something like a database backup — overlapping backup runs could cause real problems.
Allow, permits overlapping runs — for a job that genuinely shouldn't run twice concurrently (a backup writing to the same target, for instance), this can cause real data corruption or resource contention. Set Forbid explicitly for anything where overlap would be a genuine problem, rather than leaving the default unexamined.
Hands-On Exercises
Explain why a DaemonSet's "desired pod count" isn't something you directly specify the way a Deployment's replica count is, and give one concrete real-world example of a workload that genuinely needs to run on every node.
📄 View solutionExplain the three-layer relationship between a CronJob, a Job, and a Pod — which one creates which.
📄 View solutionA team runs a nightly database backup as a CronJob with the default concurrencyPolicy. One night the backup takes much longer than usual and is still running when the next scheduled run begins. Explain what happens by default, why this could be a real problem for a backup job specifically, and what concurrencyPolicy setting would prevent it.
Chapter 2 Quick Reference
- DaemonSet — one pod per node, automatically, no
replicasfield; used for log/metrics agents and CNI plugins - Job — runs to completion, not forever;
completions/parallelismcontrol how much work and how much concurrency - CronJob — creates Jobs on a schedule; three layers: CronJob → Job → Pod
- CronJob uses yet another apiVersion (
batch/v1) — the recurring apiVersion-differs-by-kind pattern continues concurrencyPolicy(Allow/Forbid/Replace) — leaving it at the default Allow for something like a backup risks real overlap problems- Next chapter: Helm — Package Management for Kubernetes — charts, templating, releases