不会飞的章鱼

熟能生巧,勤能补拙;念念不忘,必有回响。

Kubernetes编排原理——离线业务Job与Cronjob

Job

API对象定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: resouer/ubuntu-bc
# scale=10000 意思是 计算出的结果取小数点后 10000位
command: ["sh","-c","echo 'scale=10000; 4*a(1)' | bc -l "]
restartPolicy: Never # 离线计算的Pod永远不应该被重启
backoffLimit: 4

在这个模板中,我们定义了一个Ubuntu镜像的容器,他运行计算π的程序,所以,这是一个计算π的容器。

创建成功后,查看一下这个Job对象:
//TODO:
可以看到,在这个Job对象创建后,它的Pod模板被自动加上了一个controller-uid=<一个随机字符串>这样的Label。从而保证了Job与它所管理的Pod之间的匹配关系。

离线作业失败了要怎么办?

Job Controller工作原理

首先,Job Controller控制的对象直接就是Pod

其次,Job Controller在控制循环中进行的调谐操作,是根据实际Running状态的Pod的数目、已经成功退出的Pod的数目,以及parallelismcompletions参数的值共同计算出在这个周期里应该创建或者删除的Pod数目,然后调用Kubernetes API来执行这个操作。

因此,Job Controller实际上控制了作业执行的并行度(parallelism),以及总共需要完成的任务数(completions)这两个重要参数。而在实际使用时,需要根据作业的特性来决定并行度和任务数的合理取值。

CronJob

CronJob描述的是定时任务,它的API对象如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *" # 从当前开始,每一分钟执行一次
jobTemplate: # 关键!
spec:
template:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure

原来CronJob是一个Job对象的控制器。

通过以上例子,创建CronJob对象后,每一分钟后就会有一个Job产生:

//TODO:

此时,CronJob对象会记录下这次Job执行的时间:

注意:由于定时任务的特殊性,很可能某个Job还没有执行完,另外一个新Job就产生了。此时,可以通过spec.concurrenyPolicy字段来定义具体的处理策略:

  • 1,concurrenyPolicy=Allow:这是默认情况,它意味着这些Job可以同时存在;
  • 2,concurrenyPolicy=Forbid:这意味着不会创建新的Pod,该创建周期被跳过;
  • 3,concurrenyPolicy=Replace:这意味着新产生的Job会替换旧的、未执行完的Job

而如果某一次Job创建失败,这次创建就会被标记为"miss"。当在指定的时间窗口内miss的数目达到100时,CronJob会停止再创建这个Job

这个时间段可以由spec.startingDeadlineSeconds字段指定。比如,startingDeadlineSeconds=200,意味着在过去200s里,如果miss的数目达到了100,那么这个Job就不会被创建执行了。

总结

  • Job是一次性执行的离线任务;
  • CronJob是定时执行的离线任务,也就是说CronJob对象在控制Job对象,这也说明用一个对象控制另一个对象,是 Kubernetes 编排的精髓所在
------ 本文结束------
如果本篇文章对你有帮助,可以给作者加个鸡腿~(*^__^*),感谢鼓励与支持!