跳到正文
复制成功
请遵守本站许可
报告
章节_文章 // 现场报告

文章编号: RL-CRONJOB定

2026.08.13

CronJob:定时任务调度与执行策略

Chavy
Chavy
#Kubernetes#CronJob#定时任务
档案

摘要:理解 CronJob 与 Job 的关系,掌握 Cron 表达式、时区、并发策略、错过调度的处理、历史清理以及暂停和手动触发操作。

本节学习 Kubernetes 中用于管理周期性任务的工作负载控制器——CronJob。

Job 负责执行一次性任务,例如:

  • 数据库初始化。
  • 数据迁移。
  • 批量数据处理。
  • 文件转换。

但是实际生产环境中,很多任务需要定期执行。

例如:

  • 每天凌晨 2 点备份数据库。
  • 每隔 5 分钟检查服务状态。
  • 每周日清理历史日志。
  • 每月 1 日生成统计报表。

如果每次都手动创建 Job,显然不现实。

因此 Kubernetes 提供了 CronJob。

CronJob 的核心作用:按照预设的时间规则,周期性创建 Job 来执行任务。


一、CronJob 基本概念#

1. 什么是 CronJob?#

CronJob 是 Kubernetes 中用于管理定时任务的工作负载控制器。

它基于 Cron 时间表达式,在指定时间创建 Job。

架构关系:

flowchart TB
    N0["CronJob"]
    N1["Job"]
    N2["Pod"]
    N3["Container"]
    N4["执行任务"]
    N0 -->|"定时触发"| N1
    N1 --> N2
    N2 --> N3
    N3 --> N4

例如:

flowchart TB
    N0["CronJob:每天凌晨 2 点执行"]
    N1["创建 Job-001"]
    N2["执行数据库备份"]
    N3["完成任务"]
    N4["第二天凌晨 2 点"]
    N5["创建 Job-002"]
    N6["执行数据库备份"]
    N0 --> N1
    N1 --> N2
    N2 --> N3
    N4 --> N5
    N5 --> N6

注意:

CronJob 不直接运行容器,而是定时创建 Job,由 Job 创建 Pod 执行任务。

2. CronJob 与 Job 的区别#

对比JobCronJob
主要用途一次性任务周期性任务
创建方式手动或其他控制器创建按时间规则自动创建
执行次数达到目标后结束周期性重复创建 Job
时间表达式不需要需要 Cron 表达式
管理对象PodJob

简单理解:

  • Job:执行一次任务。
  • CronJob:定时创建 Job。

二、Cron 表达式的字段、取值与语法#

这是本节最重要的知识点,也是 CKA 常见考点。

1. 什么是 Cron 表达式?#

Cron 表达式是一种描述定时执行规则的字符串。

Kubernetes CronJob 使用五个字段:

PRTCL // TEXT
分 时 日 月 星期

格式:

flowchart LR
    N0["Cron 表达式:* * * * *"]
    N1["第 1 个 *:分钟(0-59)"]
    N2["第 2 个 *:小时(0-23)"]
    N3["第 3 个 *:日期(1-31)"]
    N4["第 4 个 *:月份(1-12)"]
    N5["第 5 个 *:星期(0-6,星期日通常为 0)"]
    N0 --> N1
    N0 --> N2
    N0 --> N3
    N0 --> N4
    N0 --> N5

例如:

PRTCL // TEXT
0 2 * * *

含义:

每天凌晨 2 点执行。

2. 五个字段的取值范围#

字段允许范围含义
分钟0-59第几分钟
小时0-23第几个小时
日期1-31每月第几天
月份1-12哪个月
星期0-6星期几

星期通常:

数字星期
0星期日
1星期一
2星期二
3星期三
4星期四
5星期五
6星期六

3. 常用特殊字符#

Cron 表达式主要使用以下字符:

字符含义示例
*任意值* * * * *
,枚举多个值0 2,4,6 * * *
-连续范围0 9-17 * * *
/间隔执行*/5 * * * *

例如:

每分钟执行#

PRTCL // TEXT
* * * * *

每 5 分钟执行#

PRTCL // TEXT
*/5 * * * *

每小时执行#

PRTCL // TEXT
0 * * * *

每天凌晨 2 点执行#

PRTCL // TEXT
0 2 * * *

每周一凌晨 3 点执行#

PRTCL // TEXT
0 3 * * 1

每月 1 日凌晨 0 点执行#

PRTCL // TEXT
0 0 1 * *

每天上午 9 点和下午 6 点执行#

PRTCL // TEXT
0 9,18 * * *

每周一至周五上午 9 点执行#

PRTCL // TEXT
0 9 * * 1-5

三、CronJob 完整 YAML 结构#

1. 创建一个简单的 CronJob#

需求:

每天凌晨 2 点执行一次任务,输出当前时间。

创建文件:

PRTCL // BASH
Terminal window
vim cronjob.yaml

编写:

PRTCL // YAML
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello-cronjob
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox:1.36
command:
- sh
- -c
- "date; echo Hello Kubernetes CronJob"
restartPolicy: OnFailure

这里有一个非常重要的字段:

PRTCL // YAML
jobTemplate:

它代表 CronJob 创建 Job 时所使用的模板。

可以理解为:

flowchart TB
    N0["CronJob"]
    N1["到达指定时间"]
    N2["根据 jobTemplate 创建 Job"]
    N3["Job 根据 template 创建 Pod"]
    N4["Container 执行任务"]
    N0 -->|"schedule"| N1
    N1 --> N2
    N2 --> N3
    N3 --> N4

注意 YAML 的层级关系:

flowchart TB
    N0["CronJob"]
    N1["spec"]
    N2["schedule"]
    N3["jobTemplate"]
    N4["spec"]
    N5["template"]
    N6["spec"]
    N7["containers"]
    N0 --> N1
    N1 --> N2
    N1 --> N3
    N3 --> N4
    N4 --> N5
    N5 --> N6
    N6 --> N7

这是 CKA 编写 CronJob YAML 时很容易出错的地方。

2. 创建 CronJob#

PRTCL // BASH
Terminal window
kubectl apply -f cronjob.yaml

查看:

PRTCL // BASH
Terminal window
kubectl get cronjobs

输出示例:

PRTCL // TEXT
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE
hello-cronjob 0 2 * * * False 0 <none>

字段含义:

字段含义
SCHEDULE定时执行规则
SUSPEND是否暂停
ACTIVE当前活动 Job 数量
LAST SCHEDULE最近一次调度时间

3. 查看 CronJob 创建的 Job#

PRTCL // BASH
Terminal window
kubectl get jobs

例如:

PRTCL // TEXT
NAME COMPLETIONS
hello-cronjob-28200000 1/1

查看 Job 创建的 Pod:

PRTCL // BASH
Terminal window
kubectl get pods

查看执行日志:

PRTCL // BASH
Terminal window
kubectl logs <pod-name>

四、CronJob 时区管理(timeZone)#

这是一个非常重要的生产环境知识点。

假设:

你希望每天北京时间凌晨 2 点执行数据库备份。

配置:

PRTCL // YAML
schedule: "0 2 * * *"

是否就代表北京时间凌晨 2 点?

不一定。

Kubernetes CronJob 默认使用 kube-controller-manager 所采用的时区,通常为 UTC。

如果控制平面使用 UTC,那么:

PRTCL // TEXT
UTC 02:00

对应北京时间:

PRTCL // TEXT
北京时间 10:00

这可能导致备份任务执行时间错误。

1. 使用 timeZone 指定时区#

Kubernetes 从 v1.27 开始稳定支持 spec.timeZone。

例如:

PRTCL // YAML
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup-cronjob
spec:
schedule: "0 2 * * *"
timeZone: "Asia/Shanghai"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: busybox:1.36
command:
- sh
- -c
- "echo backup started"
restartPolicy: OnFailure

现在:

PRTCL // YAML
timeZone: "Asia/Shanghai"

表示使用上海时区解释 Cron 表达式。

因此每天北京时间凌晨 2 点执行。

常见时区:

时区配置
中国标准时间Asia/Shanghai
美国东部时间America/New_York
美国太平洋时间America/Los_Angeles
UTCEtc/UTC
日本标准时间Asia/Tokyo

建议生产环境显式配置 timeZone,避免不同集群时区不一致造成任务执行错误。


五、CronJob 并发执行策略(concurrencyPolicy)#

这是本节最重要的考点之一。

考虑一个问题:

假设我们设置:

PRTCL // YAML
schedule: "*/5 * * * *"

表示每 5 分钟执行一次。

但任务需要 8 分钟才能完成。

那么:

PRTCL // TEXT
00:00 创建 Job-1
00:05 创建 Job-2
00:08 Job-1 完成
00:10 创建 Job-3
00:13 Job-2 完成

这意味着多个 Job 可能同时运行。

对于某些业务来说,这是不允许的。

例如:

数据库备份任务,如果多个备份任务同时执行,可能占用大量磁盘和网络资源。

Kubernetes 提供了 concurrencyPolicy。

主要有三种策略:

  1. Allow
  2. Forbid
  3. Replace

1. Allow:允许并发#

PRTCL // YAML
concurrencyPolicy: Allow

这是默认策略。

含义:

如果前一个 Job 还没有完成,下一个调度时间到达时,仍然可以创建新的 Job。

执行示意:

PRTCL // TEXT
00:00 Job-1 开始
00:05 Job-2 开始
00:10 Job-3 开始
Job-1、Job-2、Job-3 可以同时运行

适用场景:

  • 不同任务之间相互独立。
  • 允许并行处理。
  • 不需要严格串行执行。

2. Forbid:禁止并发#

PRTCL // YAML
concurrencyPolicy: Forbid

含义:

如果前一个 Job 还没有完成,那么新的调度时间到达时,不会创建新的 Job。

例如:

flowchart TB
    N0["00:00 Job-1 开始"]
    N1["00:05 应该创建 Job-2"]
    N2["发现 Job-1 仍在运行"]
    N3["跳过本次调度"]
    N4["00:08 Job-1 完成"]
    N5["00:10 到达下一个调度时间"]
    N6["创建 Job-3"]
    N0 --> N1
    N1 --> N2
    N2 --> N3
    N3 --> N4
    N4 --> N5
    N5 --> N6

注意:被跳过的调度不会在前一个 Job 完成后自动补执行。

适用场景:

  • 数据库备份。
  • 数据清理。
  • 不允许任务重叠的批处理。

3. Replace:替换旧任务#

PRTCL // YAML
concurrencyPolicy: Replace

含义:

如果前一个 Job 还没有完成,那么新的调度时间到达时,会尝试终止之前的活动 Job,并创建新的 Job。

例如:

flowchart TB
    N0["00:00 Job-1 开始"]
    N1["00:05 Job-2 到达调度时间"]
    N2["终止 Job-1"]
    N3["创建 Job-2"]
    N0 --> N1
    N1 --> N2
    N2 --> N3

适用场景:

  • 只关心最新一次执行结果。
  • 旧任务已经没有继续执行的价值。
  • 新任务需要优先执行。

注意:终止旧 Job 是异步过程,不意味着旧容器中的业务操作一定瞬间停止。需要考虑任务清理、数据一致性和优雅终止。

4. 三种策略对比#

策略前一个 Job 运行中,新调度到来时
Allow创建新 Job,允许并发
Forbid跳过本次调度
Replace尝试终止旧 Job,创建新 Job

CKA 高频考点

记忆:

  • Allow:允许并发。
  • Forbid:禁止并发。
  • Replace:替换旧任务。

六、错过调度时间的处理(startingDeadlineSeconds)#

再考虑一个生产问题:

假设 CronJob 每天凌晨 2 点执行。

但是凌晨 2 点时,Kubernetes 控制平面出现故障,控制器没有及时创建 Job。

等到凌晨 3 点集群恢复,应该怎么办?

是否应该立即补执行?

Kubernetes 提供了:

startingDeadlineSeconds

1. 什么是 startingDeadlineSeconds?#

它表示 Job 可以开始执行的最晚时间窗口。

例如:

PRTCL // YAML
startingDeadlineSeconds: 300

表示:

允许错过原定调度时间最多 300 秒。

例如:

flowchart TB
    N0["计划执行:02:00"]
    N1["02:03 控制器恢复"]
    N2["距离计划时间 180 秒"]
    N3["仍在 300 秒窗口内"]
    N4["可以补创建 Job"]
    N0 --> N1
    N1 --> N2
    N2 --> N3
    N3 --> N4

如果:

flowchart TB
    N0["计划执行:02:00"]
    N1["02:10 控制器恢复"]
    N2["距离计划时间 600 秒"]
    N3["超过 300 秒"]
    N4["不再补执行这次任务"]
    N0 --> N1
    N1 --> N2
    N2 --> N3
    N3 --> N4

2. YAML 示例#

PRTCL // YAML
spec:
schedule: "0 2 * * *"
startingDeadlineSeconds: 300

表示每天凌晨 2 点执行,允许延迟 5 分钟开始。

3. 不设置 startingDeadlineSeconds 会怎样?#

如果没有设置该字段,CronJob 会尝试补偿错过的调度。

但需要注意:

Kubernetes 对错过调度次数有保护机制。

如果控制器发现超过 100 次错过的调度,会停止此次补偿并报告相关错误。

因此:

startingDeadlineSeconds 不只是控制延迟,还可以限制任务补执行的时间范围。

适合:

  • 定时备份。
  • 定时数据同步。
  • 周期性报表。
  • 不能无限补执行的业务任务。

七、CronJob 历史任务管理#

CronJob 每次执行都会创建一个 Job。

如果每天执行一次:

PRTCL // TEXT
backup-001
backup-002
backup-003
backup-004
...

随着时间推移,历史 Job 会不断增加。

Kubernetes 提供两个参数管理历史任务数量。

1. successfulJobsHistoryLimit#

控制保留多少个成功的 Job。

例如:

PRTCL // YAML
successfulJobsHistoryLimit: 3

表示最多保留 3 个成功完成的历史 Job。

默认值是 3。

2. failedJobsHistoryLimit#

控制保留多少个失败的 Job。

例如:

PRTCL // YAML
failedJobsHistoryLimit: 1

表示最多保留 1 个失败的历史 Job。

默认值是 1。

3. 完整配置#

PRTCL // YAML
spec:
schedule: "0 2 * * *"
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1

含义:

PRTCL // TEXT
成功任务:最多保留 3 个
失败任务:最多保留 1 个

注意:

这两个参数管理的是 CronJob 的历史 Job,不是 Job 的 Pod 数量,也不是 TTL。

另外,历史数量清理是控制器异步协调的,不应将其理解为精确的实时数量限制。


八、CronJob 暂停与恢复(suspend)#

生产环境中,有时需要暂时停止定时任务。

例如:

  • 数据库正在维护。
  • 备份系统正在升级。
  • 当前不允许执行数据清理任务。
  • 需要暂停某个批处理任务。

这时可以使用:

PRTCL // YAML
spec:
suspend: true

1. 暂停 CronJob#

命令:

PRTCL // BASH
Terminal window
kubectl patch cronjob backup-cronjob \
-p '{"spec":{"suspend":true}}'

查看:

PRTCL // BASH
Terminal window
kubectl get cronjob

输出:

PRTCL // TEXT
NAME SCHEDULE SUSPEND
backup-cronjob 0 2 * * * True

2. 恢复 CronJob#

PRTCL // BASH
Terminal window
kubectl patch cronjob backup-cronjob \
-p '{"spec":{"suspend":false}}'

3. 暂停和恢复的区别#

需要特别注意:

暂停 CronJob 不会自动停止已经创建并正在运行的 Job。

例如:

flowchart TB
    N0["CronJob"]
    N1["Job-1(正在运行)"]
    N2["Job-2(已经完成)"]
    N0 --> N1
    N0 --> N2

此时设置:

PRTCL // YAML
suspend: true

只会阻止后续调度创建新 Job。

Job-1 仍然可以继续运行。

如果还需要停止 Job-1,需要单独处理。

另外,恢复 CronJob 后,暂停期间错过的调度可能会被补执行,具体取决于 startingDeadlineSeconds 和错过调度次数等规则。


九、CronJob 的重要运行机制与注意事项#

前面学习了 CronJob 的各种配置,但生产环境还需要理解几个底层问题。

1. CronJob 不保证任务绝对只执行一次#

这是一个很容易忽略的知识点。

Kubernetes CronJob 的调度不是严格的分布式事务系统。

在某些异常情况下,可能出现:

  • 某次调度没有创建 Job。
  • 某次调度创建了重复 Job。
  • 控制器故障后补偿调度。

因此,不能假设每次 CronJob 调度都严格只执行一次。

例如:

flowchart TB
    N0["02:00 创建 Job-1"]
    N1["任务执行数据库备份"]
    N2["控制器异常"]
    N3["可能再次创建对应调度任务"]
    N0 --> N1
    N1 --> N2
    N2 --> N3

如果任务不具备重复执行安全性,就可能造成数据问题。

如何解决?#

使用幂等性设计(Idempotency)。

例如:

数据库备份时,可以根据日期生成唯一备份文件:

PRTCL // BASH
Terminal window
backup_file="backup-$(date +%Y%m%d).sql"

执行前检查文件是否已经存在:

PRTCL // BASH
Terminal window
if [ -f "$backup_file" ]; then
echo "Backup already exists"
exit 0
fi

这只是一个简单示例,生产环境还应考虑备份完整性校验、临时文件和原子发布。

对于支付、订单、数据迁移等任务,应该通过业务唯一标识、数据库唯一约束或分布式锁保证重复执行安全。

核心原则:CronJob 负责调度,业务程序负责保证任务的幂等性。

2. CronJob 的调度并不是精确实时调度#

例如:

PRTCL // YAML
schedule: "0 2 * * *"

表示计划每天凌晨 2 点执行。

但不代表容器一定在 02:00:00 精确启动。

原因包括:

  • 控制器调度周期。
  • 控制平面负载。
  • Job 创建延迟。
  • Pod 调度延迟。
  • 镜像拉取时间。
  • 容器启动时间。

因此:

CronJob 更适合周期性批处理任务,不适合要求毫秒级精确执行的实时任务。

3. CronJob 不会自动管理业务执行结果#

CronJob 只负责按照时间规则创建 Job。

真正的业务执行逻辑由 Job 中的容器负责。

例如:

flowchart TB
    N0["CronJob:每天凌晨 2 点触发"]
    N1["Job:负责执行备份任务"]
    N2["Pod:运行备份脚本"]
    N3["Container:执行数据库备份"]
    N4["生成备份文件"]
    N0 --> N1
    N1 --> N2
    N2 --> N3
    N3 --> N4

如果备份脚本虽然返回成功,但生成的文件实际上已经损坏,Kubernetes 并不能自动发现。

所以生产环境还需要业务层的校验机制。


十、如何手动触发 CronJob?#

生产环境中,我们经常需要立即执行一次 CronJob,而不是等待下一次定时调度。

例如:

每天凌晨 2 点执行备份,但现在下午 3 点需要立即进行一次备份。

可以直接从 CronJob 创建一个 Job。

PRTCL // BASH
Terminal window
kubectl create job manual-backup \
--from=cronjob/mysql-backup

这里:

  • manual-backup:新 Job 的名称。
  • cronjob/mysql-backup:指定 CronJob 作为模板来源。

查看:

PRTCL // BASH
Terminal window
kubectl get jobs

查看日志:

PRTCL // BASH
Terminal window
kubectl logs job/manual-backup

这种方式非常实用。

例如:

场景操作
立即备份数据库手动创建 Job
测试定时任务配置手动创建 Job
临时补执行一次任务手动创建 Job
验证脚本是否正常手动创建 Job

注意:手动创建的 Job 不受原 CronJob 的定时调度和并发策略控制。如果业务不允许并发,手动触发前也要检查是否有其他备份任务正在运行。


十一、CronJob 故障排查#

1. CronJob 没有创建 Job#

查看:

PRTCL // BASH
Terminal window
kubectl get cronjob

重点关注:

PRTCL // TEXT
SCHEDULE
SUSPEND
ACTIVE
LAST SCHEDULE

常见原因:

  • Cron 表达式错误。
  • CronJob 被暂停。
  • 时区配置不正确。
  • startingDeadlineSeconds 超出限制。
  • 控制器没有正常工作。
  • 达到错过调度次数限制。

进一步排查:

PRTCL // BASH
Terminal window
kubectl describe cronjob mysql-backup

查看集群事件:

PRTCL // BASH
Terminal window
kubectl get events --sort-by=.metadata.creationTimestamp

2. CronJob 创建了 Job,但 Job 没有完成#

查看:

PRTCL // BASH
Terminal window
kubectl get jobs

查看 Pod:

PRTCL // BASH
Terminal window
kubectl get pods

查看日志:

PRTCL // BASH
Terminal window
kubectl logs <pod-name>

查看详细信息:

PRTCL // BASH
Terminal window
kubectl describe pod <pod-name>

常见原因:

  • 容器启动失败。
  • 镜像拉取失败。
  • 脚本执行错误。
  • 外部数据库不可用。
  • Job 达到超时时间。

3. CronJob 重复执行#

重点检查:

  • concurrencyPolicy 是否为 Allow。
  • 上一次任务是否执行时间过长。
  • 是否存在控制器故障后的重复调度。
  • 是否存在人工触发的 Job。
  • 业务任务是否缺少幂等控制。

4. CronJob 常见问题总结#

问题排查方向
没有触发schedule、timeZone、suspend
延迟执行控制器状态、startingDeadlineSeconds
多个 Job 并发concurrencyPolicy
Job 执行失败backoffLimit、Pod 日志
历史记录太多历史保留策略、TTL
时间不正确timeZone
重复执行幂等性、调度状态

十二、CronJob 必须掌握的命令#

操作命令
查看 CronJobkubectl get cronjobs
查看所有命名空间kubectl get cronjobs -A
查看详细信息kubectl describe cronjob mysql-backup
创建 CronJobkubectl apply -f cronjob.yaml
手动触发kubectl create job manual --from=cronjob/mysql-backup
暂停 CronJobkubectl patch cronjob mysql-backup -p '{"spec":{"suspend":true}}'
恢复 CronJobkubectl patch cronjob mysql-backup -p '{"spec":{"suspend":false}}'
删除 CronJobkubectl delete cronjob mysql-backup
查看 Jobkubectl get jobs
查看 Podkubectl get pods

十三、本节知识总结#

CronJob 核心知识体系

flowchart TB
    N0["CronJob Controller<br/>按照 Cron 表达式定时创建 Job"]
    N1["Job<br/>执行一次性任务"]
    N2["Pod<br/>运行容器"]
    N3["Container<br/>执行实际业务逻辑"]
    N0 --> N1
    N1 --> N2
    N2 --> N3

必须掌握的参数

参数作用
schedule定时表达式
timeZone时区
concurrencyPolicy并发策略
startingDeadlineSeconds错过调度的补偿时间
successfulJobsHistoryLimit成功历史保留数量
failedJobsHistoryLimit失败历史保留数量
suspend暂停调度
jobTemplateJob 模板
归档于 2026.08.13
// 档案结束
Classified
章节_06
协议编号: CC-BY-NC-SA-4.0

CronJob:定时任务调度与执行策略

作者:Chavy发布日期:2026.08.13

基于 CC BY-NC-SA 4.0

© 2026 Chavy
Powered by Astro