--- vssueId: 151 layout: LearningLayout description: Kubernetes的CronJob可以用来执行基于时间计划的定时任务_类似于Linux/Unix系统中的crontable_CronJob执行周期性的重复任务时非常有用_例如备份数据_发送邮件等_CronJob也可以用来指定将来某个时间点执行单个任务_例如将某项任务定时到系统负载比较低的时候执行。 meta: - name: keywords content: Kubernetes教程,K8S教程,K8S培训,Kubernetes CronJob --- # 使用CronJob执行自动任务 > 参考文档: [Running Automated Tasks with a CronJob](https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/) [CronJob](./) 可以用来执行基于时间计划的定时任务,类似于Linux/Unix系统中的 [crontable](https://en.wikipedia.org/wiki/Cron)。 CronJob 执行周期性的重复任务时非常有用,例如备份数据、发送邮件等。CronJob 也可以用来指定将来某个时间点执行单个任务,例如将某项任务定时到系统负载比较低的时候执行。 CronJob 也存在某些限制,例如,在某些情况下,一个 CronJob 可能会创建多个 Job。因此,Job 必须是 [幂等](/glossary/idempotent.md) 的。更多与此相关的限制请参考 [CronJob](./) [[TOC]] ## 创建CronJob 下面例子中的 CronJob 每分钟,打印一次当前时间并输出 hello world 信息。 <<< @/.vuepress/public/statics/learning/job/cronjob.yaml * 执行命令以创建 CronJob: ```sh kubectl create -f https://kuboard.cn/statics/learning/job/cronjob.yaml ``` 输出结果如下所示: ``` cronjob.batch/hello created ``` 或者,您也可以直接使用 `kubectl run` 命令创建 CronJob: ```sh kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster" ``` * 执行命令以查看已创建 CronJob 的状态 ``` sh kubectl get cronjob hello ``` 输出结果如下所示: ``` NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE hello */1 * * * * False 0 10s ``` 从输出结果可以看到,该 CronJob 还未运行任何 Job。执行一下命令,并等候一分钟左右时间 ``` sh kubectl get jobs --watch ``` 输出结果如下所示: ``` NAME COMPLETIONS DURATION AGE hello-4111706356 0/1 0s hello-4111706356 0/1 0s 0s hello-4111706356 1/1 5s 5s ``` 此时,可以看到该 CronJob 创建了一个 "hello-4111706356" Job,并执行结束。这时`ctrl + c` 停止 watch,并重新查看 Cronjob 的状态: ``` sh kubectl get cronjob hello ``` 输出信息如下所示: ``` {2} NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE hello */1 * * * * False 0 50s 75s ``` 输出结果显示,该 CronJob 在 `LAST SCHEDULE` 这个时间点成功创建了一个 Job。当前 `ACTIVE` Job 数为 0,意味着,该 Job 已经成功结束,或者已经失败。 * 查看 Pod 的输出信息 执行命令获取 Pod 的名称 ``` sh # 将 "hello-4111706356" 替换成您系统中的 Job name pods=$(kubectl get pods --selector=job-name=hello-4111706356 --output=jsonpath={.items[*].metadata.name}) ``` 查看 Pod 的日志: ``` sh kubectl logs $pods ``` 输出结果如下所示: ``` Fri Feb 22 11:02:09 UTC 2019 Hello from the Kubernetes cluster ``` ## 删除CronJob 当您不再需要某个 CronJob 时,可以使用命令将其删除 `kubectl delete cronjob `,在本例中,可以执行命令: ```sh kubectl delete cronjob hello ``` 或者 ``` sh kubectl delete -f https://kuboard.cn/statics/learning/job/cronjob.yaml ``` 删除 CronJob 时,将移除该 CronJob 创建的所有 Job 和 Pod,并且 CronJob 控制器将不会为其在创建任何新的 Job。更多信息请参考 [垃圾回收](/learning/k8s-intermediate/workload/gc.html) ## 编写CronJob YAML 与其他所有 Kubernetes 对象一样,CronJob 对象需要 `apiVersion`、`kind`、`metadata` 这几个字段。CronJob 还需要 `.spec` 字段。 ::: tip 所有对 CronJob 对象作出的修改,尤其是 `.spec` 的修改,都只对修改之后新建的 Job 有效,已经创建的 Job 不会受到影响 ::: ### Schedule `.spec.schedule` 是一个必填字段。类型为 [Cron](https://en.wikipedia.org/wiki/Cron) 格式的字符串,例如 `0 * * * *` 或者 `@hourly`,该字段定义了 CronJob 应该何时创建和执行 Job。 该字段同样支持 `vixie cron` step 值(step values),参考 [FreeBSD manual](https://www.freebsd.org/cgi/man.cgi?crontab%285%29)。例如,指定 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](/learning/k8s-intermediate/workload/wl-job/) 相同,只是不需要 `apiVersion` 和 `kind`。请参考 [编写Job的定义](/learning/k8s-intermediate/workload/wl-job/spec.html)。 ### 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`: 默认值,允许并发运行 Job * `Forbid`: 不允许并发运行 Job;如果新的执行时间点到了,而上一个 Job 还未执行完,则 CronJob 将跳过新的执行时间点,保留仍在运行的 Job,且不会在此刻创建新的 Job * `Replace`: 如果新的执行时间点到了,而上一个 Job 还未执行完,则 CronJob 将创建一个新的 Job 以替代正在执行的 Job ::: tip Concurrency policy 只对由同一个 CronJob 创建的 Job 生效。如果有多个 CronJob,则他们各自创建的 Job 之间不会相互影响。 ::: ### Suspend `.spec.suspend` 是选填字段。如果该字段设置为 `true`,所有的后续执行都将挂起,该字段不会影响到已经创建的 Job。默认值为 `false`。 ::: danger 警告 挂起(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 的记录。