从零开始学习k8s-12定时任务
背景
分布式系统中,会有很多定时任务的需求。例如定时备份,定时发邮件等等。
在传统的定时任务方式中,我们主要是用linux
自带的crontab
来实现定时任务的功能,但是这种实现会有一定的局限性,例如不容易管理,不容易迁移,出问题不方便排查等。
k8s
自带的cronjob
可以更方便的执行定时任务的调度。
需要注意的是,batch
接口是在1.2.1
版本中才支持的,本文使用的是1.2.2
版本,如果版本较低,可以参考官方文档使用对应的方案。
开始CronJob
同样参考官方文档,使用的yaml
文件是
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
可以看到,我们这里定义了一个schedule
,这个表达式跟linux
的crontab
表达式格式一致。这个yaml
使用的是每一分钟执行一次调度,每次输出一个hello
的信息。我们创建来看看。
kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 0 <none> 7s
2
3
可以看到,刚创建完毕的是没有被调度的。当我们过了一段时间之后再执行同样的命令查看。
kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 0 22s 2m34s
2
3
可以看到状态依然是False
,ACTIVE
依然是0
,但是LAST SCHEDULE
可以看到已经有数字了,这个字段代表着上一次调度的时间。我们可以查看当前的job
kubectl get jobs
NAME COMPLETIONS DURATION AGE
hello-27278062 1/1 1s 2m16s
hello-27278063 1/1 1s 76s
hello-27278064 1/1 2s 16s
2
3
4
5
可以看到,已经有任务被调度了,并且都已经完成调度了。
我们可以通过命令查看执行的日志
pods=$(kubectl get pods --selector=job-name=hello-27278064 --output=jsonpath={.items..metadata.name})
kubectl logs $pods
>>
Fri Nov 12 02:26:33 UTC 2021
Hello from the Kubernetes cluster
2
3
4
5
6
7
可以看到,我们定时调度打印的信息可以在日志中看到。
注意点
如果用定时任务调度接口,官方建议接口必须是幂等的。因为可能由于特殊原因,会出现同时创建两个job
,或者不创建任何job
的情况。
CronJob
也是会占用资源的,调度的时候也会按照一定的资源配比进行分配,如果资源不足则会调度失败。
相比于直接使用crontab
来触发定时任务,CronJob
能够更直观的观察和管理定时任务,但是相比于成熟的定时任务系统,还是有差距。
参考资料
https://kubernetes.io/zh/docs/concepts/workloads/controllers/cron-jobs/
https://kubernetes.io/zh/docs/tasks/job/automated-tasks-with-cron-jobs/