K8s 系列 | 第 19 天:Job 与 CronJob:批处理与定时任务实战


title: K8s 系列 | 第 19 天:Job 与 CronJob:批处理与定时任务实战
tags:
– Kubernetes
– K8s系列
– DevOps
– Job
– CronJob
– 批处理
– 定时任务


K8s 系列 | 第 19 天:Job 与 CronJob:批处理与定时任务实战

第 19/30 天


一、引言

在生产环境中,我们不仅需要运行长期守护的 Web 服务(如 Nginx、API Server),还需要处理大量一次性或周期性的计算任务:数据批处理、数据库备份、日志清理、模型训练、报表生成等。Kubernetes 为此提供了两个专用控制器——JobCronJob

  • Job:管理一次性任务,确保 Pod 成功执行到完成状态。
  • CronJob:基于 Cron 表达式定时触发 Job,适用于周期性任务。

本文将深入讲解 Job 和 CronJob 的核心机制、实战用法、常见陷阱以及生产最佳实践。


二、Job 核心概念

2.1 什么是 Job?

Job 是 Kubernetes 的工作负载资源之一,用于运行有限次数的 Pod,并在 Pod 成功退出(exit code 0)后标记为完成。与 Deployment 不断重启 Pod 不同,Job 的 Pod 运行结束后就停止。

2.2 Job 的关键参数

参数 作用 默认值
.spec.completions 需要成功完成的 Pod 数量 1
.spec.parallelism 允许并行运行的 Pod 数量 1
.spec.backoffLimit 失败重试次数上限 6
.spec.activeDeadlineSeconds Job 总运行时间上限
.spec.ttlSecondsAfterFinished 完成后自动清理的等待时间

2.3 Job 的三种运行模式

  1. 单 Pod 模式(默认):completions=1, parallelism=1 — 一个 Pod 运行一次。
  2. 固定完成次数completions=N, parallelism=1 — 串行执行 N 个 Pod。
  3. 工作队列模式completions=N, parallelism=M — 并行执行,共完成 N 个。
  4. 并行非队列模式completions=1, parallelism=M — M 个 Pod 同时运行,任意一个成功即完成。

三、Job 实战

3.1 创建一个简单的 Job

apiVersion: batch/v1
kind: Job
metadata:
  name: pi-job
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

运行并查看结果:

# 创建 Job
kubectl apply -f pi-job.yaml

# 查看 Job 状态
kubectl get job pi-job

# 查看 Pod 日志(Job 完成后 Pod 仍在,可查阅)
kubectl logs job/pi-job

3.2 并行 Job:数据处理场景

apiVersion: batch/v1
kind: Job
metadata:
  name: data-processor
spec:
  completions: 5
  parallelism: 3
  template:
    spec:
      containers:
      - name: worker
        image: busybox:1.36
        command:
        - sh
        - -c
        - |
          echo "Processing batch $(date +%s) ..."
          sleep 5
          echo "Done."
      restartPolicy: Never
  backoffLimit: 2
# 查看并行进度
kubectl get pods -w

这里 parallelism=3 表示最多同时运行 3 个 Pod,completions=5 表示总共需要成功完成 5 个 Pod。如果某个 Pod 失败,Job 控制器会自动创建新的替换它,直到达到 backoffLimit

3.3 限制 Job 运行时长

apiVersion: batch/v1
kind: Job
metadata:
  name: timeout-job
spec:
  activeDeadlineSeconds: 30
  template:
    spec:
      containers:
      - name: sleeper
        image: busybox:1.36
        command: ["sleep", "60"]
      restartPolicy: Never

超过 30 秒后,Job 会被标记为 Failed,所有相关 Pod 被终止(DeadlineExceeded)。

3.4 自动清理已完成 Job

apiVersion: batch/v1
kind: Job
metadata:
  name: cleanup-after-job
spec:
  ttlSecondsAfterFinished: 60
  template:
    spec:
      containers:
      - name: echo
        image: busybox:1.36
        command: ["echo", "This job will be deleted after 60 seconds"]
      restartPolicy: Never

设置 ttlSecondsAfterFinished 后,Kubernetes 会在 Job 完成后等待指定秒数,然后自动回收 Job 及其 Pod 对象。


四、CronJob 核心概念

4.1 什么是 CronJob?

CronJob 在 Job 的基础上增加了时间调度能力,使用标准的 Unix Cron 表达式定义执行周期。每次调度时,CronJob 控制器会创建一个新的 Job 对象。

4.2 CronJob 关键参数

参数 作用 默认值
.spec.schedule Cron 表达式(必需)
.spec.jobTemplate 创建的 Job 模板
.spec.startingDeadlineSeconds 启动截止时间
.spec.concurrencyPolicy 并发策略:Allow/Forbid/Replace Allow
.spec.successfulJobsHistoryLimit 保留的成功 Job 数 3
.spec.failedJobsHistoryLimit 保留的失败 Job 数 1
.spec.suspend 暂停调度 false

4.3 Cron 表达式说明

K8s 使用标准 5 字段 Cron 格式(分 时 日 月 周),支持特殊语法:

* * * * *
│ │ │ │ │
│ │ │ │ └── 星期 (0-6, 0=周日)
│ │ │ └──── 月份 (1-12)
│ │ └────── 日期 (1-31)
│ └──────── 小时 (0-23)
└────────── 分钟 (0-59)

常用示例:

表达式 含义
*/5 * * * * 每 5 分钟
0 */1 * * * 每小时整点
0 2 * * * 每天凌晨 2 点
0 0 * * 0 每周日凌晨 0 点
0 0 1 * * 每月 1 日凌晨 0 点

五、CronJob 实战

5.1 创建定时备份 CronJob

apiVersion: batch/v1
kind: CronJob
metadata:
  name: db-backup
spec:
  schedule: "0 3 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: bitnami/kubectl:latest
            command:
            - /bin/sh
            - -c
            - |
              echo "Starting database backup at $(date)..."
              kubectl exec db-pod -- pg_dump -U admin mydb > /backups/db-$(date +%Y%m%d).sql
              echo "Backup complete: db-$(date +%Y%m%d).sql"
          restartPolicy: OnFailure
  successfulJobsHistoryLimit: 5
  failedJobsHistoryLimit: 2
# 创建 CronJob
kubectl apply -f db-backup-cronjob.yaml

# 查看 CronJob
kubectl get cronjob db-backup

# 查看触发的 Job
kubectl get jobs --watch

5.2 并发策略详解

当上一个 Job 尚未完成而下一个调度时间已到时,concurrencyPolicy 决定行为:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hourly-report
spec:
  schedule: "0 * * * *"
  concurrencyPolicy: Forbid  # 不允许并发,跳过重叠执行
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: reporter
            image: busybox:1.36
            command:
            - sh
            - -c
            - |
              echo "Generating report... $(date)"
              sleep 300  # 耗时 5 分钟
              echo "Report done."
          restartPolicy: Never

三种并发策略:
Allow(默认):允许同时运行多个 Job 实例。
Forbid:若前一个 Job 仍在运行,跳过本次调度。
Replace:终止前一个 Job,创建新的 Job。

5.3 暂停与恢复 CronJob

# 暂停调度(保留已有 Job 运行)
kubectl patch cronjob db-backup -p '{"spec":{"suspend":true}}'

# 恢复调度
kubectl patch cronjob db-backup -p '{"spec":{"suspend":false}}'

# 手动触发一次(创建一次性的 Job)
kubectl create job --from=cronjob/db-backup manual-backup-$(date +%s)

六、常见问题与避坑指南

6.1 Job 不会自动重启 Pod

Job 默认的 restartPolicyNeverOnFailure不能设为 Always(K8s 会拒绝)。两者的区别:

  • Never:Pod 失败后,Job 控制器创建全新的 Pod 重试。
  • OnFailure:Pod 失败时,kubelet 在原地重启容器

建议使用 Never,配合 backoffLimit 控制重试次数,避免同一节点反复重启导致资源泄漏。

6.2 Job 完成后的 Pod 残留

默认情况下,Job 完成后 Pod 不会被自动删除,方便查看日志。生产环境建议设置:

spec:
  ttlSecondsAfterFinished: 3600  # 一小时后自动清理

6.3 CronJob 的时间偏差问题

CronJob 控制器基于控制平面的系统时间调度。如果集群节点间时间不同步,可能导致:

  • 调度时间不准确
  • Job 启动延迟

✅ 最佳实践:保证所有节点部署 NTP 服务(chrony / ntpd)。

6.4 大量历史 Job 累积

长时间运行的 CronJob 会积累大量已完成的 Job 对象,给 etcd 带来压力:

spec:
  successfulJobsHistoryLimit: 3   # 只保留最近 3 个成功记录
  failedJobsHistoryLimit: 1       # 只保留最近 1 个失败记录

默认值分别是 3 和 1,已比较合理。如果日志审计需求强,建议将日志输出到外部存储(如 Elasticsearch)而非依赖 K8s 保留 Job 对象。

6.5 时区问题

CronJob 的 schedule 基于 kube-controller-manager 的时区(默认 UTC)。如果需要特定时区:

spec:
  timeZone: "Asia/Shanghai"
  schedule: "0 8 * * *"

⚠️ timeZone 字段从 Kubernetes 1.27 开始 GA(CronJobTimeZone 特性门控),更早版本不支持。


七、生产最佳实践总结

场景 推荐方案
一次性数据迁移 Job(completions=1)
并行数据处理 Job(completions=N, parallelism=M)
每天凌晨备份数据库 CronJob(0 3 * * *
每 5 分钟清理临时文件 CronJob(*/5 * * * *
不重叠的长时间任务 CronJob(concurrencyPolicy: Forbid)
自动清理历史记录 ttlSecondsAfterFinished + historyLimit

八、下期预告

第 20 天:PriorityClass 与抢占式调度机制

在生产集群中,如何确保关键业务 Pod 在资源紧张时优先获得调度?PriorityClass 是什么?抢占式调度(Preemption)如何工作?下一篇文章将为你深入解析 K8s 的优先级调度体系。


📚 系列目录
[K8s 系列 | 第 1 天:Kubernetes 是什么?核心概念与架构全景解析] → [第 2 天:kubeadm 搭建集群] → [第 3 天:Pod 详解] → … → [第 19 天:Job 与 CronJob] → 持续更新中…

全部 30 篇文章,从基础到生产运维,每天一篇,欢迎收藏关注!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容