第27篇 k8s之控制器:DaemonSet、Job 与 CronJob

IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章,助你少走弯路。


在前两篇中,我们用 Deployment 管理了 Flask 应用的副本,实现了滚动更新和自愈。Deployment 适合管理无状态、需要多副本、可随时替换的应用。但不是所有工作负载都长这样------有些需要在每个节点上运行,有些是一次性任务,有些是按周期自动执行的定时任务。

比如:你想在每个节点上部署一个日志采集器(节点级守护),你想跑一次数据库迁移脚本(一次性任务),你想每天凌晨 2 点自动备份 Redis 数据(定时任务)。Deployment 做这些事就像用牛刀杀鸡------不是不能,而是极其别扭。

今天我们来解锁三类专为这些场景设计的控制器:DaemonSet、Job、CronJob。它们与 Deployment 一起构成了 K8s 工作负载管理的完整拼图。

一、DaemonSet:每个节点一个 Pod

1.1 什么是 DaemonSet?

DaemonSet 确保每个节点上恰好运行一个 Pod 副本(或者匹配特定条件的节点上各运行一个)。节点加入集群时自动部署,节点移除时自动回收。

典型使用场景:

  • 日志采集:每个节点上运行 Fluentd / Filebeat,采集所有容器的日志

  • 监控代理:每个节点上运行 Prometheus Node Exporter,暴露节点指标

  • 网络插件:每个节点上运行 Calico / Flannel 的代理组件

  • 存储守护进程:每个节点上运行 Ceph / GlusterFS 客户端

1.2 实战:部署 Node Exporter 监控代理

以下 YAML 在每个节点上部署一个 Prometheus Node Exporter,采集节点的 CPU、内存、磁盘等指标。这也是我们贯穿案例从"可运行"走向"可观测"的第一步。

bash 复制代码
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  labels:
    app: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostPID: true
      containers:
        - name: node-exporter
          image: prom/node-exporter:latest
          args:
            - --path.procfs=/host/proc
            - --path.sysfs=/host/sys
            - --path.rootfs=/host/root
          ports:
            - containerPort: 9100
          volumeMounts:
            - name: proc
              mountPath: /host/proc
              readOnly: true
            - name: sys
              mountPath: /host/sys
              readOnly: true
            - name: root
              mountPath: /host/root
              readOnly: true
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: sys
          hostPath:
            path: /sys
        - name: root
          hostPath:
            path: /

关键配置说明:

  • kind: DaemonSet 声明这是一个 DaemonSet 控制器

  • hostNetwork: true 使 Pod 直接使用宿主机网络命名空间(Node Exporter 需要访问宿主机网络指标)

  • hostPID: true 使 Pod 能看到宿主机的进程列表

  • hostPath 卷将宿主机的 /proc/sys/ 挂载到容器内,让 Exporter 读取系统指标

  • 无需 replicas 字段------DaemonSet 自动根据节点数量决定副本数

部署并验证:

bash 复制代码
kubectl apply -f node-exporter-daemonset.yaml
kubectl get daemonset
# NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
# node-exporter   1         1         1       1            1           <none>          30s

kubectl get pods -l app=node-exporter -o wide
# NAME                  READY   STATUS    NODE       AGE
# node-exporter-abcde   1/1     Running   minikube   30s

Minikube 是单节点集群,所以只运行 1 个 Pod。在多节点集群中,每个节点都会自动运行一个。

1.3 DaemonSet vs Deployment

二、Job:一次性任务

2.1 什么是 Job?

Job 确保指定数量的 Pod 成功完成 (退出码 0)。Job 创建的 Pod 在任务完成后不会自动重启(restartPolicy 通常设为 NeverOnFailure),而是保留在集群中以便查看日志和状态。

典型使用场景:

  • 数据库迁移(Django manage.py migrate

  • 数据清洗与 ETL 任务

  • 一次性报告生成

  • 密钥轮换脚本

2.2 实战:Redis 数据备份 Job

为我们的贯穿案例创建一个定期执行的 Redis 备份任务(先看一次性 Job,再升级为 CronJob)。

bash 复制代码
apiVersion: batch/v1
kind: Job
metadata:
  name: redis-backup
spec:
  ttlSecondsAfterFinished: 600
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: backup
          image: redis:alpine
          command:
            - sh
            - -c
            - |
              echo "开始备份,时间: $(date)"
              redis-cli -h redis-service -p 6379 --rdb /backup/dump.rdb
              if [ $? -eq 0 ]; then
                echo "备份成功"
              else
                echo "备份失败"
                exit 1
              fi
          volumeMounts:
            - name: backup-storage
              mountPath: /backup
      volumes:
        - name: backup-storage
          emptyDir: {}

关键配置说明:

  • restartPolicy: Never:Job 的 Pod 退出后不重启。如果任务失败,由 Job Controller 决定是否创建新 Pod 重试

  • ttlSecondsAfterFinished: 600:Job 完成后 10 分钟自动清理(K8s v1.21+)。不设则需手动删除

  • command 中的 exit 1 确保备份失败时 Pod 返回非零退出码,Job Controller 据此判断任务是否成功

部署并验证:

bash 复制代码
kubectl apply -f redis-backup-job.yaml
kubectl get job
# NAME           COMPLETIONS   DURATION   AGE
# redis-backup   1/1           3s         10s

kubectl get pods -l job-name=redis-backup
# NAME                 READY   STATUS      RESTARTS   AGE
# redis-backup-xyz12   0/1     Completed   0          10s

Pod 的 STATUS=Completed 表示任务已成功完成。查看日志:

bash 复制代码
kubectl logs job/redis-backup
# 开始备份,时间: Mon May 27 10:00:00 UTC 2025
# 备份成功

2.3 Job 的三种运行模式

2.4 backoffLimit 与失败重试

Job 默认会在 Pod 失败后重试,由 backoffLimit 控制最大重试次数(默认 6):

达到上限后 Job 标记为 Failed。对于幂等性任务(如数据备份),可设置较高重试次数;对于非幂等任务(如数据库迁移),建议设为 1 或 2,避免重复执行产生脏数据。

2.5 并行 Job 的工作队列模式

对于需要并行处理的大规模任务(如批量图片压缩、日志分析),可以配置并行 Job:

bash 复制代码
spec:
  completions: 50          # 总共需要完成 50 个 Pod
  parallelism: 10          # 同时运行 10 个 Pod

这种模式下,Job Controller 会始终维持 10 个 Pod 并行运行,直至全部 50 个 Pod 成功完成。适合将大型任务拆分为独立子任务并行处理的场景。

三、CronJob:定时任务

3.1 什么是 CronJob?

CronJob 在指定的时间表上自动创建 Job,语法与 Linux crontab 完全一致。它是对 Job 的定时调度封装。

典型使用场景:

  • 每日凌晨数据库备份

  • 每小时日志轮转与归档

  • 每周生成业务报表

  • 定期证书续期检查

3.2 实战:每日凌晨 2 点备份 Redis

将前面的一次性 Job 升级为 CronJob:

bash 复制代码
apiVersion: batch/v1
kind: CronJob
metadata:
  name: redis-daily-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      ttlSecondsAfterFinished: 86400
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: backup
              image: redis:alpine
              command:
                - sh
                - -c
                - |
                  echo "定时备份开始,时间: $(date)"
                  redis-cli -h redis-service -p 6379 --rdb /backup/dump.rdb
                  if [ $? -eq 0 ]; then
                    echo "备份成功"
                  else
                    echo "备份失败"
                    exit 1
                  fi
              volumeMounts:
                - name: backup-storage
                  mountPath: /backup
          volumes:
            - name: backup-storage
              emptyDir: {}

关键配置说明:

  • schedule: "0 2 * * *" 使用标准 crontab 语法------分、时、日、月、周,表示每天凌晨 2:00 执行

  • jobTemplate 内嵌了 Job 的完整 spec,结构与 Job YAML 完全一致

  • restartPolicy: OnFailureNever 更适合定时任务------偶发性网络抖动导致的失败会被自动重试

  • ttlSecondsAfterFinished: 86400 保留 24 小时后自动清理

部署并验证:

bash 复制代码
kubectl apply -f redis-cronjob.yaml
kubectl get cronjob
# NAME                 SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
# redis-daily-backup   0 2 * * *   False     0        <none>          10s

3.3 手动触发 CronJob

从 K8s v1.27 起,可以直接从 CronJob 创建一个一次性 Job:

bash 复制代码
kubectl create job manual-backup --from=cronjob/redis-daily-backup
kubectl get pods -l job-name=manual-backup

这个命令会基于 CronJob 的 jobTemplate 立即创建一个 Job,用于测试定时任务的正确性。

3.4 CronJob 常见参数

三个重要参数的深入说明

  • startingDeadlineSeconds:当控制平面因故障恢复后,发现某个 CronJob 应该被执行了 5 次但只执行了 3 次。如果设了此参数,超过截止时间的任务会被跳过,避免积压的 Job 同时爆发占用集群资源。

  • concurrencyPolicyAllow 允许同一 CronJob 的多个 Job 并行执行(需保证任务是幂等的);Forbid 如果上一个 Job 未结束则跳过本次调度;Replace 取消正在运行的 Job 并启动新的。

  • suspend: true 可以在不删除 CronJob 对象的情况下暂停调度,适合维护窗口期间临时禁制定时任务。

四、控制器选择指南

至此,我们已经学过了 5 类控制器:Deployment、StatefulSet(将在第 27 篇之后展开)、DaemonSet、Job、CronJob。如何根据业务需求选择合适的控制器?

与 Docker Compose 的对比 :Compose 没有针对不同工作负载提供不同的管理对象------所有服务都用 services 定义,定时任务需要依赖外部 cron 或脚本触发。K8s 的控制器体系将工作负载按特征分类,每种控制器针对特定场景优化了生命周期管理和调度策略。

五、命令速查表

六、本篇总结

  • DaemonSet:每个节点运行一个 Pod,适合日志采集、监控代理等节点级守护任务。

  • Job:一次性任务,运行到完成,支持并行和重试,适合数据库迁移、数据备份等场景。

  • CronJob:定时调度 Job,基于 crontab 表达式,适合定期备份、报表生成等周期性任务。

  • 控制器选型:根据工作负载的特征选择合适的控制器------服务类用 Deployment,节点级用 DaemonSet,批处理用 Job/CronJob。

至此,K8s 的核心工作负载控制器你已经全部掌握。下一篇文章------第 28 篇:Service:为 Pod 提供稳定的访问入口,我们将解决一个关键问题:Deployment 管理着不断变化 IP 的 Pod,其他服务如何稳定地找到它们?答案就是 Service。

想了解更多还可以去各个平台搜索「IT策士」,一起升级 IT 思维 !

相关推荐
蜀道山老天师1 小时前
Docker安装配置全教程(含银河麒麟服务器部署+镜像加速)
运维·docker·容器
EMTime10 小时前
Docker运行OpenWRT
运维·docker·容器
zyl8372113 小时前
Docker 使用手册
运维·docker·容器
Elastic 中国社区官方博客15 小时前
我们如何在 Elasticsearch Serverless 上将向量搜索吞吐量提升一倍
大数据·数据库·人工智能·elasticsearch·搜索引擎·云原生·serverless
maomao大哥闯天下16 小时前
K8s如何实现滚动更新、健康检查与探测机制
docker·容器·kubernetes
楼田莉子16 小时前
Docker学习:Docker介绍及其架构介绍
运维·后端·学习·docker·容器·架构
张忠琳18 小时前
【kubernetes v1.21】(一)Kubernetes 总览架构深度分析
云原生·架构·kubernetes
香气袭人知骤暖18 小时前
PG数据库 Docker 容器自动备份方案
数据库·docker·容器
maomao大哥闯天下19 小时前
K8s对象deployment、job、service应用详解
java·容器·kubernetes