1. CronJob

CronJob 管理基于时间的 Job,即:

  • 在给定时间点只运行一次
  • 周期性地在给定时间点运行。创建周期性运行的 Job,例如:数据库备份、发送邮件。

注意:

Cronjob 管理的对象是 job,job 运行时创建的 pod,cronjob不直接管理 pod。

一个 CronJob 对象类似于 Linux 系统计划任务 crontab 文件中的一行。它根据指定的预定计划周期性地运行一个 Job,格式可以参考 Cron

从集群版本 1.8 开始,batch/v2alpha1 API 组中的 CronJob 资源已经被废弃。 你应该切换到 API 服务器默认启用的 batch/v1beta1 API 组。

对于先前版本的集群,版本 < 1.8,启动 API Server(参考 为集群开启或关闭 API 版本 获取更多信息)时,通过传递选项 --runtime-config=batch/v2alpha1=true 可以开启 batch/v2alpha1 API。

在 Kubernetes 1.4 版本引入了 ScheduledJob 资源,但从 1.5 版本开始改成了 CronJob。

为 CronJob 资源创建清单时,请确保所提供的名称是一个合法的 DNS 子域名. 名称不能超过 52 个字符。 这是因为 CronJob 控制器将自动在提供的 Job 名称后附加 11 个字符,并且存在一个限制, 即 Job 名称的最大长度不能超过 63 个字符。

1.1. API 版本对照表

Kubernetes 版本 Batch API 版本 默认开启
v1.5-v1.7 batch/v2alpha1
v1.8-v1.9 batch/v1beta1

注意:使用默认未开启的 API 时需要在 kube-apiserver 中配置 --runtime-config=batch/v2alpha1

1.2. CronJob Spec

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
  namespace: test-ns
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

1.2.1. schedule

.spec.schedule调度,必需字段,指定任务运行周期,格式同 Cron

它的值是 Cron 格式字的符串,例如:0 * * * *,或者 @hourly,根据指定的调度时间 Job 会被创建和执行。

在预定计划中,问号(?)和星号(*)的意义是相同的,表示给定字段的取值是任意可用值。

注意:

所有 CronJob 的 schedule 时间都是基于初始 Job 的主控节点的时区。

Crontab 基本语法:

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

该格式也包含了扩展的 vixie cron 步长值。 FreeBSD 手册中解释如下: 步长可被用于范围组合。范围后面带有 /<数字> 可以声明范围内的步幅数值。 例如,0-23/2 可被用在小时域来声明命令在其他数值的小时数执行 ( V7 标准中对应的方法是0,2,4,6,8,10,12,14,16,18,20,22)。 步长也可以放在通配符后面,因此如果你想表达 "每两小时",就用 */2 。

1.2.2. jobTemplate

.spec.jobTemplateJob 模板,必需字段,指定需要运行的任务,格式同 Job。

它是 Job 的模板。 除了它可以是嵌套的,并且不具有 apiVersion 或 kind 字段之外,它和 Job 一样具有完全相同的模式(schema)。 参考 编写 Job 规格。

1.2.3. startingDeadlineSeconds

.spec.startingDeadlineSeconds启动 Job 的期限(秒级别),该字段是可选的。它表示任务如果由于某种原因错过了调度时间,开始该任务的截止时间的秒数。过了截止时间,CronJob 就不会开始任务。 不满足这种最后期限的任务会被统计为失败任务。如果该域没有声明,那任务就没有最后期限。

CronJob 控制器会统计错过了多少次调度。如果错过了100次以上的调度,CronJob 就不再调度了。 当没有设置 .spec.startingDeadlineSeconds 时,CronJob 控制器统计从 status.lastScheduleTime 到当前的调度错过次数。 例如一个 CronJob 期望每分钟执行一次,status.lastScheduleTime是 5:00am, 但现在是 7:00am。那意味着 120 次调度被错过了,所以 CronJob 将不再被调度。 如果设置了 .spec.startingDeadlineSeconds 域(非空),CronJob 控制器统计从 `.spec.startingDeadlineSeconds1 到当前时间错过了多少次任务。 例如设置了 200,它会统计过去 200 秒内错过了多少次调度。 在那种情况下,如果过去 200 秒内错过了超过 100 次的调度,CronJob 就不再调度。

1.2.4. successfulJobsHistoryLimit

.spec.successfulJobsHistoryLimit 历史成功任务的保留数量,该字段是可选的,在 Kubernetes 1.8版本后支持。

成功完成的作业保存多少个。默认为3,设置限制的值为 0时相关类型的 Job 完成后将不会被保留。

1.2.5. failedJobsHistoryLimit

.spec.failedJobsHistoryLimit : 历史失败任务的保留数量,该字段是可选的,在 Kubernetes 1.8版本后支持。

失败的作业保存多少个,默认为1,设置限制的值为 0时相关类型的 Job 完成后将不会被保留。

1.2.6. concurrencyPolicy

.spec.concurrencyPolicy并发策略,该字段也是可选的。它指定了如何处理被 Cron Job 创建的 Job 的并发执行。只允许指定下面策略中的一种:

  • Allow(默认):允许并发运行 Job
  • Forbid:禁止并发运行,如果前一个还没有完成,则直接跳过下一个
  • Replace:取消当前正在运行的 Job,用一个新的来替换

注意:

当前策略只能应用于同一个 Cron Job 创建的 Job。如果存在多个 Cron Job,它们创建的 Job 之间总是允许并发运行。

1.2.7. suspend

.spec.suspend挂起,该字段也是可选的。如果设置为 true,后续所有执行都会被挂起。它对已经开始执行的 Job 不起作用。默认值为 false

注意:

在调度时间内挂起的执行都会被统计为错过的任务。当 .spec.suspendtrue 改为 false 时, 且没有开始的最后期限,错过的任务会被立即调度。

1.3. 示例

1.3.1. 创建cronjob

$ kubectl create -f cronjob.yaml
cronjob "hello" created

当然,也可以用kubectl run来创建一个CronJob:

kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster"

1.3.2. 查看cronjob

$ kubectl get cronjob
NAME      SCHEDULE      SUSPEND   ACTIVE    LAST-SCHEDULE
hello     */1 * * * *   False     0         <none>


$ kubectl get jobs
NAME               DESIRED   SUCCESSFUL   AGE
hello-1202039034   1         1            49s
$ pods=$(kubectl get pods --selector=job-name=hello-1202039034 --output=jsonpath={.items..metadata.name})

$ kubectl logs $pods
Mon Aug 29 21:34:09 UTC 2016
Hello from the Kubernetes cluster

$ kubectl delete cronjob hello
cronjob "hello" deleted

1.3.3. 删除 Cron Job

一旦不再需要 Cron Job,简单地可以使用 kubectl 命令删除它:

$ kubectl delete cronjob hello
cronjob "hello" deleted

这将会终止正在创建的 Job。

然而,运行中的 Job 将不会被终止,不会删除 Job 或 它们的 Pod。

为了清理那些 Job 和 Pod,需要列出该 Cron Job 创建的全部 Job,然后删除它们:

$ kubectl get jobs
NAME               DESIRED   SUCCESSFUL   AGE
hello-1201907962   1         1            11m
hello-1202039034   1         1            8m
...

$ kubectl delete jobs hello-1201907962 hello-1202039034 ...
job "hello-1201907962" deleted
job "hello-1202039034" deleted
...

一旦 Job 被删除,由 Job 创建的 Pod 也会被删除。

注意:

所有由名称为 “hello” 的 Cron Job 创建的 Job 会以前缀字符串 “hello-” 进行命名。如果想要删除当前 Namespace 中的所有 Job,可以通过命令 kubectl delete jobs --all 立刻删除它们。

1.4. 扩展阅读

1.4.1. CronJob 限制

CronJob 根据其计划编排,在每次该执行任务的时候大约会创建一个 Job。 我们之所以说 "大约",是因为在某些情况下,可能会创建两个 Job,或者不会创建任何 Job。 我们试图使这些情况尽量少发生,但不能完全杜绝。因此,Job 应该是 幂等的。

如果 startingDeadlineSeconds 设置为很大的数值或未设置(默认),并且 concurrencyPolicy 设置为 Allow,则作业将始终至少运行一次。

对于每个 CronJob,CronJob 控制器 检查从上一次调度的时间点到现在所错过了调度次数。如果错过的调度次数超过 100 次, 那么它就不会启动这个任务,并记录这个错误:

Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew.

需要注意的是,如果 startingDeadlineSeconds 字段非空,则控制器会统计从 startingDeadlineSeconds 设置的值到现在而不是从上一个计划时间到现在错过了多少次 Job。 例如,如果 startingDeadlineSeconds 是 200,则控制器会统计在过去 200 秒中错过了多少次 Job。

如果未能在调度时间内创建 CronJob,则计为错过。 例如,如果 concurrencyPolicy 被设置为 Forbid,并且当前有一个调度仍在运行的情况下, 试图调度的 CronJob 将被计算为错过。

例如,假设一个 CronJob 被设置为从 08:30:00 开始每隔一分钟创建一个新的 Job,并且它的 startingDeadlineSeconds 字段 未被设置。如果 CronJob 控制器从 08:29:00 到 10:21:00 终止运行,则该 Job 将不会启动,因为其错过的调度次数超过了100。

为了进一步阐述这个概念,假设将 CronJob 设置为从 08:30:00 开始每隔一分钟创建一个新的 Job, 并将其 startingDeadlineSeconds 字段设置为 200 秒。 如果 CronJob 控制器恰好在与上一个示例相同的时间段(08:29:00 到 10:21:00)终止运行, 则 Job 仍将从 10:22:00 开始。 造成这种情况的原因是控制器现在检查在最近 200 秒(即 3 个错过的调度)中发生了多少次错过的 Job 调度,而不是从现在为止的最后一个调度时间开始。

CronJob 仅负责创建与其调度时间相匹配的 Job,而 Job 又负责管理其代表的 Pod。

Copyright © 温玉 2021 | 浙ICP备2020032454号 all right reserved,powered by Gitbook该文件修订时间: 2023-05-20 21:15:12

results matching ""

    No results matching ""