# Kubernetes(K8s)笔记Day13 :工作负载资源概述与 Job (CronJob)控制器
一、Kubernetes 工作负载资源概述
Kubernetes 提供若干种内置的工作负载资源(控制器),用于管理不同场景下的 Pod:
| 工作负载资源 | 适用场景 | 核心特点 |
|---|---|---|
| Deployment | 无状态应用(如 Web 服务、API 网关) | Pod 相互等价,可随时替换,支持滚动更新和回滚 |
| StatefulSet | 有状态应用(如数据库、消息队列) | Pod 有固定身份和独立存储,启停有序 |
| DaemonSet | 节点级支撑服务(如日志采集、网络插件) | 每个节点上运行且仅运行一个 Pod 副本 |
| Job | 一次性任务(如数据迁移、批量计算) | Pod 运行完成后自动退出,不再重启 |
| CronJob | 定时任务(如定期备份、定时报表) | 按照 Cron 表达式周期性地创建 Job |
核心概念:工作负载资源本质上就是控制器(Controller) + Pod 模板。控制器负责根据 Pod 模板创建和管理 Pod 的生命周期。
二、Job(一次性任务)
2.1 什么是 Job?
Job是 Kubernetes 中用于管理一次性任务的控制器。它创建一个或多个 Pod,并确保指定数量的 Pod 成功完成执行。
核心特点:
| 特点 | 说明 |
|---|---|
| 一次性执行 | Job 创建的 Pod 在任务完成后会退出,状态变为Completed,而不是像 Deployment 那样持续运行 |
| 自动重启 | 如果 Pod 失败或被删除,Job 控制器会自动创建一个新的 Pod 继续执行,直到任务成功完成 |
| 适用场景 | 批处理任务、数据迁移、报表生成、计算任务等只需要执行一次的场景 |
Job 与普通 Pod 的区别:
| 对比维度 | 普通 Pod | Job 管理的 Pod |
|---|---|---|
| 退出后行为 | 退出后不再处理(除非设置restartPolicy) | 失败后会重试,直到成功或达到重试上限 |
| 管理方式 | 独立存在,需手动管理 | 由 Job 控制器自动管理生命周期 |
| 适用场景 | 持续运行的服务 | 执行完即结束的一次性任务 |
2.2 Job 示例一:简单的批处理任务
下面是一个简单的 Job 示例,它会在 Pod 中执行一条命令,输出信息并等待 15 秒后退出。
# job1.yamlapiVersion:batch/v1kind:Jobmetadata:name:process-itemlabels:jobgroup:jobexamplespec:template:metadata:name:jobexamplelabels:jobgroup:jobexamplespec:containers:-name:cimage:docker.io/library/busybox:1.28imagePullPolicy:IfNotPresentcommand:["sh","-c","echo Processing item && sleep 15"]restartPolicy:Never# ⚠️ Job 中不能使用 Always这个pod的作用是输出Processing item,等待15秒之后自动退出
参数解析:
| 字段 | 说明 |
|---|---|
apiVersion: batch/v1 | Job 资源所属的 API 组和版本 |
kind: Job | 资源类型为 Job |
metadata.name | Job 的名称 |
spec.template | Pod 模板,定义要运行的 Pod 规格 |
spec.template.spec.containers | 容器定义,指定镜像和要执行的命令 |
spec.template.spec.restartPolicy | 重启策略:Job 中必须设置为Never或OnFailure,不能使用默认的Always |
restartPolicy在 Job 中的说明:
| 重启策略 | 行为 |
|---|---|
Never | Pod 失败后,Job 控制器会创建新的 Pod来重试 |
OnFailure | Pod 失败后,原地重启容器(不创建新 Pod) |
Always | Job 中不可用,会导致 Job 无法正常完成 |
为什么这里没有标签选择器?
因为 Job 采用“命令式创建 + 属主引用”的强绑定方式,控制器创建 Pod 后立即记录引用,后续通过 ownerReferences (通过kubectl describe pod xxx 命令查看)追踪 Pod 的生命周期
操作命令
# 创建 Job[root@hd1 k8s]# kubectl apply -f job1.yaml# 查看 Job 状态[root@hd1 k8s]# kubectl get jobNAME COMPLETIONS DURATION AGE process-item1/1 16s 20s# 查看 Pod(任务完成后状态为 Completed)[root@hd1 k8s]# kubectl get pod | grep processprocess-item-9wq4m0/1 Completed020s# 查看 Pod 日志(输出命令执行结果)[root@hd1 k8s]# kubectl logs process-item-9wq4mProcessing item#这个语法也有相同的效果,只是用的是job的名称[root@hd1 k8s]# kubectl logs job/process-itemProcessing item2.3 Job 示例二:计算 π 到小数点后 2000 位
这是一个稍微复杂的 Job 示例,它使用 Perl 镜像计算 π 的值,并打印结果。
# job2.yamlapiVersion:batch/v1kind:Jobmetadata:name:pispec:template:spec:containers:-name:piimage:docker.io/library/perl:5.34.0imagePullPolicy:IfNotPresentcommand:["perl","-Mbignum=bpi","-wle","print bpi(2000)"]restartPolicy:NeverbackoffLimit:4新增参数解析:
| 字段 | 说明 |
|---|---|
backoffLimit: 4 | 重试次数限制:Pod 失败后最多重试 4 次。如果所有尝试都失败,Job 状态变为Failed。默认值为 6 |
操作命令
# 创建 Job[root@hd1 k8s]# kubectl apply -f job2.yaml# 查看 Job 控制器[root@hd1 k8s]# kubectl get job piNAME COMPLETIONS DURATION AGE pi1/1 12s 30s# 查看 Job 的日志(通过 job 名称直接查看)[root@hd1 k8s]# kubectl logs job/pi3.14159265358979323846264338327950288419716939937510...2.4 Job 的其他常用配置
| 配置项 | 说明 | 示例 |
|---|---|---|
completions | 指定需要成功完成的 Pod 数量(并行场景) | completions: 5表示需要 5 个 Pod 成功完成 |
parallelism | 指定同时运行的 Pod 数量上限 | parallelism: 2表示最多同时运行 2 个 Pod |
activeDeadlineSeconds | Job 的最长运行时间(超时则标记失败) | activeDeadlineSeconds: 300表示 5 分钟超时 |
backoffLimit | 失败重试次数上限 | backoffLimit: 4 |
三、CronJob(定时任务)
3.1 什么是 CronJob?
CronJob是 Kubernetes 中用于管理定时任务的控制器。它根据指定的时间表(Cron 表达式)周期性地创建 Job,类似于 Linux 系统中的crontab。
核心特点:
| 特点 | 说明 |
|---|---|
| 周期性执行 | 按照 Cron 表达式在指定的时间点自动创建 Job |
| 自动清理 | 可以配置保留历史 Job 的数量,自动清理旧的 Job |
| 适用场景 | 定期备份、定时报表生成、数据清理、定时同步等 |
3.2 Cron 表达式格式说明
CronJob 使用标准的 Cron 表达式,格式为:
分钟 小时 日 月 星期| 字段 | 取值范围 | 说明 |
|---|---|---|
| 分钟 | 0-59 | 每小时的第几分钟 |
| 小时 | 0-23 | 每天的第几小时 |
| 日 | 1-31 | 每月的第几天 |
| 月 | 1-12 | 每年的第几月 |
| 星期 | 0-6(0=星期日) | 每周的第几天 |
常见 Cron 表达式示例:
| 表达式 | 含义 |
|---|---|
* * * * * | 每分钟执行一次 |
0 * * * * | 每小时整点执行一次(每小时的 0 分) |
0 0 * * * | 每天午夜(0:00)执行一次 |
0 2 * * * | 每天凌晨 2:00 执行一次 |
0 0 * * 0 | 每周日凌晨 0:00 执行一次 |
0 0 1 * * | 每月 1 日凌晨 0:00 执行一次 |
*/5 * * * * | 每 5 分钟执行一次 |
0 9-17 * * * | 每天 9:00 到 17:00 之间每小时执行一次 |
3.3 CronJob 示例:每分钟打印时间
下面是一个完整的 CronJob 示例,它会在每分钟执行一次,打印当前时间和问候信息。
# cronjob.yamlapiVersion:batch/v1kind:CronJobmetadata:name:hellospec:schedule:"* * * * *"#调度时间表:Cron 表达式,指定何时触发任务jobTemplate:#Job 模板:定义每次触发时创建的 Job 规格spec:#Job 的规格template:spec:containers:-name:helloimage:docker.io/library/busybox:1.28imagePullPolicy:IfNotPresentcommand:-/bin/sh--c-date; echo Hello from the Kubernetes clusterrestartPolicy:OnFailure可以观测到,cronjob与job的语法基本一致,只是包裹了一层调度时间表schedule,并且将基本job的配置放到了jobTemplate下。
CronJob 中restartPolicy的选择:
在 CronJob 的 Pod 模板中,restartPolicy通常设置为OnFailure或Never。
| 重启策略 | 适用场景 |
|---|---|
OnFailure | 推荐:Pod 失败时原地重启,能快速恢复,适合大多数定时任务 |
Never | 任务失败时重建新 Pod,适合完全隔离的重试场景 |
应用yaml
# 创建 CronJob[root@hd1 k8s]# kubectl apply -f cronjob.yamlcronjob.batch/hello created# 查看 CronJob[root@hd1 k8s]# kubectl get cronjobNAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE hello * * * * * False044s 60s# 查看由 CronJob 创建的 Job[root@hd1 k8s]# kubectl get jobNAME COMPLETIONS DURATION AGE hello-282290831/1 3s 90s hello-282290841/1 3s 30s# 查看 Pod[root@hd1 k8s]# kubectl get pod | grep hellohello-28229083-2n6gz0/1 Completed090s hello-28229084-xkzsj0/1 Completed030s# 查看第一次执行的日志[root@hd1 k8s]# kubectl logs hello-28229083-2n6gzSun Sep312:43:01 UTC2023Hello from the Kubernetes cluster# 查看第二次执行的日志[root@hd1 k8s]# kubectl logs hello-28229084-xkzsjSun Sep312:44:01 UTC2023Hello from the Kubernetes cluster3.4 CronJob 的其他常用配置
| 配置项 | 说明 | 示例 |
|---|---|---|
startingDeadlineSeconds | 任务启动的截止时间(秒)。如果错过调度时间超过此值,则跳过本次执行 | startingDeadlineSeconds: 60 |
concurrencyPolicy | 并发策略: - Allow(默认):允许并发执行- Forbid:禁止并发,如果上一次未完成则跳过本次- Replace:替换,取消上一次未完成的并启动新的 | concurrencyPolicy: Forbid |
successfulJobsHistoryLimit | 保留的成功 Job 数量(默认 3) | successfulJobsHistoryLimit: 3 |
failedJobsHistoryLimit | 保留的失败 Job 数量(默认 1) | failedJobsHistoryLimit: 1 |
suspend | 是否暂停调度(true暂停,false正常运行) | suspend: true |
带完整配置的 CronJob 示例:
apiVersion:batch/v1kind:CronJobmetadata:name:hellospec:schedule:"0 2 * * *"startingDeadlineSeconds:60concurrencyPolicy:ForbidsuccessfulJobsHistoryLimit:5failedJobsHistoryLimit:2jobTemplate:spec:template:spec:containers:-name:helloimage:busybox:1.28command:["sh","-c","date; echo Hello"]restartPolicy:OnFailure四、Job 与 CronJob 对比总结
| 对比维度 | Job | CronJob |
|---|---|---|
| 执行频率 | 一次性执行 | 周期性执行(按 Cron 表达式) |
| 适用场景 | 批处理任务、数据迁移、一次性计算 | 定期备份、定时报表、周期性清理 |
| 是否持续运行 | ❌ 执行完成后 Pod 退出(Completed) | ❌ 每次执行完成即退出,但会定期创建新任务 |
| 失败重试 | ✅ 支持(通过backoffLimit控制) | ✅ 支持(通过 Job 模板的backoffLimit控制) |
| 并发控制 | 通过parallelism和completions控制 | 通过concurrencyPolicy控制 |
| 历史保留 | ❌ 不涉及 | ✅ 支持保留成功/失败的历史 Job 数量 |
| 暂停调度 | ❌ 不涉及 | ✅ 支持(suspend: true) |
| 错过调度处理 | ❌ 不涉及 | ✅ 支持(startingDeadlineSeconds) |
五、核心知识点速查
5.1 Job 核心要点
| 知识点 | 说明 |
|---|---|
restartPolicy限制 | Job 中不能使用Always,只能使用Never或OnFailure |
backoffLimit | 失败重试次数上限,默认 6 次 |
completions | 需要成功完成的 Pod 数量(默认 1) |
parallelism | 并行运行的 Pod 数量上限(默认 1) |
| 查看日志 | kubectl logs job/<job-name>可直接查看 Job 的日志 |
| 删除 Job | 删除 Job 时会自动删除其创建的 Pod(kubectl delete job <name>) |
5.2 CronJob 核心要点
| 知识点 | 说明 |
|---|---|
| 时间表格式 | 标准 Cron 表达式:分钟 小时 日 月 星期 |
| Job 模板 | spec.jobTemplate.spec中定义 Job 规格,与独立 Job 完全相同 |
| 并发策略 | Allow(默认)、Forbid、Replace |
| 历史限制 | successfulJobsHistoryLimit(默认 3)和failedJobsHistoryLimit(默认 1) |
| 暂停调度 | suspend: true可暂停 CronJob 的调度 |
5.3 常用命令速查
# ---------- Job 相关 ----------# 创建 Jobkubectl apply-fjob.yaml# 查看 Jobkubectl get job kubectl get job-owide# 查看 Job 详情kubectl describe job<job-name># 查看 Job 的日志kubectl logs job/<job-name># 删除 Job(同时删除关联的 Pod)kubectl delete job<job-name># ---------- CronJob 相关 ----------# 创建 CronJobkubectl apply-fcronjob.yaml# 查看 CronJobkubectl get cronjob kubectl get cj# 查看 CronJob 详情kubectl describe cronjob<cronjob-name># 查看 CronJob 创建的 Jobkubectl get job|grep<cronjob-name># 删除 CronJob(同时删除关联的 Job 和 Pod)kubectl delete cronjob<cronjob-name># 暂停 CronJobkubectl patch cronjob<cronjob-name>-p'{"spec":{"suspend":true}}'# 恢复 CronJobkubectl patch cronjob<cronjob-name>-p'{"spec":{"suspend":false}}'5.4 Job 与 CronJob 创建的资源链
┌─────────────────────────────────────────────────────────────────────────────┐ │ 资源创建链关系 │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ Deployment → ReplicaSet → Pod │ │ StatefulSet → Pod(直接管理) │ │ DaemonSet → Pod(直接管理) │ │ │ │ Job → Pod(直接管理,Pod 完成后进入 Completed) │ │ CronJob → Job → Pod(定期创建新的 Job) │ │ │ └─────────────────────────────────────────────────────────────────────────────┘六、常见问题排查
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
Job 一直卡在Running不结束 | 容器内的进程没有退出,或进入死循环 | 检查命令是否正确;确保命令执行完成后进程自然退出 |
Job 显示Failed | 容器退出码非 0,且重试次数已用完 | kubectl logs <pod>查看失败原因;调整backoffLimit增加重试次数 |
| CronJob 没有按时执行 | 时间表表达式写错,或节点时间不同步 | 检查 Cron 表达式格式;确认节点系统时间是否正确 |
| CronJob 积累了过多的 Job | 未设置历史限制,或限制值过大 | 设置successfulJobsHistoryLimit和failedJobsHistoryLimit |
| 同一个 CronJob 的任务重叠执行 | 并发策略为Allow(默认) | 将concurrencyPolicy改为Forbid或Replace |
七、总结
| 资源类型 | 一句话总结 |
|---|---|
| Job | “一次性任务”:只执行一次,执行完 Pod 自动退出,失败会自动重试 |
| CronJob | “定时任务”:根据 Cron 表达式周期性创建 Job,适合定期执行的任务 |
八、部分参数的补充说明
1. 关于 CronJob 的时间表
重要提示:CronJob 的时间表是基于Kubernetes 控制平面所在的时区(通常是 UTC 时间),而非本地时区。如果需要在特定本地时间执行任务,需要注意时区换算,或使用CRON_TZ变量(部分版本支持)。
2. 关于 Job 的completions和parallelism的补充
原文未涉及这两个参数。补充说明如下:
spec:completions:5# 总共需要成功完成 5 个 Podparallelism:2# 最多同时运行 2 个 Pod工作流程:
- Job 控制器首先启动 2 个 Pod(受
parallelism限制) - 每完成一个 Pod,就启动下一个
- 直到累计完成 5 个 Pod(受
completions限制),Job 标记为完成
3. 关于 Job 的超时控制
示例中未涉及activeDeadlineSeconds,补充说明:
spec:activeDeadlineSeconds:300# Job 最长运行 300 秒(5 分钟)如果 Job 运行时间超过此值,Job 会被标记为Failed,即使重试次数未用完。超时控制常用于防止任务因异常而无限执行。