kubernete编排技术四:Job和CronJob

简介: kubernete编排技术四:Job和CronJob

微信图片_20221212124117.jpg这篇文章我们学习一下kubernete对Job的编排。不同于前面讲的Deployment、StatefulSet的编排,Job是一个执行一次就结束的pod,并不会滚动更新。


Job


定义job非常简单,只要在yaml文件中把kind字段定义成Job就可以了。如下kubejob.yaml:

apiVersion: batch/v1
kind: Job
metadata:
  name: kubejob
spec:
  parallelism: 2
  completions: 4
  template:
    spec:
      containers:
      - name: myjob
        image: zjj2006forever/kubejob:1.0
        imagePullPolicy: IfNotPresent
      restartPolicy: Never
  backoffLimit: 4
  activeDeadlineSeconds: 600

    restartPolicy:重启策略,这儿我们定义是Never,就是如果任务失败后不会重启,而是会创建一个新pod出来,直到创建次数超过了backoffLimit。如果设置成OnFailure,则失败后不会重新创建pod而是会重启。

    backoffLimit:默认是6,我们定义失败次数是4

    activeDeadlineSeconds:控制pod重新创建时间,防止失败后无限制的重新创建,Job运行结束后就会进入Completed状态,如果Job一直没有执行成功,就会反复地重新创建,直到时间超过activeDeadlineSeconds的值,上面我设置了600s如果Job在600s后还没有完成,那就会结束。

    parallelism:任务并行度,上面设置是2个,这样就会生成2个pod并行执行

    completions:期望有多少个pod执行完成后整个任务结束,上面设置是4


    注意:上面的Job中,需要创建pod的数量 = 期望总共完成的pod数量(completions参数) - Completed状态的pod数量(已完成) - running状态的pod数量(运行中)


    下面我们写一段java代码,这段代码很简单,每隔12s一次依次输出0到9的数,我把它打成一个镜像,提交到我的dockerhub,名称:zjj2006forever/kubejob:1.0

    public class JobTest {
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < 10; i++){
                System.out.println(i);
                Thread.sleep(12000);
            }
        }
    }

    上面的镜像打包好后,执行如下命令创建Job

    [root@master kubejob]# kubectl create -f kubejob.yaml 
    job.batch/kubejob created

    这时我们看一下Job的描述

    [root@master kubejob]# kubectl describe jobs/kubejob
    Name:                     kubejob
    Namespace:                default
    Selector:                 controller-uid=190e811d-4d89-4d1d-9911-144499413c3a
    Labels:                   controller-uid=190e811d-4d89-4d1d-9911-144499413c3a
                              job-name=kubejob
    Annotations:              <none>
    Parallelism:              2
    Completions:              4
    Start Time:               Thu, 30 Jul 2020 07:14:53 -0400
    Active Deadline Seconds:  600s
    Pods Statuses:            2 Running / 0 Succeeded / 0 Failed
    Pod Template:
      Labels:  controller-uid=190e811d-4d89-4d1d-9911-144499413c3a
               job-name=kubejob
      Containers:
       myjob:
        Image:        zjj2006forever/kubejob:1.0
        Port:         <none>
        Host Port:    <none>
        Environment:  <none>
        Mounts:       <none>
      Volumes:        <none>
    Events:
      Type    Reason            Age   From            Message
      ----    ------            ----  ----            -------
      Normal  SuccessfulCreate  105s  job-controller  Created pod: kubejob-vxgzg
      Normal  SuccessfulCreate  105s  job-controller  Created pod: kubejob-tbgqj

    上面的输出我要说明一下,我们看到有一个Selector,是给了controller一个uid,这个uid的作用是匹配job和它管理的pod的对应关系,也就是通过这个uid,Job才可以管理它创建的pod。


    然后查看pod数量,2个pod都已经进入了running状态。

    [root@master kubejob]# kubectl get pods
    NAME            READY   STATUS    RESTARTS   AGE
    kubejob-tbgqj   1/1     Running   0          5s
    kubejob-vxgzg   1/1     Running   0          5s

    上面的输出我们看到当前有2个pod正在并行执行,4分钟以后,我们查看所有的pod,都已经完成

    [root@master kubejob]# kubectl get pods
    NAME            READY   STATUS      RESTARTS   AGE
    kubejob-fnx6b   0/1     Completed   0          3m9s
    kubejob-tbgqj   0/1     Completed   0          5m13s
    kubejob-vxgzg   0/1     Completed   0          5m13s
    kubejob-w7zlb   0/1     Completed   0          3m9s

    而我们这时再查看pod的状态,COMPLETIONS说明期望4个任务都已经完成

    [root@master kubejob]# kubectl get Job
    NAME      COMPLETIONS   DURATION   AGE
    kubejob   4/4           4m8s       19m

    我们查看其中一个pod的日志,输出正确,如下图:

    [root@master kubejob]# kubectl logs kubejob-fnx6b
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9

    CronJob


    从名字中我们也可以看出,这是一个定时任务控制器,事实上,它也是用标准的Unix cron表达式来控制任务的执行。它的定义也非常简单,把kind定义成CronJob。我们先定义一个yaml文件cronjob.yaml如下:

    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
      name: mycronjob
    spec:
      schedule: "*/1 * * * *"
      jobTemplate:
        spec:
          template:
            spec:
              containers:
              - name: mycronjob
                image: zjj2006forever/kubejob:1.0
                imagePullPolicy: IfNotPresent
              restartPolicy: OnFailure
      concurrencyPolicy: Replace

    从上面的yaml定义中我们看到有一个jobTemplate属性,他是一个job的模板,用来控制Job对象。所以,CronJob其实是一个Job对象的控制器。还记得之前文章《kubernete编排技术二:deployment》中用deployment来控制ReplicaSet对象吗,其实是一个道理。


    CronJob对Job的控制,是通过参数schedule来进行的,这个参数的表达式就跟我们在linux下创建定时任务配置的cron时间格式一样。


    这儿要注意,我上面定义的cron表达式是每分钟执行一次,但是上面我写的java应用是每2分钟才能执行,那是不是会有时间段内同时存在2个任务呢?

    我们可以用这个字段来控制spec.concurrencyPolicy,它有3个属性值:默认是Allow,允许job同时存在;Forbid表示上一个任务没有执行完成这个任务不允许创建;Replace表示新产生的任务pod会替换掉旧的。


    接下来我们创建这个CronJob,执行下面命令:


    kubectl create -f cronjob.yaml

    查看创建的任务:

    [root@master kubejob]# kubectl get CronJob
    NAME        SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
    mycronjob   */1 * * * *   False     1        21s             4m14s

    再看一下pod和日志打印:

    [root@master kubejob]# kubectl get pods
    NAME                         READY   STATUS    RESTARTS   AGE
    mycronjob-1596280800-9xnpm   1/1     Running   0          52s
    [root@master kubejob]# kubectl logs mycronjob-1596280800-9xnpm
    0
    1
    2
    3
    4

    这时我们看到其中一个pod打印出5个数之后(用了一分钟),就消失了,出现了新的Pod,这也印证了我们yaml文件中的spec.concurrencyPolicy=Replace

    [root@master kubejob]# kubectl logs mycronjob-1596280800-9xnpm
    Error from server (NotFound): pods "mycronjob-1596280800-9xnpm" not found

    下面的输出我们还看到了pod被Replace的过程

    [root@master kubejob]# kubectl get pods
    NAME                         READY   STATUS              RESTARTS   AGE
    mycronjob-1596280920-2vlhr   1/1     Terminating         0          60s
    mycronjob-1596280980-gvqqd   0/1     ContainerCreating   0          0s
    [root@master kubejob]# kubectl get pods
    NAME                         READY   STATUS    RESTARTS   AGE
    mycronjob-1596280980-gvqqd   1/1     Running   0          14s

    最后说明一下,如果一个Job创建失败,这个Job就标记为miss,一旦指定时间内miss次数达到100,CronJob会停止再创建这个Job。这个时间可以由spec.startingDeadlineSeconds参数指定,单位是s。这里我就不再实验了。


    总结


    相对于之前讲的编排技术,Job和CronJob是相对比较简单一种的编排技术,但是也非常重要,包括怎么控制并发任务(parallelism),怎么控制完成数量(completions),还有定时任务配置(schedule)。这些对kubernete中的应用起了很好的支持。

    相关文章
    |
    2月前
    |
    Kubernetes Perl 容器
    kubernetes 的Job 的并行执行 配置
    在Kubernetes中,Job是一种用于批处理任务的Controller对象。如果你想要配置Job以支持并行执行,可以使用Job的`.spec.parallelism`字段。这个字段定义了Job中可以并行运行的Pod的最大数量。 下面是一个简单的Job定义,其中包含了`.spec.parallelism`字段: ```yaml apiVersion: batch/v1 kind: Job metadata: name: example-job spec: parallelism: 3 # 这里定义了并行运行的Pod的数量 completions: 5 # 定义了成功完成的
    |
    12月前
    |
    Kubernetes 算法 调度
    13-Kubernetes-Pod详解-调度
    13-Kubernetes-Pod详解-调度
    |
    消息中间件 Kubernetes 小程序
    kubernetes job玩转到底
    kubernetes job玩转到底
    |
    12月前
    |
    Kubernetes Cloud Native Ubuntu
    【探索 Kubernetes|作业管理篇 系列 16】离线业务 Job、CronJob
    大家好,我是秋意零。 在上一篇中,我们讲解了 DaemonSet 控制器,相信你以及理解了其的工作过程,分为三部。一是,获取所有 Node 节点中的 Pod;二是,判断是否有符合 DaemonSet 管理的 Pod;三是,通过“亲和性”和“容忍”来精确控制并保证 Pod 在目标节点运行。 今天的内容是 Job 与 CronJob 离线业务控制器。
    386 1
    |
    设计模式 Kubernetes Cloud Native
    【探索 Kubernetes|作业管理篇 系列 7】探究 Pod 有什么用,为什么需要它
    【探索 Kubernetes|作业管理篇 系列 7】探究 Pod 有什么用,为什么需要它
    71 1
    |
    12月前
    |
    Perl
    18-Kubernetes-Pod控制器详解- Job
    18-Kubernetes-Pod控制器详解- Job
    |
    编解码 运维 Kubernetes
    【探索 Kubernetes|作业管理篇 系列 9】Pod 的服务对象(上)
    【探索 Kubernetes|作业管理篇 系列 9】Pod 的服务对象(上)
    115 0
    |
    Kubernetes 安全 API
    【探索 Kubernetes|作业管理篇 系列 9】Pod 的服务对象(下)
    【探索 Kubernetes|作业管理篇 系列 9】Pod 的服务对象(下)
    103 0
    |
    存储 Kubernetes 监控
    【探索 Kubernetes|作业管理篇 系列 15】DaemonSet 的”过人之处“
    【探索 Kubernetes|作业管理篇 系列 15】DaemonSet 的”过人之处“
    81 0
    |
    消息中间件 Kubernetes API
    Kubernetes: Job 和 CronJob 的实现原理
    Kubernetes: Job 和 CronJob 的实现原理
    1068 0
    Kubernetes: Job 和 CronJob 的实现原理