1 CronJob定时任务控制器简介

CronJob是指在Kubernetes集群里按照类Unix cron语法周期性地创建Job,适合定时备份、统计、清理、巡检等到点就跑一次的任务。

2 CronJob的特点

特性 说明
调度语法 与Linux crontab 相同:分 时 日 月 周(0-59 0-23 1-31 1-12 0-6)
并发策略 concurrencyPolicy: Allow/Forbid/Replace决定是否允许多个Job同时跑
历史限制 successfulJobsHistoryLimit/failedJobsHistoryLimit控制保留已结束Job的数量,防止etcd膨胀
时区支持 集群可设.spec.timeZone: “Asia/Shanghai”(需开启特性,1.24+版本支持)
一次性或索引 底层仍是Job,可跑单个Pod也可跑并行索引作业

3 CronJob常用场景

场景 举例
定时备份 数据库、ETCD、GitLab 仓库快照
日志/数据清理 删除7天前日志、压缩旧数据
统计报表 每日凌晨生成销售日报、资源使用率报告
证书续期 每天03:00检查并更新Encrypt证书
镜像/缓存刷新 周期性重新拉取最新基础镜像
健康巡检 每10分钟扫描一次集群安全策略

4 CronJob与Job的区别

维度 Job CronJob
触发方式 手动/一次性 定时自动
对象类型 batch/v1 Job batch/v1 CronJob
历史记录 手动删除 自动保留可配置份数
并发控制 有concurrencyPolicy

5 一个典型的CronJob控制器资源清单文件

下面是一份生产中常用的定时备份资源清单。
这份CronJob资源清单的功能是:
每天02:30(上海时区)触发一次,生成Job、启动Pod、mysqldump全库压缩及上传MinIO分布式对象存储系统,并发被禁止、历史记录保留3份、失败重试3次、全程不超过1小时。

apiVersion: batch/v1                 # 1. API版本:batch/v1为CronJob稳定版本
kind: CronJob                        # 2. 资源类型:CronJob(定时任务)
metadata:
  name: mysql-backup                 # 3. 对象名称,集群内唯一
  namespace: default                 # 4. 所属命名空间,可省略(默认 default)
spec:
  schedule: "30 2 * * *"             # 5. crontab语法:每天02:30触发
  concurrencyPolicy: Forbid          # 6. 并发策略:上一次未跑完则跳过新一次
  successfulJobsHistoryLimit: 3      # 7. 保留成功Job历史数(0=不保留)
  failedJobsHistoryLimit: 3          # 8. 保留失败Job历史数
  timeZone: "Asia/Shanghai"          # 9. 1.24+集群支持:使用上海时区
  startingDeadlineSeconds: 200       # 10. 调度窗口:02:30后200s内必须启动,否则标为Failed
  jobTemplate:                       # 11. Job模板:每次调度生成一个Job对象
    spec:
      backoffLimit: 3                # 12. Job级别重试次数(Pod失败3次即放弃)
      activeDeadlineSeconds: 3600    # 13. Job全局超时1h,到点强制删除仍在运行的Pod
      template:                      # 14. Pod模板
        spec:
          restartPolicy: OnFailure   # 15. 容器异常退出才重启;成功即Completed
          containers:
          - name: mysqldump          # 16. 主容器:执行备份命令
            image: mysql:8.0-debian  # 17. 自带mysqldump客户端
            env:
            - name: MYSQL_PWD        # 18. 通过环境变量注入密码,避免命令行泄漏
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: password
            command: ["/bin/bash", "-c"]
            args:                    # 19. 备份、压缩、上传到MinIO分布式对象存储系统
            - |
              set -e
              DATE=$(date +%F-%H-%M)
              mysqldump -h mysql -u root --all-databases --single-transaction --quick --lock-tables=false \
                | gzip > /tmp/all-${DATE}.sql.gz
              mc alias set minio http://minio:9000 ${MINIO_ACCESS_KEY} ${MINIO_SECRET_KEY}
              mc cp /tmp/all-${DATE}.sql.gz minio/backups/mysql/
              echo "Backup ${DATE} uploaded"
            env:
            - name: MINIO_ACCESS_KEY
              valueFrom: {secretKeyRef: {name: minio-secret, key: accesskey}}
            - name: MINIO_SECRET_KEY
              valueFrom: {secretKeyRef: {name: minio-secret, key: secretkey}}
            volumeMounts:            # 20. 临时目录,避免容器层满
            - name: tmp
              mountPath: /tmp
          volumes:
          - name: tmp                # 21. emptyDir卷,Pod删除即清理
            emptyDir: {}

上述yaml的重要字段及作用:

字段 作用
schedule 标准5位crontab,双引号必填
concurrencyPolicy Allow(默认)/Forbid/Replace
startingDeadlineSeconds 错过调度窗口后不再补跑
successfulJobsHistoryLimit 值为0表示完成后立即删除Job,不留历史
timeZone 需集群版本1.24+并开启CronJobTimeZone特性
jobTemplate.spec.backoffLimit 单个Job内Pod重启次数上限
activeDeadlineSeconds 整个Job最长存活时间,防挂死

使用方法

kubectl apply -f mysql-backup-cronjob.yaml # 创建CronJob对象
kubectl get cronjob mysql-backup           # 查看CronJob对象
kubectl get job -l app=mysql-backup        # 查看每次生成的Job对象
kubectl logs -f job/mysql-backup-***       # 查看备份实时日志

6 CronJob示例

接下来在一个控制平面节点和两个工作节点的集群运行一个CronJob示例,每隔1分钟向/root/k8s-test/datatime-cronjob.log文件写一行带时间戳的日志文件。

(1) 编写CronJob资源清单文件
该CronJob为定时任务,每分钟执行一次,schedule的语法规则和Uninx的cron语法规则相同。

[root@master 15-cronjob]# cat busybox-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: time-writer-cj
spec:
  schedule: "*/1 * * * *"  # one time per minute
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: writer
            image: busybox:1.34.1
            command:
            - /bin/sh
            - -c
            - |
              echo "$(date '+%F %T') - hello from busybox" >> /opt/cronjob/time-cronjob.log
            volumeMounts:
            - name: hostdir
              mountPath: /opt/cronjob
          restartPolicy: OnFailure
          volumes:
          - name: hostdir
            hostPath:
              path: /root/k8s-test/data
              type: DirectoryOrCreate

(2) 创建CronJob

# 查看Job,CronJob,Pod,可以看到只有上次Job任务的Job和Pod
[root@master 15-cronjob]# kubectl get job
NAME              COMPLETIONS   DURATION   AGE
time-writer-job   1/1           3s         6m32s
[root@master 15-cronjob]# kubectl get cronjob
No resources found in default namespace.
[root@master 15-cronjob]# kubectl get pod
NAME                    READY   STATUS      RESTARTS   AGE
time-writer-job-cxr4c   0/1     Completed   0          6m40s
# 创建CronJob
[root@master 15-cronjob]# kubectl apply -f busybox-cronjob.yaml
cronjob.batch/time-writer-cj created

(3) 查看CronJob

# SCHEDULE为任务调度,这里为每分钟调度一次
[root@master 15-cronjob]# kubectl get cronjob
NAME             SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
time-writer-cj   */1 * * * *   False     1        2s              7s
# cronjob会在触发调度时创建一个job
[root@master 15-cronjob]# kubectl get job
NAME                      COMPLETIONS   DURATION   AGE
time-writer-cj-29246273   1/1           3s         7s
time-writer-job           1/1           3s         7m1s
# 每次执行任务都会创建一个job
[root@master 15-cronjob]# kubectl get job
NAME                      COMPLETIONS   DURATION   AGE
time-writer-cj-29246273   1/1           3s         103s
time-writer-cj-29246274   1/1           3s         43s
time-writer-job           1/1           3s         8m37s
# 第三个job
[root@master 15-cronjob]# kubectl get job
NAME                      COMPLETIONS   DURATION   AGE
time-writer-cj-29246273   1/1           3s         2m12s
time-writer-cj-29246274   1/1           3s         72s
time-writer-cj-29246275   1/1           3s         12s
time-writer-job           1/1           3s         9m6s
# 可以看到cronjob被调度到了worker1节点
[root@master 15-cronjob]# kubectl get pod -o wide
NAME                            READY   STATUS      RESTARTS   AGE     IP          NODE      NOMINATED NODE   READINESS GATES
time-writer-cj-29246273-nc8m8   0/1     Completed   0          2m30s   10.42.1.3   worker1   <none>           <none>
time-writer-cj-29246274-fmkc7   0/1     Completed   0          90s     10.42.1.4   worker1   <none>           <none>
time-writer-cj-29246275-8xfq2   0/1     Completed   0          30s     10.42.1.5   worker1   <none>           <none>
time-writer-job-cxr4c           0/1     Completed   0          9m24s   10.42.1.2   worker1   <none>           <none>
[root@master 15-cronjob]#

(4) 查看CronJob的输出文件
【本步骤在worker1虚拟机执行】
由于本CronJob被调度到了worker1节点,所以需要进入worker1查看。

# 进入worker1节点宿主机目录
[root@worker1 data]# pwd
/root/k8s-test/data
# 可以看到生成了一个time-cronjob.log文件
[root@worker1 data]# ls
time-cronjob.log  time-job.log
# 查看cronjob的输出,每秒执行一次
[root@worker1 data]# cat time-cronjob.log
2025-08-09 21:51:59 - hello from busybox
2025-08-09 21:52:59 - hello from busybox
2025-08-09 21:53:59 - hello from busybox
[root@worker1 data]#
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐