07 DaemonSet 与 Job/CronJob:离线/守护业务
系列专栏《深入剖析 Kubernetes》· 基于张磊极客时间专栏思想整理 · 适合 CSDN 发布07 DaemonSet 与 Job/CronJob离线/守护业务在前几讲里我们反复提到 Deployment 用来跑长期在线、要保副本数的无状态服务。但真实集群里还有两类典型业务Deployment 并不合适守护型daemon集群里每个节点都要跑一份的 agent比如日志采集器、监控探针、网络插件。节点增减时它要自动跟随。离线型batch跑完就结束的任务——数据清洗、模型训练、定时报表。它们不追求永远在线而是追求跑完、跑对、可重试。Kubernetes 为此提供了三套专门的控制器DaemonSet、Job、CronJob。本讲逐一拆解。一、DaemonSet每个节点一个 PodDaemonSet 的核心契约非常简单集群里有几个满足条件的节点就自动跑几个 Pod一一对应。新增节点自动补节点下线 Pod 自动回收。经典用途Fluentd/Filebeat 日志采集、node-exporter 监控、Calico/Cilium 网络插件、GPU 驱动守护进程。基本实现原理DaemonSet 控制器 watch 节点列表对每个节点经过nodeSelector/affinity和toleration过滤后保证存在一个绑定的 Pod。新节点 Ready 时控制器立刻在上面创建一个 Pod节点被删除对应的 Pod 也被回收。┌──────────────── k8s 集群 ────────────────┐ │ node-1 node-2 node-3 │ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ fluent│ │ fluent│ │ fluent│ │ ← DaemonSet 保证每节点 1 个 │ │d Pod │ │d Pod │ │d Pod │ │ │ └──────┘ └──────┘ └──────┘ │ │ (新增 node-4 → 控制器自动补一个 fluentd) │ └───────────────────────────────────────────┘nodeSelector 与 toleration控制跑在哪、容不怕脏默认 DaemonSet 会尝试覆盖所有节点但生产上常需要微调apiVersion:apps/v1kind:DaemonSetmetadata:name:fluentdnamespace:kube-systemspec:selector:matchLabels:{app:fluentd}template:metadata:labels:{app:fluentd}spec:# 1) 只跑在带 disktypessd 标签的节点上nodeSelector:disktype:ssd# 2) 容忍tolerationmaster 上的 NoSchedule 污点否则上不去tolerations:-key:node-role.kubernetes.io/mastereffect:NoSchedulecontainers:-name:fluentdimage:fluent/fluentd:v1.16resources:requests:{cpu:100m,memory:100Mi}limits:{cpu:200m,memory:200Mi}nodeSelector硬性标签匹配只有贴了disktypessd的节点才会被调度。更灵活的是nodeAffinity。toleration容忍默认 K8s 不会把 Pod 调度到带NoSchedule污点taint的节点如 master。DaemonSet 想上 master 采集日志就必须用 toleration “容忍该污点。注意容忍是能上”不是必须上真正决定去哪还要配合其他调度规则。二、Job管理离线批处理任务Deployment 的目标是维持 N 个 Pod 永远活而Job 的目标是把任务成功跑完。Job 会创建 Pod并持续 watch直到指定数量的 Pod成功退出phaseSucceededJob 就算完成。期间 Pod 崩溃Job 会按策略重启它。三个关键字段apiVersion:batch/v1kind:Jobmetadata:name:data-exportspec:completions:5# 总共需要成功完成 5 个 Pod即任务份数parallelism:2# 同时最多并行跑 2 个backoffLimit:3# 整体允许失败重试次数超过则 Job 标记 FailedactiveDeadlineSeconds:3600# 总时限超时强制终止防止挂死template:spec:restartPolicy:OnFailure# Job 只允许 OnFailure 或 Nevercontainers:-name:exporterimage:myrepo/exporter:v2command:[python,export.py]completions任务需要成功多少个 Pod。设成 1 就是单任务设成 N 可用来做分片批处理每个 Pod 处理一部分数据。parallelism并发度。结合completions实现5 份任务、2 个并发的流水式执行。backoffLimit失败重试上限。注意它的语义是Pod 重启次数的累计达到后 Job 不再重试、状态置为 Failed。排查Job 一直不动时先看 Pod 日志和这个上限。restartPolicy在 Job 里不能是 Always否则成功退出也会被无限拉起只能OnFailure或Never。场景AI 训练任务用 Job大模型/数据处理的训练任务本质就是跑一次、出结果、结束。尤其配合operator如 Kubeflow Training Operator / MPIJob、PyTorchJob底层依然是一个个 Job 管理训练 Pod# 简化示意单卡训练 JobapiVersion:batch/v1kind:Jobmetadata:{name:train-resnet}spec:completions:1template:spec:restartPolicy:OnFailurecontainers:-name:trainerimage:myregistry/train:torch2.3resources:limits:{nvidia.com/gpu:1}# 申请 1 张 GPUcommand:[python,train.py,--epochs,50]分布式训练多机多卡通常由 Kubeflow 的PyTorchJob/TFJob这类 CRD 编排但底层仍遵循Job 管生命周期、完成即退的思路。区别在于训练任务更关心节点故障时的断点续训、Checkpoint 持久化这些要靠挂载 PVC 和自定义重试逻辑来补齐。三、CronJobk8s 里的定时任务CronJob Job 的定时触发器。它按cron 表达式周期性地创建 Job对应我们熟悉的crontab。apiVersion:batch/v1kind:CronJobmetadata:name:nightly-reportspec:schedule:0 2 * * *# 每天凌晨 2:00分钟 小时 日 月 周concurrencyPolicy:Forbid# 上次没跑完这次就不新开可选 Allow/ReplacestartingDeadlineSeconds:300# 错过调度点 300s 内仍补跑否则跳过successfulJobsHistoryLimit:3# 保留最近 3 个成功 Job 记录failedJobsHistoryLimit:1jobTemplate:spec:template:spec:restartPolicy:OnFailurecontainers:-name:reporterimage:myrepo/report:v1command:[sh,-c,python gen_report.py]cron 表达式速查5 段与 Linux crontab 一致┌── 分 (0-59) │ ┌── 时 (0-23) │ │ ┌── 日 (1-31) │ │ │ ┌── 月 (1-12) │ │ │ │ ┌── 周 (0-6, 0周日) * * * * * 0 2 * * * → 每天 02:00 */15 * * * * → 每 15 分钟 0 0 * * 1 → 每周一 00:00几个易踩的坑时区CronJob 默认用 kube-controller-manager 的时区。若需指定可在spec.timeZone或 annotation 中设置取决于版本。并发concurrencyPolicy决定上次没跑完这次怎么办生产定时任务务必显式设置避免任务叠加把资源打爆。历史清理不配historyLimit集群会无限累积 Job 对象拖慢 API server。四、三者对比速查控制器目标生命周期典型场景DaemonSet每节点跑一个长期运行日志/监控/网络插件Job跑完 N 个任务完成后结束批处理、训练、迁移CronJob定时触发 Job周期性创建 Job报表、备份、清理小结 / 核心要点DaemonSet保证每个满足条件的节点一个 Pod靠nodeSelector限定范围、靠toleration容忍污点才能上 master 等特殊节点节点动态增删时自动跟随。Job以任务成功完成为目标而非永远在线用completions/parallelism控制份数与并发backoffLimit控制重试restartPolicy只能 OnFailure/Never。AI 训练这类一次性重任务正是 Job 的天然场景。CronJob用标准 cron 表达式周期性创建 Job务必关注concurrencyPolicy、timeZone、historyLimit避免任务叠加和资源泄漏。选型口诀守护类 → DaemonSet跑完即止 → Job定时跑完即止 → CronJob长驻无状态服务 → 才轮到 Deployment。下一篇我们会把视角下沉到节点内部看看这些 Pod 到底是被谁、怎么真正跑起来的——这就是容器运行时与 CRI 的故事。