------> 课程视频同步分享在今日头条和B站
大家好,我是博哥爱运维,有时候我们想在K8s跑个一次性任务,或者是定时任务,能不能实现呢,答案肯定是可以的。
首先讲下一次性任务,在K8s中它叫job,直接来实战一番,先准备下yaml配置
这里我们不知道yaml怎么写,可以直接
kubectl create job -h
就能看到命令行创建示例了,然后可以根据创建出来的服务资源来导出它的yaml配置为my-job.yaml
apiVersion: batch/v1 # 1. batch/v1 是当前 Job 的 apiVersion
kind: Job # 2. 指明当前资源的类型为 Job
metadata:
name: my-job
spec:
template:
metadata:
spec:
containers:
- image: registry.cn-shanghai.aliyuncs.com/acs/busybox:v1.29.2
name: my-job
command: ["echo","Hello, boge."]
restartPolicy: Never # 3. restartPolicy 指定什么情况下需要重启容器。对于 Job,只能设置为 Never 或者 OnFailure
创建它并查看结果
# kubectl apply -f my-job.yaml
job.batch/my-job created
# kubectl get jobs.batch
NAME COMPLETIONS DURATION AGE
my-job 1/1 2s 73s
# COMPLETIONS 已完成的
# DURATION 这个job运行所花费的时间
# AGE 这个job资源已经从创建到目前为止的时间
# job会生成一个pod,当完成任务后会是Completed的状态
# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-job-7h6fb 0/1 Completed 0 31s
# 看下这个job生成的pod日志
# kubectl logs my-job-7h6fb
Hello, boge.
job失败了会有什么现象出现呢?
我们编辑这个job的yaml,把执行的命令改成一个不存在的命令看看会发生什么
apiVersion: batch/v1 # 1. batch/v1 是当前 Job 的 apiVersion
kind: Job # 2. 指明当前资源的类型为 Job
metadata:
name: my-job
spec:
template:
metadata:
spec:
containers:
- image: registry.cn-shanghai.aliyuncs.com/acs/busybox:v1.29.2
name: my-job
command: ["echoaaa","Hello, boge."]
restartPolicy: Never # 3. restartPolicy 指定什么情况下需要重启容器。对于 Job,只能设置为 Never 或者 OnFailure
创建它
# kubectl apply -f my-job.yaml
# 可以观察到这个job因为不成功,并且restartPolicy重启模式是Never不会被重启,但它的job状态始终未完成,所以它会一直不停的创建新的pod,直到COMPLETIONS为1/1,对于我们这个示例,它显然永远都不会成功
# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-job-9fcbm 0/1 StartError 0 47s
my-job-bt2kd 0/1 StartError 0 54s
my-job-mlnzz 0/1 StartError 0 37s
my-job-mntdp 0/1 StartError 0 17s
# kubectl get job
NAME COMPLETIONS DURATION AGE
my-job 0/1 15s 15s
# 找一个pod看下事件描述,会很清晰地指出命令不存在
# kubectl describe pod my-job-9fcbm
Name: my-job-9fcbm
Namespace: default
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 44s default-scheduler Successfully assigned default/my-job-9fcbm to 10.0.1.204
Normal Pulling 43s kubelet Pulling image "busybox"
Normal Pulled 36s kubelet Successfully pulled image "busybox" in 7.299038719s
Normal Created 36s kubelet Created container my-job
Warning Failed 36s kubelet Error: failed to create containerd task: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "echoaaa": executable file not found in $PATH: unknown
# 删除掉这个job,不然那创建的pod数量可有够多的了
# kubectl delete job my-job
# 试试把restartPolicy重启模式换成OnFailure观察看看
# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-job-gs95h 0/1 CrashLoopBackOff 3 84s
# 可以看到它不会创建新的pod,而是会尝试重启自身,以期望恢复正常,这里看到已经重启了3次,还会持续增加到5,然后会被K8s给删除以尝试,因为这里只是job而不是deployment,它不会自己再启动一个新的pod,所以这个job等于就没有了,这里说明OnFailure是生效的,至少不会有那么多错误的pod出现了
并行执行job
准备好yaml配置
apiVersion: batch/v1
kind: Job
metadata:
name: my-job
spec:
parallelism: 2 # 并行执行2个job
template:
metadata:
name: my-job
spec:
containers:
- image: registry.cn-shanghai.aliyuncs.com/acs/busybox:v1.29.2
name: my-job
command: ["echo","Hello, boge."]
restartPolicy: OnFailure
创建并查看结果
# kubectl apply -f my-job.yaml
job.batch/my-job created
# job一共启动了2个pod,并且它们的AGE一样,可见是并行创建的
# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-job-fwf8l 0/1 Completed 0 7s
my-job-w2fxd 0/1 Completed 0 7s
再来个组合测试下并行完成定制的总任务数量
apiVersion: batch/v1
kind: Job
metadata:
name: myjob
spec:
completions: 6 # 此job完成pod的总数量
parallelism: 2 # 每次并发跑2个job
template:
metadata:
name: myjob
spec:
containers:
- name: hello
image: registry.cn-shanghai.aliyuncs.com/acs/busybox:v1.29.2
command: ["echo"," hello boge! "]
restartPolicy: OnFailure
创建并查看结果
# 可以看到是每次并发2个job,完成6个总量即停止
# kubectl get pod
NAME READY STATUS RESTARTS AGE
myjob-54wmk 0/1 Completed 0 11s
myjob-fgtmj 0/1 Completed 0 15s
myjob-fkj5l 0/1 Completed 0 7s
myjob-hsccm 0/1 Completed 0 7s
myjob-lrpsr 0/1 Completed 0 15s
myjob-ppfns 0/1 Completed 0 11s
# 符合预期
# kubectl get job
NAME COMPLETIONS DURATION AGE
myjob 6/6 14s 34s
# 测试完成后删掉这个资源
kubectl delete job myjob
到此,job的内容就讲完了,在生产中,job比较适合用在CI/CD流水线中,作完一次性任务使用,我在生产中基本没怎么用这个资源。
上面的job是一次性任务,那我们需要定时循环来执行一个任务可以嘛?答案肯定是可以的,就像我们在linux系统上面用crontab一样,在K8s上用cronjob的另一个好处就是它是分布式的,执行的pod可以是在集群中的任意一台NODE上面(这点和cronsun有点类似)
让我们开始实战吧,先准备一下cronjob的yaml配置为my-cronjob.yaml
apiVersion: batch/v1beta1 # <--------- 当前 CronJob 的 apiVersion
kind: CronJob # <--------- 当前资源的类型
metadata:
name: hello
spec:
schedule: "* * * * *" # <--------- schedule 指定什么时候运行 Job,其格式与 Linux crontab 一致,这里 * * * * * 的含义是每一分钟启动一次
jobTemplate: # <--------- 定义 Job 的模板,格式与前面 Job 一致
spec:
template:
spec:
containers:
- name: hello
image: registry.cn-shanghai.aliyuncs.com/acs/busybox:v1.29.2
command: ["echo","boge like cronjob."]
restartPolicy: OnFailure
正常创建后,我们过几分钟来看看运行结果
# 这里会显示cronjob的综合信息
# kubectl get cronjobs.batch
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello * * * * * False 0 66s 2m20s
# 可以看到它每隔一分钟就会创建一个pod来执行job任务
# kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-1610267460-9b6hp 0/1 Completed 0 2m5s
hello-1610267520-fm427 0/1 Completed 0 65s
hello-1610267580-v8g4h 0/1 ContainerCreating 0 5s
# 测试完成后删掉这个资源
# kubectl delete cronjobs.batch hello
cronjob.batch "hello" deleted
cronjob定时任务在生产中的用处很多,这也是为什么上面job我说用得很少的缘故,我们可以把一些需要定时定期运行的任务,在K8s上以cronjob运行,依托K8s强大的资源调度以及服务自愈能力,我们可以放心的把定时任务交给它执行。