Job 会根据任务创建出一个或多个Pod, 并确保指定数量的 Pod 可以成功执行到进程正常结束。
- 当数量达到指定的成功个数阈值时,任务(即 Job)结束。
- 删除 Job 会清除所创建的全部 Pod,运行中的 Job 也会被清除
- 挂起 Job 的操作会删除 Job 的所有活跃 Pod,直到 Job 被再次恢复执行。
Job
编写Job规范
Job 对象的定义非常简单,如下
所示
:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: busybox
command: ["sh", "-c", "echo 'scale=1000; 4*a(1)' | bc -l "]
restartPolicy: Never
backoffLimit: 4
这个yaml文件中,我们一眼就看到了,Pod模板,即.spec.template字段
- Pod模板描述的是一个计算Π的容器
-
Job的.spec中只有
.spec.template
是必须字段 -
Pod的
RestartPolicy
只能设置为Never或OnFailure, 在 Deployment 对象里,restartPolicy 则只允许被设置为 Always -
跟其他控制器不同的是,Job 对象并不要求你定义一个
.spec.selector
来描述要控制哪些 Pod。 -
重试次数到达
.spec.backoffLimit
所设的上限,Job 会被标记为失败, 其中运行的 Pod 都会被终止。
创建这个Job
[root@sztcyl-177-9-244 ycloud]# kubectl apply -f job-pi.yaml
job.batch/pi created
查看下Job描述信息
[root@ycloud ~]# kubectl describe job pi
Name: pi
Namespace: default
Selector: controller-uid=76731211-42fe-46b0-9161-33b8283dc390
Labels: controller-uid=76731211-42fe-46b0-9161-33b8283dc390
job-name=pi
Annotations: <none>
Parallelism: 1
·········
Pod Template:
Labels: controller-uid=76731211-42fe-46b0-9161-33b8283dc390
job-name=pi
Containers:
pi:
Image: busybox
Port: <none>
Host Port: <none>
Command:
sh
-c
echo 'scale=10000; 4*a(1)' | bc -l
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 47m job-controller Created pod: pi--1-vrsm8
Normal Completed 36m job-controller Job completed
我们可以看到,这个Job对象在被创建之后,
selector
和
lable
这两个字段自动添加了controller-uuid相同的值,从而确保其不会与任何其他 Job 重叠
Job内部自动添加的与pod的关联,为了避免不同Job之间无法确认管理的Pod。
运行时间
如果Job运行失败,Job控制器不会去启动新的Pod,但是,它会不停的去重启容器,知道任务完成。在Job对象中有一个字段可以控制运行时间,防止任务运行失败,一直重启任务。
”activeDeadlineSeconds“,设置Job的运行时间,一旦达到,运行中的Pod就会被中止。
示例
apiVersion: batch/v1
kind: Job
metadata:
name: pi-sec
spec:
template:
spec:
containers:
- name: pi
image: busybox
command: ["sh", "-c", "echo 'scale=10000; 4*a(1)' | bc -l "]
restartPolicy: Never
backoffLimit: 4
activeDeadlineSeconds: 5
注意 Job 的
.spec.activeDeadlineSeconds
优先级高于其
.spec.backoffLimit
设置。
我们把运行时间设置为5秒,然后运行Job,查看运行结果
[root@ycloud ycloud]# kubectl get po
NAME READY STATUS RESTARTS AGE
pi-sec--1-99h2m 0/1 Error 0 22s
pi-sec--1-gdm2s 0/1 Error 0 52s
pi-sec--1-mfdvg 0/1 Error 0 54s
pi-sec--1-tqfxs 0/1 Error 0 42s
我们发现创建的Pod状态都是 Error,
[root@ycloud ycloud]# kubectl describe jobs pi-sec
Name: pi-sec
Namespace: default
Selector: controller-uid=71cf756b-e074-499c-90c9-e4f824e03b1a
Labels: controller-uid=71cf756b-e074-499c-90c9-e4f824e03b1a
······
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 7m32s job-controller Created pod: pi-sec--1-mfdvg
Normal SuccessfulCreate 7m30s job-controller Created pod: pi-sec--1-gdm2s
Normal SuccessfulCreate 7m20s job-controller Created pod: pi-sec--1-tqfxs
Normal SuccessfulCreate 7m job-controller Created pod: pi-sec--1-99h2m
Warning DeadlineExceeded 6m20s job-controller Job was active longer than specified deadline
我们查看Job对象的事件描述,看到Job失败的原因是 DeadlineExceeded
Job并行执行
completions 和 parallelism
-
completions,它定义的是 Job 至少要完成的 Pod 数目,即 Job 的最小完成数。
-
parallelism,它定义的是一个 Job 在任意时间最多可以启动多少个 Pod 同时运行;
当成功Pode个数达到completions阈值,Job被视为成功;
示例
apiVersion: batch/v1
kind: Job
metadata:
name: pi-com
spec:
template:
spec:
containers:
- name: pi
image: busybox
command: ["sh", "-c", "echo 'scale=10000; 4*a(1)' | bc -l "]
restartPolicy: Never
backoffLimit: 4
parallelism: 3
completions: 3
我们设置Job的最大并行数和最小完成数都是3,创建这个Job对象
[root@ycloud ycloud]# kubectl apply -f job-com.yaml
job.batch/pi-com created
[root@ycloud ycloud]# kubectl get po
NAME READY STATUS RESTARTS AGE
pi-com--1-2vs6z 1/1 Running 0 2m8s
pi-com--1-7jm69 1/1 Running 0 2m8s
pi-com--1-9mkq7 1/1 Running 0 2m8s
我们可以看到,三个任务同时运行。
综上所述:completions: 最后要成功运行多少个pod, parallelism: 每次只能启动多少个pod
使用拓展
模板拓展
把Job的yaml文件定义为一个模板,通过模板来生成Job
apiVersion: batch/v1
kind: Job
metadata:
name: process-item-$ITEM
labels:
jobgroup: jobexample
spec:
template:
metadata:
name: jobexample
labels:
jobgroup: jobexample
spec:
containers:
- name: c
image: busybox
command:
- sh
- '-c'
- echo Processing item $ITEM && sleep 5
restartPolicy: Never
可以看到,我们在这个 Job 的 YAML 里,定义了 $ITEM 这样的“变量”。
如果我们之间去运行这个job,会提示我们名称不符合规范标准。
[root@ycloud ~]# kubectl apply -f job.yaml
The Job "process-item-$ITEM" is invalid:
* metadata.name: Invalid value: "process-item-$ITEM": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')
所以在运行这种Job时,我们需要注意这两个方面:
- 创建 Job 时,需要对变量 $ITEM 传参
- 这个模板创建出的 Job ,都会带有 jobgroup: jobexample 的标签。
我们可以编写shell脚本,把 $ITEM 替换掉
#!/bin/bash
mkdir ./jobs
for i in aa bb cc
do
cat job.yaml | sed "s/\$ITEM/$i/" > ./jobs/job-$i.yaml
done
运行脚本之后,可以看到一组来自同一个模板的不同Job的yaml就生产了,
[root@ycloud ycloud]# ll jobs/
total 12
-rw-r--r-- 1 root root 400 Oct 7 13:54 job-aa.yaml
-rw-r--r-- 1 root root 400 Oct 7 13:54 job-bb.yaml
-rw-r--r-- 1 root root 400 Oct 7 13:54 job-cc.yaml
让我们创建这些Job
[root@ycloud ycloud]# kubectl apply -f jobs/
job.batch/process-item-aa created
job.batch/process-item-bb created
job.batch/process-item-cc created
最后我们查看下Pod的输出,目前kubelet logs只支持一个Pod的输出,我们这里通过一个循环来检查Pod的输出
[root@ycloud ycloud]# cat for.sh
#!/bin/bash
for p in $(kubectl get pods -l jobgroup=jobexample -o name)
do
kubectl logs $p
done
[root@ycloud ycloud]# bash for.sh
Processing item aa
Processing item bb
Processing item cc
CronJob
CronJob是Job对象的一个控制器, 该对象根据 Cron 格式定义的时间计划,周期性地创建 Job 对象。
CronJob 执行周期性的重复任务可以用来定时备份数据、发送邮件等
Cron时间表语法
并发规则
concurrencyPolicy 声明了 CronJob 创建的任务执行时发生重叠如何处理
- Allow,这也是默认情况,这意味着这些 Job 可以同时存在;
- Forbid,这意味着不会创建新的 Pod,该创建周期被跳过;
- Replace,这意味着新产生的 Job 会替换旧的、没有执行完的 Job。
CronJob示例
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *" #每 1 个时间单位执行一次
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
上面这个CronJob,从当前开始,每分钟会打印出时间和“Hello from the Kubernetes cluster”
[root@ycloud ycloud]# kubectl apply -f cronjob.yaml
cronjob.batch/hello created
[root@ycloud ycloud]# kubectl get jobs
NAME COMPLETIONS DURATION AGE
hello-27752081 0/1 48s 48s
CronJob 对象会对Job执行进行记录
[root@ycloud ycloud]# kubectl get cronjobs
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 2 21s 4m18s
LAST SCHEDULE
这个时间点成功创建了一个 Job。当前
ACTIVE
Job 数为 2,意味着,该 Job 已经成功结束.
[root@ycloud ycloud]# kubectl logs hello-27752082--1-kdnz2
Fri Oct 7 06:44:04 UTC 2022
Hello from the Kubernetes cluster
结论
我们了解了Job和CronJob的简单使用。从CronJob对像的yaml文件中,我们就可以了解到,Job和CronJob就跟Deployment和ReplicaSet一样,是被管理的关系