高级调度-CronJob:定时任务的应用
- [1. 简介](#1. 简介)
- [2. Linux 上的 CronJob 定时任务](#2. Linux 上的 CronJob 定时任务)
- [3. 创建 K8s 的 CronJob](#3. 创建 K8s 的 CronJob)
- [4. 删除 k8s 的 CronJob](#4. 删除 k8s 的 CronJob)
1. 简介
在 Kubernetes 中,CronJob 是一种用于创建定时任务的资源对象。它允许我们在集群中预定和运行定期的作业,类似于 Linux 系统中的 cron 任务。
使用 CronJob 资源可以很容易地在 Kubernetes 上创建定时任务,无需依赖外部工具或服务。以下是 CronJob 的一些主要特点和应用:
-
定时调度
:CronJob 允许您基于 Cron 表达式来定义任务的调度规则,比如每天凌晨执行、每个星期五执行等。 -
作业管理
:CronJob 创建的任务会生成对应的 Job 资源,并在指定的时间执行任务。如果任务成功完成,则 Job 会被标记为完成;如果任务失败,则 Job 会保留失败的状态,并且根据配置的重试策略进行重试。 -
并行处理
:CronJob 允许您配置并发性,即同时执行的任务数量。这可以帮助您控制资源的使用情况,避免过多的任务同时运行导致资源耗尽。 -
灵活的配置
:CronJob 支持很多配置选项,例如定义任务的容器镜像、环境变量、命令参数等,使得定时任务的执行更加灵活。
2. Linux 上的 CronJob 定时任务
在 Linux 上,CronJob
是一种用于定时执行任务的工具,它可以让您在指定的时间间隔内运行命令或脚本。
Cron 表达式:
bash
# ┌───────────── 分钟 (0 - 59)
# │ ┌───────────── 小时 (0 - 23)
# │ │ ┌───────────── 月的某天 (1 - 31)
# │ │ │ ┌───────────── 月份 (1 - 12)
# │ │ │ │ ┌───────────── 周的某天 (0 - 6)(周日到周一;在某些系统上,7 也是星期日)
# │ │ │ │ │ 或者是 sun,mon,tue,web,thu,fri,sat
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
下面是在 Linux 上使用 CronJob 的一般步骤:
编辑 Cron 表
:打开终端,并使用以下命令编辑 Cron 表。
bash
crontab -e
如果是第一次编辑 Cron 表,系统会提示您选择默认的编辑器。
添加定时任务
:在 Cron 表中,每行表示一个定时任务。每行包含六个字段,分别表示分钟、小时、日期、月份、星期和要执行的命令。您可以根据需要调整这些参数。
例如,要在每天的凌晨 2 点运行 /path/to/command 命令,可以在 Cron 表中添加以下内容:
bash
0 2 * * * /path/to/command
这表示每天的第 0 分钟、第 2 小时(凌晨 2 点)执行 /path/to/command 命令。
-
保存 Cron 表
:完成编辑后,请保存并关闭 Cron 表。编辑器会自动将新的 Cron 表写入系统。 -
验证 Cron 任务
:可以使用以下命令查看当前用户的 Cron 表内容。
bash
crontab -l
这将显示当前用户的所有定时任务。
管理 Cron 任务
:通过编辑 Cron 表,您可以添加、修改或删除定时任务。当您需要对定时任务进行更改时,请使用 crontab -e 命令再次编辑 Cron 表。
另外,还有一些其他的 CronJob 使用技巧:
可以使用 *
通配符表示任意值,例如 * * * * *
表示每分钟都运行。
您可以使用逗号分隔的值来指定多个值,例如 0,15,30,45 * * * *
表示每小时的第 0、15、30 和 45 分钟运行。
可以使用连字符指定一个范围,例如 0 9-17 * * 1-5
表示在周一至周五的上午 9 点到下午 5 点之间的每个整点运行。
请注意,CronJob 的精度是分钟级别的,并且会受到系统时间的影响。因此,确保系统时间准确无误。
看了下我这里的定时任务:
bash
[root@docker-54 config]# crontab -l
0-59/10 * * * * /usr/sbin/ntpdate us.pool.ntp.org | logger -t NTP
[root@docker-54 config]#
这个定时任务的含义是每隔10分钟执行一次 /usr/sbin/ntpdate us.pool.ntp.org
命令,并将命令的输出通过管道传递给 logger -t NTP
。
让我来解释一下每个部分的含义:
-
0-59/10
:这表示分钟字段,表示每隔10分钟执行一次任务。范围是从0到59,斜杠后面的数字表示步长,也就是间隔。因此,0-59/10 表示每隔10分钟执行一次任务。 -
*
:这是通配符,表示"每"。 -
*
:这是通配符,表示不限制。 -
*
:这是通配符,表示不限制。 -
/usr/sbin/ntpdate us.pool.ntp.org
:这是要执行的命令,它会使用 NTP 协议从 us.pool.ntp.org 获取时间并进行同步。 -
|
:这是管道符号,用于将命令的输出传递给下一个命令。 -
logger -t NTP
:这是将命令的输出通过 logger 工具记录到系统日志中,标记为 NTP。
因此,这个定时任务的含义是每隔10分钟使用 NTP 协议从 us.pool.ntp.org
获取时间并进行同步,同时将命令的输出记录到系统日志中,以便日后查看或跟踪时间同步的情况。
3. 创建 K8s 的 CronJob
新建配置文件:cron-job-pd.yaml
bash
apiVersion: batch/v1
kind: CronJob # 定时任务
metadata:
name: cron-job-test # 定时任务名字
spec:
concurrencyPolicy: Allow # 并发调度策略:Allow 允许并发调度,Forbid:不允许并发执行,Replace:如果之前的任务还没执行完,就直接执行新的,放弃上一个任务
failedJobsHistoryLimit: 1 # 保留多少个失败的任务
successfulJobsHistoryLimit: 3 # 保留多少个成功的任务
suspend: false # 是否挂起任务,若为 true 则该任务不会执行
# startingDeadlineSeconds: 30 # 间隔多长时间检测失败的任务并重新执行,时间不能小于 10
schedule: "* * * * *" # 调度策略
jobTemplate:
spec:
template:
spec:
containers:
- name: busybox
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
这里使用 busybox
镜像创建一个容器,每分钟执行一次 date; echo Hello from the Kubernetes cluster
的命令。
bash
[root@docker-54 jobs]# kubectl apply -f cron-job-pd.yaml
cronjob.batch/cron-job-test created
[root@docker-54 jobs]#
[root@docker-54 jobs]# kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cron-job-test * * * * * False 0 <none> 5s
[root@docker-54 jobs]#
[root@docker-54 jobs]# kubectl get cj
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cron-job-test * * * * * False 0 <none> 36s
[root@docker-54 jobs]#
这里显示LAST SCHEDULE
为 none 表示最后一次调度记录不存在,证明还没有执行过。
bash
[root@docker-54 jobs]# kubectl describe cj cron-job-test
Name: cron-job-test
Namespace: default
Labels: <none>
Annotations: <none>
Schedule: * * * * *
Concurrency Policy: Allow
Suspend: False
Successful Job History Limit: 3
Failed Job History Limit: 1
Starting Deadline Seconds: <unset>
Selector: <unset>
Parallelism: <unset>
Completions: <unset>
Pod Template:
Labels: <none>
Containers:
busybox:
Image: busybox:1.28
Port: <none>
Host Port: <none>
Command:
/bin/sh
-c
date; echo Hello from the Kubernetes cluster
Environment: <none>
Mounts: <none>
Volumes: <none>
Last Schedule Time: Sun, 26 Nov 2023 22:35:00 +0800
Active Jobs: cron-job-test-28350155
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 57s cronjob-controller Created job cron-job-test-28350155
[root@docker-54 jobs]#
可以下这个任务的具体信息。
接着再看下状态:
bash
[root@docker-54 jobs]# kubectl get cj
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cron-job-test * * * * * False 0 32s 3m30s
[root@docker-54 jobs]#
可以看到已经距离上次调度已经过了 32s
了。
另外看下执行记录:
bash
[root@docker-54 jobs]# kubectl get po | grep cron
cron-job-test-28350156--1-xn5xf 0/1 Completed 0 2m46s
cron-job-test-28350157--1-9mfwx 0/1 Completed 0 106s
cron-job-test-28350158--1-75v5k 0/1 Completed 0 46s
[root@docker-54 jobs]#
[root@docker-54 jobs]# kubectl logs -f cron-job-test-28350158--1-75v5k
Sun Nov 26 14:38:01 UTC 2023
Hello from the Kubernetes cluster
[root@docker-54 jobs]#
可以看到这些执行任务,并且是执行成功的状态。
在我们实际是用的过程中,也是这样,只是把我们的脚本改成自定义的实现就好了。
4. 删除 k8s 的 CronJob
接着我们来删除这个 CronJob:
bash
[root@docker-54 jobs]# kubectl get cj
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cron-job-test * * * * * False 0 11s 7m9s
[root@docker-54 jobs]#
[root@docker-54 jobs]# kubectl delete cj cron-job-test
cronjob.batch "cron-job-test" deleted
[root@docker-54 jobs]#
[root@docker-54 jobs]# kubectl get cj
No resources found in default namespace.
[root@docker-54 jobs]#
[root@docker-54 jobs]# kubectl get po | grep cron
[root@docker-54 jobs]#
可以看到,在我删除了CronJob 之后,对应的 Pod 记录也随之删除了。