K8s学习笔记(九) job与cronjob
在 Kubernetes 中,Job 和 CronJob 是专门用于处理 “任务型工作负载” 的资源对象:
- Job 用于运行一次性任务(任务完成后自动结束,不会持续运行),比如数据备份、批量计算、初始化数据等。
- CronJob 是定时任务的封装(基于时间调度的 Job),类似 Linux 的
cron
服务,用于周期性执行任务(如每天凌晨清理日志、每小时生成报表)。
1 Job:一次性任务的 “执行者”
Job 的核心目标是:确保任务 “成功完成”(即使节点故障,K8s 也会在其他节点重启任务)。任务完成后,Job 会保留历史 Pod(默认保留 1 个),方便查看执行结果。
1.1 Job 的核心属性(必懂)
定义 Job 时,需要明确 “任务如何执行”“执行多少次”“失败了怎么办”,关键属性如下:
属性名 | 作用 | 示例值 |
---|---|---|
spec.template | 任务的 Pod 模板(核心!Job 通过创建 Pod 来执行任务,和普通 Pod 定义类似) | 包含containers 、image 等 |
spec.completions | 任务需要 “成功完成” 的总次数(默认 1 次,适合批量任务) | 3 (需成功执行 3 次) |
spec.parallelism | 任务的 “并行度”(同时运行的 Pod 数量,默认 1) | 2 (同时跑 2 个 Pod) |
spec.restartPolicy | 容器失败后的重启策略(Job 只能用OnFailure 或Never ,不能用Always ) | OnFailure (失败后重启容器) |
spec.backoffLimit | 任务失败的 “重试上限”(超过次数则 Job 标记为 Failed,默认 6 次) | 4 (最多重试 4 次) |
spec.activeDeadlineSeconds | 任务的 “超时时间”(超过这个时间,无论是否完成都会终止,单位秒) | 300 (5 分钟超时) |
1.2 Job 示例:执行一次 “打印日期” 任务
创建一个简单的 Job,让 Pod 执行date
命令(完成后自动退出),YAML 文件(job-demo.yaml
):
apiVersion: batch/v1
kind: Job
metadata:name: date-job # Job名称
spec:completions: 1 # 成功完成1次即可parallelism: 1 # 同时运行1个PodbackoffLimit: 4 # 最多重试4次template:spec:containers:- name: date-containerimage: busybox:1.35 # 轻量Linux镜像command: ["date"] # 执行date命令(输出当前时间后退出)restartPolicy: OnFailure # 容器失败时重启(如命令执行出错)
操作与查看:
# 创建Job
kubectl apply -f job-demo.yaml# 查看Job状态(STATUS为Completed表示成功)
kubectl get job date-job
# 输出示例:
# NAME COMPLETIONS DURATION AGE
# date-job 1/1 3s 10s# 查看Job创建的Pod(名称格式:Job名-随机字符串)
kubectl get pods --selector=job-name=date-job # 用标签筛选Job关联的Pod
# 输出示例:
# NAME READY STATUS RESTARTS AGE
# date-job-8f2x9 0/1 Completed 0 15s# 查看Pod的执行结果(即date命令的输出)
kubectl logs date-job-8f2x9
# 输出示例:
# Fri Oct 2 12:34:56 UTC 2025
1.3 Job 的生命周期(从创建到结束)
- 创建阶段:Job 被提交后,K8s 根据
parallelism
创建对应数量的 Pod。 - 执行阶段:
- 若 Pod 成功退出(容器 exit code=0),则计数
completions
加 1; - 若 Pod 失败(exit code≠0),根据
restartPolicy
决定是否重启(OnFailure
重启容器,Never
重新创建 Pod),直到达到backoffLimit
或activeDeadlineSeconds
。
- 若 Pod 成功退出(容器 exit code=0),则计数
- 结束阶段:当
completions
达到设定值,Job 状态变为Completed
;若超过重试次数或超时,状态变为Failed
。
2 CronJob:定时任务的 “调度器”
CronJob 本质是 “Job 的调度器”—— 通过时间表达式(类似 Linux 的cron
)定期创建 Job,从而实现周期性任务。比如 “每天凌晨 2 点执行数据库备份”“每小时清理临时文件”。
2.1 CronJob 的核心属性(必懂)
CronJob 在 Job 的基础上增加了 “时间调度” 和 “任务并发控制” 的属性,关键配置如下:
属性名 | 作用 | 示例值 |
---|---|---|
spec.schedule | 定时调度表达式(核心!格式:分 时 日 月 周 ,和 Linux cron 一致) | 0 2 * * * (每天凌晨 2 点) |
spec.jobTemplate | 要调度的 Job 模板(定义任务的具体内容,和 Job 的 spec 一致) | 包含completions 、template 等 |
spec.concurrencyPolicy | 并发策略(当新任务触发时,旧任务未完成如何处理) | Allow (允许并发,默认)、Forbid (禁止,跳过新任务)、Replace (替换,终止旧任务) |
spec.startingDeadlineSeconds | 任务的 “启动截止时间”(若因各种原因未按时启动,超过此时长则视为失败) | 300 (5 分钟内未启动则失败) |
spec.successfulJobsHistoryLimit | 保留 “成功 Job” 的历史记录数量(默认 3 个,超过自动删除) | 5 (保留 5 个成功记录) |
spec.failedJobsHistoryLimit | 保留 “失败 Job” 的历史记录数量(默认 1 个) | 2 (保留 2 个失败记录) |
重点:schedule
表达式格式(和 Linux cron 一致)
格式:分 时 日 月 周
(5 个字段,空格分隔),支持通配符和特殊符号:
*
:任意值(如* * * * *
表示每分钟);,
:枚举(如0 1,3 * * *
表示每天 1 点和 3 点);-
:范围(如0 9-17 * * 1-5
表示工作日 9 点到 17 点每小时 0 分);/
:步长(如*/10 * * * *
表示每 10 分钟);@yearly
/@monthly
/@daily
/@hourly
:快捷方式(如@daily
等价于0 0 * * *
)。
2.2 CronJob 示例:每分钟打印当前时间
创建一个 CronJob,每分钟执行一次date
命令(通过 Job 实现),YAML 文件(cronjob-demo.yaml
):
apiVersion: batch/v1
kind: CronJob
metadata:name: date-cronjob # CronJob名称
spec:schedule: "*/1 * * * *" # 每分钟执行一次concurrencyPolicy: Allow # 允许并发(前一个未结束也可启动新的)startingDeadlineSeconds: 10 # 10秒内未启动则视为失败successfulJobsHistoryLimit: 2 # 保留2个成功Job记录failedJobsHistoryLimit: 1 # 保留1个失败Job记录jobTemplate: # 要调度的Job模板spec:completions: 1parallelism: 1backoffLimit: 2template:spec:containers:- name: date-containerimage: busybox:1.35command: ["date"]restartPolicy: OnFailure
操作与查看:
# 创建CronJob
kubectl apply -f cronjob-demo.yaml# 查看CronJob状态
kubectl get cronjob date-cronjob
# 输出示例:
# NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
# date-cronjob */1 * * * * False 0 20s 1m# 查看CronJob创建的Job(每触发一次生成一个Job)
kubectl get jobs --selector=controller-uid=$(kubectl get cronjob date-cronjob -o jsonpath='{.metadata.uid}')
# 输出示例(每分钟一个Job):
# NAME COMPLETIONS DURATION AGE
# date-cronjob-28501560 1/1 2s 30s
# date-cronjob-28501561 1/1 2s 24s# 查看最新Job的Pod日志(取最近的Job名称)
kubectl logs $(kubectl get pods --selector=job-name=date-cronjob-28501561 -o jsonpath='{.items[0].metadata.name}')
# 输出示例:
# Fri Oct 2 12:40:00 UTC 2025
2.3 CronJob 的生命周期(从调度到执行)
- 调度阶段:K8s 根据
schedule
表达式定期检查是否需要触发任务(默认每 10 秒检查一次)。 - 启动阶段:若到达调度时间,CronJob 会创建一个 Job;若因节点故障等原因未按时启动,超过
startingDeadlineSeconds
则本次调度失败。 - 执行阶段:新创建的 Job 按自身规则运行(同 Job 的生命周期),CronJob 会根据
concurrencyPolicy
处理并发任务。 - 清理阶段:当历史 Job 数量超过
successfulJobsHistoryLimit
或failedJobsHistoryLimit
时,自动删除旧记录。
4 Job 与 CronJob 的核心区别
维度 | Job | CronJob |
---|---|---|
任务类型 | 一次性任务(执行一次就结束) | 定时任务(按时间周期重复执行) |
触发方式 | 手动创建后立即执行 | 按schedule 表达式自动触发 |
核心配置 | completions 、parallelism | schedule 、jobTemplate 、concurrencyPolicy |
适用场景 | 数据备份(一次性)、初始化脚本 | 日志清理(每日)、报表生成(每小时) |
5 常见问题与排错
- Job 一直处于 Active 状态,不结束:
- 原因:Pod 内的容器没有退出(比如命令是
tail -f /dev/null
这类阻塞进程),导致completions
无法达到设定值。 - 解决:检查容器命令是否会自动退出(exit code=0),或手动删除 Pod 强制结束(
kubectl delete pod <pod-name>
)。
- 原因:Pod 内的容器没有退出(比如命令是
- CronJob 到时间了但没创建 Job:
- 原因 1:
schedule
表达式错误(比如61 * * * *
,分钟不能超过 60)。 - 原因 2:
startingDeadlineSeconds
设置过小(比如调度检查延迟了 20 秒,但该值设为 10,导致视为失败)。 - 排错:
kubectl describe cronjob <cronjob-name>
,查看Events
字段(如 “Error creating job: schedule is invalid”)。
- 原因 1:
- CronJob 创建的 Job 太多,占用资源:
- 解决:减小
successfulJobsHistoryLimit
和failedJobsHistoryLimit
(如设为 1),或定期清理旧 Job(kubectl delete jobs --field-selector status.successful=1
)。
- 解决:减小
- Job 的 Pod 反复重启,但一直失败:
- 原因:容器命令执行失败(exit code≠0),且
restartPolicy=OnFailure
导致不断重启。 - 解决:
kubectl logs <pod-name>
查看错误日志,修复命令;或调整backoffLimit
限制重试次数。
- 原因:容器命令执行失败(exit code≠0),且
6 总结
- Job 是 “一次性任务” 的载体,核心是确保任务成功完成,适合临时执行的脚本、计算等。
- CronJob 是 “定时任务” 的调度器,通过时间表达式周期性创建 Job,适合重复性任务。
- 关键是理解:Job 的
completions
/parallelism
控制任务执行次数和并行度;CronJob 的schedule
和concurrencyPolicy
控制调度规则和并发行为。