k8s之job和cronjob

写在前面

本文一起看下使用k8s来进行作业和定时作业。

1:k8s的业务类型

如果是按照业务类型来划分的话,可以分为离线业务在线业务,如下:

在线业务:容器启动之后就一直不退出的业务,如Nginx
离线业务:容器启动后执行一段时间就退出,如busybox
    job:提供容器单次运行的能力
    cronJob:提供容器多次运行的能力

busybox是一个集成了很多命令和工具的软件,进行了压缩,体积小,方便使用。

针对在线业务使用pod启动容器后,就在那里好好的运行就行了,但是对于离线业务,怎么办呢?pod只具备编排容器的能力,但并不具备以某种运行方式运行容器的能力,比如以某种固定的时间频率运行一组容器,那么我们能不能在pod原有功能的基础上对其改造让其具备这种能力呢?理论上是可以的,但是这就不符合面向对象的单一职责原则了,毕竟k8s的apiserver的请求处理方式也是按照面向对象的思想来封装的,这怎么办呢?我们知道,有一种设计模式叫做装饰模式 ,通过组合原有的对象,即将原有对象作为自己的成员变量,这样在使用其固有能力的同时,也可以增加自己需要的增强逻辑了,比如我们这里对于pod装饰,如果是Job,则装饰后的伪代码可能如下:

class Job {
    private Pod pod = new Pod();
    // 任务执行设置信息
    private JobSetting jobSetting = new JobSetting("任务设置信息");
    public void run() {
       // 满足job要求
       if (满足jobSetting要求) {
          // 通过pod编排容器,执行作业
          pod.orchestrationContainers();
       }
    }
}

现在pod在job的增强下已经能够按照某种设置来执行离线作业了,但是如果是想要实现cronJob又该怎么办呢?依然是如此,继续装饰job即可,如下伪代码:

class CronJob {
    private Job job = new Job();
    // 设置执行频率的对象
    private Cron cron = new Cron("*/1 * * * *");
    public void run() {
       while (true) {
          if (cron判断又该执行了) {
             // 通过job执行离线作业
             job.run();
          }
       }
    }
}

其实k8s也正是这么做的,接下来就一起看下。

2:Job

首先通过如下操作生成Job的yaml:

dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl create job echo-job --image=busybox $out
apiVersion: batch/v1
kind: Job
metadata:
  creationTimestamp: null
  name: echo-job
spec:
  template:
    metadata:
      creationTimestamp: null
    spec:
      containers:
      - image: busybox
        name: echo-job
        resources: {}
      restartPolicy: Never
status: {}

修改后最终如下:

apiVersion: batch/v1
kind: Job
metadata:
  name: echo-job

spec:
  template:
    spec:
      restartPolicy: OnFailure
      containers:
      - image: busybox
        name: echo-job
        imagePullPolicy: IfNotPresent
        command: ["/bin/echo"]
        args: ["hello", "world"]

然后创建job:

dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl apply -f job.yml
job.batch/echo-job created

查看pod(因为是对pod的装饰或增强,所以底层还是要创建pod的),如下可以获取job:

dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get job
NAME       COMPLETIONS   DURATION   AGE
echo-job   1/1           15s        10m

其中COMPLETIONS是1/1说明作业已经完成了,DURATION作业持续时长是15s。当然也可以看其内部的pod,如下:

dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get pod
NAME             READY   STATUS      RESTARTS   AGE
echo-job-rjq86   0/1     Completed   0          2m9s

可以看到pod的名字是echo-job-rjq86,是在job的name后自动增加了一个随机后缀,这样我们就不需要在yaml中配置了,降低使用的复杂度,另外READY是0/1,是因为这是一个离线任务,执行完毕后就结束了,如下可以看到job包装的pod中容器的输出信息:

dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl logs -c echo-job echo-job-rjq86 
hello world

我们在前面分析了job是对pod的装饰和增强,其实从yaml文件的结构也是可以看出来的,参考下图:

k8s之job和cronjob_第1张图片

看到这里,你可能会想,job也不过如此,我直接用pod也可以实现,何必多此一举,但实际job能力远不止于此,它还提供了很多的配置参数,如下的几个:

activeDeadlineSeconds,设置 Pod 运行的超时时间。
backoffLimit,设置 Pod 的失败重试次数。
completions,Job 完成需要运行多少个 Pod,默认是 1 个。
parallelism,它与 completions 相关,表示允许并发运行的 Pod 数量,避免过多占用资源。

然后我们就可以将Job的参数设置成15秒超时,最多重试2次,总共需要运行完4个 Pod,但同一时刻最多并发2个Pod,yaml如下:


apiVersion: batch/v1
kind: Job
metadata:
  name: sleep-job

spec:
  activeDeadlineSeconds: 15
  backoffLimit: 2
  completions: 4
  parallelism: 2

  template:
    spec:
      restartPolicy: OnFailure
      containers:
      - image: busybox
        name: echo-job
        imagePullPolicy: IfNotPresent
        command:
          - sh
          - -c
          - sleep $(($RANDOM % 10 + 1)) && echo done

创建job:

dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl apply -f sleepjob.yml 
job.batch/sleep-job created

查看作业执行进度:

dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get job
NAME        COMPLETIONS   DURATION   AGE
sleep-job   3/4           9s         9s
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get job
NAME        COMPLETIONS   DURATION   AGE
sleep-job   4/4           14s        14s

一共4个任务,最终变成4/4即所有的作业都完成了,如下也可以查看执行的进度:

dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get pod -w
NAME              READY   STATUS      RESTARTS   AGE
sleep-job-6jdkh   1/1     Running     0          8s
sleep-job-cmwbm   0/1     Completed   0          8s
sleep-job-kgc9l   1/1     Running     0          4s
sleep-job-6jdkh   0/1     Completed   0          9s
sleep-job-6gd9l   0/1     Pending     0          0s
sleep-job-6gd9l   0/1     Pending     0          0s
sleep-job-6gd9l   0/1     ContainerCreating   0          0s
sleep-job-6jdkh   0/1     Completed           0          9s
sleep-job-6gd9l   1/1     Running             0          1s
sleep-job-kgc9l   0/1     Completed           0          9s
sleep-job-kgc9l   0/1     Completed           0          9s
sleep-job-6gd9l   1/1     Completed         0          6s

可以看到容器在不断的进行创建,运行,完成,这个其实就是job在根据我们的设置信息来不断的调用pod的功能的过程,这个不断的创建,运行,完成也正是job对pod装饰的内容。

3:CronJob

上面我们看了job,再看cronjob就容易多了,cronjob就是对job进行了进一步的装饰,增加了按照固定周期执行job的功能,如下生成cronjob对应的yaml:

dongyunqi@dongyunqi-virtual-machine:~/test$ export out="--dry-run=client -o yaml"              # 定义Shell变量
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl create cj echo-cj --image=busybox --schedule="" $out
apiVersion: batch/v1
kind: CronJob
metadata:
  creationTimestamp: null
  name: echo-cj
spec:
  jobTemplate:
    metadata:
      creationTimestamp: null
      name: echo-cj
    spec:
      template:
        metadata:
          creationTimestamp: null
        spec:
          containers:
          - image: busybox
            name: echo-cj
            resources: {}
          restartPolicy: OnFailure
  schedule: ""
status: {}

修改完善后如下:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: echo-cj

spec:
  schedule: '*/1 * * * *'
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - image: busybox
            name: echo-cj
            imagePullPolicy: IfNotPresent
            command: ["/bin/echo"]
            args: ["hello", "world"]

主要增加了schedule表达式 用来设置job执行的频率,如下创建cronjob对象:

dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl apply -f cronjob.yml 
cronjob.batch/echo-cj created

这样就会按照每分钟一次的频率来执行作业了,如下查看生成的job和pod:

dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get job
NAME               COMPLETIONS   DURATION   AGE
echo-cj-27884435   1/1           1s         2m4s
echo-cj-27884436   1/1           1s         64s
echo-cj-27884437   1/1           0s         4s
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get pod
NAME                     READY   STATUS      RESTARTS   AGE
echo-cj-27884435-j2mjg   0/1     Completed   0          2m8s
echo-cj-27884436-8fbxs   0/1     Completed   0          68s
echo-cj-27884437-5nqkc   0/1     Completed   0          8s

可以看到每个job都对应一个pod(通过pod名称前缀可以匹配到所属的job)。最后看下此时cronjob对job的装饰结构:

k8s之job和cronjob_第2张图片

写在后面

小节

本文先分析了面向对象中的装饰设计模式,后又介绍了在线任务和离线任务,然后进行类比分别引出了job对pod的装饰,cronjob对job的装饰,并分别看了具体的例子,希望能帮助到你。

参考文章列表

cron任务表达式 。

你可能感兴趣的:(k8s,kubernetes,job,cronjob,装饰设计模式)