# 使用CronJob执行自动任务
参考文档: Running Automated Tasks with a CronJob (opens new window)
CronJob 可以用来执行基于时间计划的定时任务,类似于Linux/Unix系统中的 crontable (opens new window)。
CronJob 执行周期性的重复任务时非常有用,例如备份数据、发送邮件等。CronJob 也可以用来指定将来某个时间点执行单个任务,例如将某项任务定时到系统负载比较低的时候执行。
CronJob 也存在某些限制,例如,在某些情况下,一个 CronJob 可能会创建多个 Job。因此,Job 必须是 幂等 的。更多与此相关的限制请参考 CronJob
# 创建CronJob
下面例子中的 CronJob 每分钟,打印一次当前时间并输出 hello world 信息。
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
执行命令以创建 CronJob:
kubectl create -f https://kuboard.cn/statics/learning/job/cronjob.yaml
1输出结果如下所示:
cronjob.batch/hello created
1或者,您也可以直接使用
kubectl run
命令创建 CronJob:kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster"
1执行命令以查看已创建 CronJob 的状态
kubectl get cronjob hello
1输出结果如下所示:
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE hello */1 * * * * False 0 <none> 10s
1
2从输出结果可以看到,该 CronJob 还未运行任何 Job。执行一下命令,并等候一分钟左右时间
kubectl get jobs --watch
1输出结果如下所示:
NAME COMPLETIONS DURATION AGE hello-4111706356 0/1 0s hello-4111706356 0/1 0s 0s hello-4111706356 1/1 5s 5s
1
2
3
4此时,可以看到该 CronJob 创建了一个 "hello-4111706356" Job,并执行结束。这时
ctrl + c
停止 watch,并重新查看 Cronjob 的状态:kubectl get cronjob hello
1输出信息如下所示:
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE hello */1 * * * * False 0 50s 75s
1
2输出结果显示,该 CronJob 在
LAST SCHEDULE
这个时间点成功创建了一个 Job。当前ACTIVE
Job 数为 0,意味着,该 Job 已经成功结束,或者已经失败。查看 Pod 的输出信息
执行命令获取 Pod 的名称
# 将 "hello-4111706356" 替换成您系统中的 Job name pods=$(kubectl get pods --selector=job-name=hello-4111706356 --output=jsonpath={.items[*].metadata.name})
1
2查看 Pod 的日志:
kubectl logs $pods
1输出结果如下所示:
Fri Feb 22 11:02:09 UTC 2019 Hello from the Kubernetes cluster
1
2
# 删除CronJob
当您不再需要某个 CronJob 时,可以使用命令将其删除 kubectl delete cronjob <cronjob name>
,在本例中,可以执行命令:
kubectl delete cronjob hello
或者
kubectl delete -f https://kuboard.cn/statics/learning/job/cronjob.yaml
删除 CronJob 时,将移除该 CronJob 创建的所有 Job 和 Pod,并且 CronJob 控制器将不会为其在创建任何新的 Job。更多信息请参考 垃圾回收
# 编写CronJob YAML
与其他所有 Kubernetes 对象一样,CronJob 对象需要 apiVersion
、kind
、metadata
这几个字段。CronJob 还需要 .spec
字段。
TIP
所有对 CronJob 对象作出的修改,尤其是 .spec
的修改,都只对修改之后新建的 Job 有效,已经创建的 Job 不会受到影响
# Schedule
.spec.schedule
是一个必填字段。类型为 Cron (opens new window) 格式的字符串,例如 0 * * * *
或者 @hourly
,该字段定义了 CronJob 应该何时创建和执行 Job。
该字段同样支持 vixie cron
step 值(step values),参考 FreeBSD manual (opens new window)。例如,指定 CronJob 每隔两个小时执行一次,可以有如下三种写法:
0 0,2,4,5,6,8,12,14,16,17,20,22 * * *
)- 使用 范围值 + Step 值的写法:
0 0-23/2 * * *
- Step 也可以跟在一个星号后面,如
0 */2 * * *
TIP
问号 ?
与 星号 *
的含义相同,代表着该字段不做限定
# Job Template
.spec.jobTemplate
字段是必填字段。该字段的结构与 Job 相同,只是不需要 apiVersion
和 kind
。请参考 编写Job的定义。
# Starting Deadline
.spec.startingDeadlineSeconds
为可选字段,代表着从计划的时间点开始,最迟多少秒之内必须启动 Job。如果超过了这个时间点,CronJob 就不会为其创建 Job,并将其记录为一次错过的执行次数。如果该字段未指定,则 Job 必须在指定的时间点执行。
CronJob 控制器将为每一个 CronJob 记录错过了多少次执行次数,如果错过的执行次数超过 100,则控制器将不会再为该 CronJob 创建新的 Job。如果 .spec.startingDeadlineSeconds
未指定,CronJob 控制器计算从 .status.lastScheduleTime
开始到现在为止总共错过的执行次数。
例如,某一个 CronJob 应该每分钟执行一次,.status.lastScheduleTime
的值是 上午5:00,假设现在已经是上午7:00。这意味着已经有 120 次执行时间点被错过,因此该 CronJob 将不再执行了。
如果 .spec.startingDeadlineSeconds
字段被设置为一个非空的值,则 CronJob 控制器计算将从 .spec.startingDeadlineSeconds
秒以前到现在这个时间段内错过的执行次数。
例如,假设该字段被设置为 200
,控制器将只计算过去 200 秒内错过的执行次数。如果在过去 200 秒之内,有超过 100 次错过的执行次数,则 CronJob 将不再执行。
# Concurrency Policy
.spec.concurrencyPolicy
是选填字段,指定了如何控制该 CronJob 创建的 Job 的并发性,可选的值有:
Allow
: 默认值,允许并发运行 JobForbid
: 不允许并发运行 Job;如果新的执行时间点到了,而上一个 Job 还未执行完,则 CronJob 将跳过新的执行时间点,保留仍在运行的 Job,且不会在此刻创建新的 JobReplace
: 如果新的执行时间点到了,而上一个 Job 还未执行完,则 CronJob 将创建一个新的 Job 以替代正在执行的 Job
TIP
Concurrency policy 只对由同一个 CronJob 创建的 Job 生效。如果有多个 CronJob,则他们各自创建的 Job 之间不会相互影响。
# Suspend
.spec.suspend
是选填字段。如果该字段设置为 true
,所有的后续执行都将挂起,该字段不会影响到已经创建的 Job。默认值为 false
。
警告
挂起(suspend)的时间段内,如果恰好存在有计划的执行时间点,则这些执行时间计划都被记录下来。如果不指定 .spec.startingDeadlineSeconds
,并将 .spec.suspend
字段从 true
修改为 false
,则挂起这段时间内的执行计划都将被立刻执行。
# Job History Limits
.spec.successfulJobsHistoryLimit
和 .spec.failedJobsHistoryLimit
字段是可选的。这些字段指定了 CronJob 应该保留多少个 completed 和 failed 的 Job 记录。
.spec.successfulJobsHistoryLimit
的默认值为 3.spec.failedJobsHistoryLimit
的默认值为 1
如果将其设置为 0
,则 CronJob 不会保留已经结束的 Job 的记录。