文章目录
- 实验环境
- 一、job、cronjob介绍
- 二、创建job
-
- a.命令行方式
- b.yaml文件方式
- job中pod的重启策略
- job其他一些参数
- 三、创建cronjob
-
- a.命令行方式
- b.yaml文件方式
- 指定实施成功后,最多保留pod数
- 限制执行任务的时间
- 四、通过cronjob中的模板来创建job
实验环境
初始初始集群环境: (vms21)192.168.26.21——master1 (vms22)192.168.26.22——worker1 (vms23)192.168.26.23——worker2
一、job、cronjob介绍
deployment控制器可以确保环境中的一定数量pod如果某个副本pod挂断后,控制器将重新创建此pod,对于deployment控制的这些pod,一般操作是守护过程(daemon) 但有时候,我们不需要一个过程一直运行,比如测试、数学操作等。有些过程只需要临时操作,操作结束。在这种情况下,它们不适合使用deployment了 所以这里介绍另外两种控制器,job与cronjob
1.job与cronjob都是控制器(创建pod、管理pod) 2.job与cronjob创建的pod,都是为了完成一次性任务,过程完成后就结束了,不会一直运行,但创建了pod不会自动删除,状态会变成Completed 如:
NAME READY STATUS RESTARTS AGE xxpod 0/1 Completed 0 13s
3.但是job与cronjob不同之处在于,cronjob中包括了job定期创建模板job,而job是一次性的,比如job设定一个时间来执行和创建一个时间pod,执行结束,而cronjob根据定时器的设置,例如每个星期天晚上创建一个job
二、创建job
a.命令行方式
执行命令必须定义为 “--” 后 kubectl create job [job名] --image=[镜像名] -- [命令是容器启动后运行的主要过程]
b.yaml文件方式
使用命令行输出yaml模板
执行命令必须定义为 “--” 后,--dry-run需写在 “--” 前 #执行命令也可以先不定义,等待生成yaml后,可在yaml中定义容器command kubectl create job [job名] --image=[镜像名] --dry-run=client -o yaml -- [命令是容器启动后运行的主要过程] > [文件名.yaml]
例:创建一个job,名为myjob1,使用busybox镜像 (1)可以提前拉取镜像
nerdctl pull busybox
(2)输出yaml文件
kubectl create job myjob1 --image=busybox --dry-run=client -o yaml -- date > myjob1.yaml #或先不定义命令 kubectl create job myjob1 --image=busybox --dry-run=client -o yaml > myjob1.yaml
这里我们先不定义命令,等生成了yaml后,在yaml定义容器的主过程command 输出的yaml文件如下:
apiVersion: batch/v1 kind: Job metadata: creationTimestamp: null name: myjob1 spec: template: metadata: creationTimestamp: null spec: containers: - image: busybox name: myjob1 resources: {
} restartPolicy: Never status: {
}
(3)修改yaml文件 和其它控制器一样,template下定义pod的模板 我们将pod宽限期为0,执行过程为date,然后休眠10秒,然后结束 修改后yaml如下:
apiVersion: batch/v1 kind: Job metadata: creationTimestamp: null name: myjob1 spec: template: metadata: creationTimestamp: null spec: terminationGracePeriodSeconds: 0 containers: - image: busybox imagePullPolicy: IfNotPresent command: ["sh","-c","date ; sleep 10"] name: myjob1 resources:
}
restartPolicy: Never
status: {
}
(4)创建job
kubectl apply -f myjob1.yaml
(5)查看job
kubectl get jobs
#输出:
NAME COMPLETIONS DURATION AGE
myjob1 0/1 6s 6s
可以看到COMPLETIONS为0/1,意思是job中创建的pod要执行的命令至少要成功执行1次才算成功(即容器中的主进程command),当前为0,任务还没有执行完 在大概9s时,查看pods,可以看到pod还在Running
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
myjob1-tnk76 1/1 Running 0 9s
等过了10s(因为命令中定义的是执行完date后,休眠10s后,结束),可以看到pod里的进程一次执行完了 此时的READY为0/1,STATUS为Completed
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
myjob1-tnk76 0/1 Completed 0 13s
此时查看job,COMPLETIONS为1/1
kubectl get jobs
#输出:
NAME COMPLETIONS DURATION AGE
myjob1 1/1 13s 14s
(6)那么,假如我们定义的容器的主进程的命令执行失败会怎么样呢? 现在,我们删除这个job,pod也会随之删除,然后将容器内的command定义为一个注定要执行失败的命令,如: 将sleep关键字写错
...
containers:
- image: busybox
imagePullPolicy: IfNotPresent
command: ["sh","-c","date ; slee 10"]
name: myjob1
...
然后重新创建这个pod
kubectl apply -f myjob1.yaml
查看job、查看pod
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
myjob1-5g7ql 0/1 Error 0 14s
myjob1-bjn9g 0/1 ContainerCreating 0 1s
myjob1-jj7pq 0/1 Error 0 7s
myjob1-mgvjt 0/1 Error 0 21s
myjob1-mpdwb 0/1 Error 0 17s
myjob1-v87x5 0/1 Error 0 4s
myjob1-zfm84 0/1 Error 0 10s
kubectl get jobs
#输出:
NAME COMPLETIONS DURATION AGE
myjob1 0/1 50s 50s
可以看到没有完成任务,job会不停的去重新创建pod来完成任务 为什么这里会不停地去创建pod呢?——这就和pod的重启策略有关
job中pod的重启策略
根据上一个例子中,pod内的命令执行失败,即任务没有执行完成,job会一直新建pod去完成任务,这是因为定义pod的重启策略为Never
job中的pod的重启策略只有两种: Never:只要任务没有完成,则会新创建pod运行,直到job完成——会产生多个pod OnFailure:只要任务没有完成,则会重启opd,直到job完成
job中的pod没有Always这种重启策略,因为是一次性任务,若执行成功了,就结束了
上一个例子中,只需将重启策略restartPolicy改为OnFailure,就不会因为任务失败而一直创建新的pod
...
spec:
containers:
- image: busybox
name: myjob1
resources: {
}
restartPolicy: OnFailure
...
job中一些其他参数
有时候,我们认为任务一次成功执行之后,可能有偶然性的因素,因此我们想确保任务不是偶然成功的,有以下一些相关参数: parallelism——定义job中一次性运行(创建)几个pod(这个值不会超过completions的值) completions——job任务结束需要成功运行的pod个数,即状态为Completed的pod数 backoffLimit——若job失败,重试的次数
实验: (1)如下:completions设为6,parallelism设为2,即需要创建6个pod、共6次成功执行命令,每次执行2次,即每次创建2个pod,那么需要3次
apiVersion: batch/v1
kind: Job
metadata:
creationTimestamp: null
name: myjob1
spec:
completions: 6
parallelism: 2
template:
metadata:
creationTimestamp: null
spec:
terminationGracePeriodSeconds: 0
containers:
- image: busybox
imagePullPolicy: IfNotPresent
command: ["sh","-c","date ; sleep 10"]
name: myjob1
resources: {
}
restartPolicy: Never
status: {
}
(2)删除上一个实验的job,创建这个job 创建后,查看pod,可以看到第一次先创建了2个pod来执行任务
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
myjob1-n7hb8 1/1 Running 0 5s
myjob1-wnb7g 1/1 Running 0 5s
等这两个pod成功执行完任务后,会创建第二对pod来执行
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
myjob1-lmw5w 1/1 Running 0 3s
myjob1-m9qzb 1/1 Running 0 4s
myjob1-n7hb8 0/1 Completed 0 17s
myjob1-wnb7g 0/1 Completed 0 17s
最后,会创建第三对pod
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
myjob1-xs5fk 1/1 Running 0 4s
myjob1-b2qqj 1/1 Running 0 6s
myjob1-lmw5w 0/1 Completed 0 18s
myjob1-m9qzb 0/1 Completed 0 19s
myjob1-n7hb8 0/1 Completed 0 32s
myjob1-wnb7g 0/1 Completed 0 32s
成功执行了6次之后,任务才算完成
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
myjob1-xs5fk 0/1 Completed 0 14s
myjob1-b2qqj 0/1 Completed 0 16s
myjob1-lmw5w 0/1 Completed 0 28s
myjob1-m9qzb 0/1 Completed 0 29s
myjob1-n7hb8 0/1 Completed 0 42s
myjob1-wnb7g 0/1 Completed 0 42s
kubectl get jobs
#输出:
NAME COMPLETIONS DURATION AGE
myjob1 6/6 41s 47s
假设若任务执行失败,难道就一直重启(重启策略为OnFailure时)或者一直新建pod(重启策略为Never时)下去吗 可以使用backoffLimit设置失败后重试次数
三、创建cronjob
实验:创建一个job名为pi,任务为 “使用perl来计算圆周率后面500位” (1)拉取镜像perl
nerdctl pull perl
(2)创建pi.yaml,如下:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
terminationGracePeriodSeconds: 0
containers:
- image: docker.io/library/perl:latest
imagePullPolicy: IfNotPresent
command: ["perl","-Mbignum=bpi","-wle","print bpi(500)"]
name: pi
restartPolicy: Never
(3)创建job
kubectl apply -f pi.yaml
(4)执行完毕后,查看输出
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
pi-9vqmm 0/1 Completed 0 4s
kubectl get jobs
#输出:
NAME COMPLETIONS DURATION AGE
pi 1/1 3s 27s
kubectl logs pi-9vqmm
#输出:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491
以上这个例子中,job执行完了也就结束了,但有时候,我们并不想只执行一次,比如想定期去清理一些缓存、定期去删除一些僵尸容器等,我们就可以使用cronjob来实现 查看没有在正常运行的容器
nerdctl ps -a | grep -i ex
cronjob里面定义了一个job模板,而job里面又定义了pod模板… 创建cronjob
a.命令行方式
#执行的命令必须定义在 “--” 后
#schedule:调度,定义多长时间执行一次,格式:分 时 天 月 周,若我们不考虑某个时间单位,那这个时间单位就用*表示
kubectl create cronjob [cronjob名] --image=[镜像名] --schedule="*/1 * * * *" -- [命令,即容器启动后运行的主进程]
schedule——定义调度的时间 格式:分 时 天 月 周,若我们不考虑某个时间单位,那这个时间单位就用*表示 如:
#7点的每一分钟都会执行
* 7 * * *
#每天的7点整都会执行
0 7 * * *
#每周的周一到周五的7点整都执行
0 7 * * 1-5
#1-5的完整写法其实1-5/1,表示起始点为1,步长为1,从1(星期1)、1+1=2(星期2)、2+1=3(星期三)...一直加到5
#每周的周一、周三、周五的5点整执行
#第一种写法:
0 5 * * 1-5/2 #1(星期1)、1+2=3(星期三)、3+2=5(星期五)
#第二种写法:
0 5 * * 1,3,5
#24小时每1分钟都去执行
* * * * *
#或(完整写法,步长为1)
*/1 * * * *
b.yaml文件方式
利用命令行方式输出yaml模板
#执行的命令必须定义在 “--” 后,--dry-run需写在 “--” 前
#执行的命令也可以先不定义,等生成了yaml后,可在yaml中定义容器的command
kubectl create cronjob [cronjob名] --image=[镜像名] --schedule="*/1 * * * *" --dry-run=client -o yaml -- [命令,即容器启动后运行的主进程] > [文件名.yaml]
例: 我们先不指定命令,使用busybox镜像,输出mycj.yaml
kubectl create cronjob mycj1 --image=busybox --schedule="*/1 * * * *" --dry-run=client -o yaml > mycj.yaml
生成的yaml文件如下:
apiVersion: batch/v1
kind: CronJob
metadata:
creationTimestamp: null
name: mycj1
spec:
jobTemplate:
metadata:
creationTimestamp: null
name: mycj1
spec:
template:
metadata:
creationTimestamp: null
spec:
containers:
- image: busybox
name: mycj1
resources: {
}
restartPolicy: OnFailure
schedule: '*/1 * * * *'
status: {
}
如yaml文件所示,spec.jobTemplate定义的是job的模板,根据schedule定义的时间,每到了指定的时间就去创建一个job jobTemplate下又包括了pod的模板template
实验: (1)修改mycj1.yaml,将pod的宽限期设为0,镜像拉取策略为IfNotPresent 指定执行的任务为执行date,然后休眠15秒
apiVersion: batch/v1
kind: CronJob
metadata:
creationTimestamp: null
name: mycj1
spec:
jobTemplate:
metadata:
creationTimestamp: null
name: mycj1
spec:
template:
metadata:
creationTimestamp: null
spec:
terminationGracePeriodSeconds: 0
containers:
- image: busybox
command: ["sh","-c","date ; sleep 15"]
name: mycj1
imagePullPolicy: IfNotPresent
resources: {
}
restartPolicy: OnFailure
schedule: '*/1 * * * *'
status: {
}
(2)创建这个cronjob
kubectl apply -f mycj1.yaml
(3)查看job、查看pod,可以看到每到系统时间的下一分钟的开始,就会自动创建一个job,job去创建一个pod执行任务
kubectl get jobs
#输出:
NAME COMPLETIONS DURATION AGE
mycj1-27625612 0/1 2s 2s
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
mycj1-27625612-xth79 1/1 Running 0 4s
#------------------------------------------------------
kubectl get jobs
#输出:
NAME COMPLETIONS DURATION AGE
mycj1-27625612 1/1 18s 31s
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
mycj1-27625612-xth79 0/1 Completed 0 33s
#------------------------------------------------------
kubectl get jobs
#输出:
NAME COMPLETIONS DURATION AGE
mycj1-27625612 1/1 18s 65s
mycj1-27625613 0/1 5s 5s
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
mycj1-27625612-xth79 0/1 Completed 0 66s
mycj1-27625613-m7qds 1/1 Running 0 6s
又过了一会,可以看到有4个运行完的pod的了,那么照此推理,一个小时会有60个pod,一天24小时就会有1440个pod
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
mycj1-27625617-g4gmv 0/1 Completed 0 3m18s
mycj1-27625618-jjrnr 0/1 Completed 0 2m18s
mycj1-27625619-msbc9 0/1 Completed 0 78s
mycj1-27625620-5ph62 0/1 Completed 0 18s
但事实是如此吗?过了一会后,我们再查看一下pod
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
mycj1-27625619-msbc9 0/1 Completed 0 2m35s
mycj1-27625620-5ph62 0/1 Completed 0 95s
mycj1-27625621-2v58s 0/1 Completed 0 35s
可以看到它只给我们保留了3个pod,已经将一个pod删除了,这是因为它默认只给我们保留3个pod
指定成功执行后,最多保留的pod数
我们也可以自己指定保留几个pod 在spec下可以用successfulJobsHistoryLimit定义,表示成功执行后、运行完毕后,最多保留几个pod,默认值是3 结合上个例子中的yaml文件,来进行实验 实验: (1)删除刚刚创建的cronjob,修改yaml文件,定义成功运行后,最多保留5个pod
kubectl delete cj mycj1
修改处如下:
...
apiVersion: batch/v1
kind: CronJob
metadata:
creationTimestamp: null
name: mycj1
spec:
successfulJobsHistoryLimit: 5
jobTemplate:
...
(2)创建这个cronjob,过一会后,查看pod,可以看到最多只给我们保留了5个pod
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
mycj1-27625633-4p9jh 0/1 Completed 0 5m5s
mycj1-27625634-t58lh 0/1 Completed 0 4m5s
mycj1-27625635-4tqvp 0/1 Completed 0 3m5s
mycj1-27625636-p2lpz 0/1 Completed 0 2m5s
mycj1-27625637-922xh 0/1 Completed 0 65s
mycj1-27625638-dcnmj 1/1 Running 0 5s
kubectl get jobs
#输出:
NAME COMPLETIONS DURATION AGE
mycj1-27625633 1/1 20s 5m14s
mycj1-27625634 1/1 18s 4m14s
mycj1-27625635 1/1 18s 3m14s
mycj1-27625636 1/1 17s 2m14s
mycj1-27625637 1/1 18s 74s
mycj1-27625638 0/1 14s 14s
#---------------------------------------------------------------
kubectl get pods
#输出:
NAME READY STATUS RESTARTS AGE
mycj1-27625635-4tqvp 0/1 Completed 0 4m25s
mycj1-27625636-p2lpz 0/1 Completed 0 3m25s
mycj1-27625637-922xh 0/1 Completed 0 2m25s
mycj1-27625638-dcnmj 0/1 Completed 0 85s
mycj1-27625639-g74b7 0/1 Completed 0 25s
kubectl get jobs
#输出:
NAME COMPLETIONS DURATION AGE
mycj1-27625635 1/1 18s 4m29s
mycj1-27625636 1/1 17s 3m29s
mycj1-27625637 1/1 18s 2m29s
mycj1-27625638 1/1 18s 89s
mycj1-27625639 1/1 18s 29s
限定任务的执行时间
以上的例子中,我们指定了容器的主进程执行date然后休眠15s,因此我们知道pod的运行时间大概为15s,但在实际情况中,一个进程的运行时间是未知的,可能是5s,也可能30s,但是假设我们估计某个程序它的运行时间不应该超过10s,若超过了10s,则我们认为是异常了,因此,我们可以限定这个pod它最多能运行多长时间
在job模板中定义pod限定的运行时间,pod若超过这个时间还没执行完,这个pod就会被强制杀死 实验: (1)删除上一个实验的cronjob
kubectl delete cj mycj1
(2)继续修改上一个实验的yaml,指定限定的运行时间为10s 修改后yaml如下:
apiVersion: batch/v1
kind: CronJob
metadata:
creationTimestamp: null
name: mycj1
spec:
successfulJobsHistoryLimit: 5
jobTemplate:
metadata:
creationTimestamp: null
name: mycj1
spec:
activeDeadlineSeconds: 10
template:
metadata:
creationTimestamp: null
spec:
terminationGracePeriodSeconds: 0
containers:
- image: busybox
command: ["sh","-c","date ; sleep 15"]
name: mycj1
imagePullPolicy: IfNotPresent
resources: {
}
restartPolicy: OnFailure
schedule: '*/1 * * * *'
status: {
}
(3)创建这个cronjob,然后我们每隔0.5s,让它自动执行kubectl get pods
,来观察结果
kubectl apply -f mycj1.yaml
watch -n .5 'kubectl get pods'
可以观察到,待pod创建后,运行10s后,该pod就被自动删除了
四、通过cronjob中的模板来创建job
#根据cronjob中定义的模板来创建job
#cronjob缩写为cj
kubectl create job [job名] --from cj/[cronjob名]