Job 与 CronJob

Kubernetes 集群中为我们提供了 JobCronJob 两种资源对象来应对我们的这种需求。

Job 负责处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束。而CronJob 则就是在 Job 上加上了时间调度。

Job

我们用 Job 这个资源对象来创建一个任务,我们定义一个 Job 来执行一个倒计时的任务,对应的资源清单如下所示:(job-demo.yaml)

apiVersion: batch/v1
kind: Job
metadata:
  name: job-demo
  namespace: default
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: busybox
        image: busybox
        imagePullPolicy: IfNotPresent
        args:
        - "/bin/sh"
        - "-c"
        - "for i in 5 4 3 2 1;do echo $i;done"

我们可以看到 Job 中也是一个 Pod 模板,和之前的 Deployment、StatefulSet 之类的是一致的,只是 Pod 中的容器要求是一个任务,而不是一个常驻前台的进程了,因为需要退出,另外值得注意的是 JobRestartPolicy 仅支持 NeverOnFailure 两种,不支持 Always

直接创建这个 Job 对象

[root@k8s-master k8s-yaml]# kubectl apply -f job-demo.yaml 
job.batch/job-demo created

[root@k8s-master k8s-yaml]# kubectl get pods
NAME             READY   STATUS      RESTARTS   AGE
job-demo-jsl9s   0/1     Completed   0          2m8s

我们可以看到很快 Pod 变成了 Completed 状态,这是因为容器的任务执行完成正常退出了,我们可以查看对应的日志:

[root@k8s-master k8s-yaml]# kubectl logs job-demo-jsl9s
5
4
3
2
1

如果的任务执行失败了,如果定义了 restartPolicy=OnFailure,那么任务在执行失败后 Job 控制器就会不断地尝试创建一个新 Pod,当然,这个尝试肯定不能无限进行下去。我们可以通过 Job 对象的 spec.backoffLimit 字段来定义重试次数,另外需要注意的是 Job 控制器重新创建 Pod 的间隔是呈指数增加的,即下一次重新创建 Pod 的动作会分别发生在 10s、20s、40s… 后。

如果我们定义的 restartPolicy=Never,那么任务执行失败后,Job 控制器就不会去尝试创建新的 Pod 了,它会不断地尝试重启 Pod 里的容器。

上面我们这里的 Job 任务对应的 Pod 在运行结束后,会变成 Completed 状态,但是如果执行任务的 Pod 因为某种原因一直没有结束怎么办呢?同样我们可以在 Job 对象中通过设置字段 spec.activeDeadlineSeconds 来限制任务运行的最长时间,比如:

spec:
 activeDeadlineSeconds: 100

那么当我们的任务 Pod 运行超过了 100s 后,这个 Job 的所有 Pod 都会被终止,并且, Pod 的终止原因会变成 DeadlineExceeded

CronJob

CronJob 其实就是在 Job 的基础上加上了时间调度,我们可以在给定的时间点运行一个任务,也可以周期性地在给定时间点运行。这个实际上和我们 Linux 中的 crontab 就非常类似,也是分、时、日、月、周

CronJob 会通过 job 模板(jobTemplate)来实现自动创建 job,下面我们定义一个(cronjob-demo.yaml)

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: cron-demo
  namespace: default
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: test
            image: busybox
            imagePullPolicy: IfNotPresent
            args:
            - "/bin/sh"
            - "-c"
            - "for i in 5 4 3 2 1;do echo $i;done"

要注意的是.spec.schedule字段是必须填写的,用来指定任务运行的周期,格式就和 crontab 一样,另外一个字段是.spec.jobTemplate, 用来指定需要运行的任务,格式当然和 Job 是一致的。还有一些值得我们关注的字段 .spec.successfulJobsHistoryLimit(默认为3) 和 .spec.failedJobsHistoryLimit(默认为1),表示历史限制,是可选的字段,指定可以保留多少完成和失败的 Job。然而,当运行一个 CronJob 时,Job 可以很快就堆积很多,所以一般推荐设置这两个字段的值。如果设置限制的值为 0,那么相关类型的 Job 完成后将不会被保留。

然后我们直接创建 cronjob 对象

[root@k8s-master k8s-yaml]# kubectl apply -f cronjob-demo.yaml 
cronjob.batch/cron-demo created

[root@k8s-master k8s-yaml]# kubectl get cronjob
NAME        SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cron-demo   */1 * * * *   False     0        <none>          7s

稍等一会,我们就可以查看 job 对象,就是由 CronJob 每隔一分钟执行一次创建出来的

[root@k8s-master k8s-yaml]# kubectl get job
NAME                   COMPLETIONS   DURATION   AGE
cron-demo-1626320340   1/1           2s         2m12s
cron-demo-1626320400   1/1           0s         71s
cron-demo-1626320460   1/1           1s         11s

如果不需要执行 CronJob 了直接删除就可以了

[root@k8s-master k8s-yaml]# kubectl delete -f cronjob-demo.yaml 
cronjob.batch "cron-demo" deleted
本作品采用《CC 协议》,转载必须注明作者和本文链接
(= ̄ω ̄=)··· 暂无内容!

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!