一、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 秒后退出。
yaml
# job1.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: process-item
labels:
jobgroup: jobexample
spec:
template:
metadata:
name: jobexample
labels:
jobgroup: jobexample
spec:
containers:
- name: c
image: docker.io/library/busybox:1.28
imagePullPolicy: IfNotPresent
command: ["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 的生命周期
操作命令
bash
# 创建 Job
[root@hd1 k8s]# kubectl apply -f job1.yaml
# 查看 Job 状态
[root@hd1 k8s]# kubectl get job
NAME COMPLETIONS DURATION AGE
process-item 1/1 16s 20s
# 查看 Pod(任务完成后状态为 Completed)
[root@hd1 k8s]# kubectl get pod | grep process
process-item-9wq4m 0/1 Completed 0 20s
# 查看 Pod 日志(输出命令执行结果)
[root@hd1 k8s]# kubectl logs process-item-9wq4m
Processing item
#这个语法也有相同的效果,只是用的是job的名称
[root@hd1 k8s]# kubectl logs job/process-item
Processing item
2.3 Job 示例二:计算 π 到小数点后 2000 位
这是一个稍微复杂的 Job 示例,它使用 Perl 镜像计算 π 的值,并打印结果。
yaml
# job2.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: docker.io/library/perl:5.34.0
imagePullPolicy: IfNotPresent
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
新增参数解析:
| 字段 | 说明 |
|---|---|
backoffLimit: 4 |
重试次数限制 :Pod 失败后最多重试 4 次。如果所有尝试都失败,Job 状态变为 Failed。默认值为 6 |
操作命令
bash
# 创建 Job
[root@hd1 k8s]# kubectl apply -f job2.yaml
# 查看 Job 控制器
[root@hd1 k8s]# kubectl get job pi
NAME COMPLETIONS DURATION AGE
pi 1/1 12s 30s
# 查看 Job 的日志(通过 job 名称直接查看)
[root@hd1 k8s]# kubectl logs job/pi
3.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 表达式,格式为:
text
分钟 小时 日 月 星期
| 字段 | 取值范围 | 说明 |
|---|---|---|
| 分钟 | 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 示例,它会在每分钟执行一次,打印当前时间和问候信息。
yaml
# cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "* * * * *" #调度时间表:Cron 表达式,指定何时触发任务
jobTemplate: #Job 模板:定义每次触发时创建的 Job 规格
spec: #Job 的规格
template:
spec:
containers:
- name: hello
image: docker.io/library/busybox:1.28
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
可以观测到,cronjob与job的语法基本一致,只是包裹了一层调度时间表schedule,并且将基本job的配置放到了 jobTemplate下。
CronJob 中 restartPolicy 的选择 :
在 CronJob 的 Pod 模板中,restartPolicy 通常设置为 OnFailure 或 Never。
| 重启策略 | 适用场景 |
|---|---|
OnFailure |
推荐:Pod 失败时原地重启,能快速恢复,适合大多数定时任务 |
Never |
任务失败时重建新 Pod,适合完全隔离的重试场景 |
应用yaml
bash
# 创建 CronJob
[root@hd1 k8s]# kubectl apply -f cronjob.yaml
cronjob.batch/hello created
# 查看 CronJob
[root@hd1 k8s]# kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello * * * * * False 0 44s 60s
# 查看由 CronJob 创建的 Job
[root@hd1 k8s]# kubectl get job
NAME COMPLETIONS DURATION AGE
hello-28229083 1/1 3s 90s
hello-28229084 1/1 3s 30s
# 查看 Pod
[root@hd1 k8s]# kubectl get pod | grep hello
hello-28229083-2n6gz 0/1 Completed 0 90s
hello-28229084-xkzsj 0/1 Completed 0 30s
# 查看第一次执行的日志
[root@hd1 k8s]# kubectl logs hello-28229083-2n6gz
Sun Sep 3 12:43:01 UTC 2023
Hello from the Kubernetes cluster
# 查看第二次执行的日志
[root@hd1 k8s]# kubectl logs hello-28229084-xkzsj
Sun Sep 3 12:44:01 UTC 2023
Hello from the Kubernetes cluster
3.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 示例:
yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "0 2 * * *"
startingDeadlineSeconds: 60
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 5
failedJobsHistoryLimit: 2
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox:1.28
command: ["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 常用命令速查
bash
# ---------- Job 相关 ----------
# 创建 Job
kubectl apply -f job.yaml
# 查看 Job
kubectl get job
kubectl get job -o wide
# 查看 Job 详情
kubectl describe job <job-name>
# 查看 Job 的日志
kubectl logs job/<job-name>
# 删除 Job(同时删除关联的 Pod)
kubectl delete job <job-name>
# ---------- CronJob 相关 ----------
# 创建 CronJob
kubectl apply -f cronjob.yaml
# 查看 CronJob
kubectl get cronjob
kubectl get cj
# 查看 CronJob 详情
kubectl describe cronjob <cronjob-name>
# 查看 CronJob 创建的 Job
kubectl get job | grep <cronjob-name>
# 删除 CronJob(同时删除关联的 Job 和 Pod)
kubectl delete cronjob <cronjob-name>
# 暂停 CronJob
kubectl patch cronjob <cronjob-name> -p '{"spec":{"suspend":true}}'
# 恢复 CronJob
kubectl patch cronjob <cronjob-name> -p '{"spec":{"suspend":false}}'
5.4 Job 与 CronJob 创建的资源链
text
┌─────────────────────────────────────────────────────────────────────────────┐
│ 资源创建链关系 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 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 的补充
原文未涉及这两个参数。补充说明如下:
yaml
spec:
completions: 5 # 总共需要成功完成 5 个 Pod
parallelism: 2 # 最多同时运行 2 个 Pod
工作流程:
- Job 控制器首先启动 2 个 Pod(受
parallelism限制) - 每完成一个 Pod,就启动下一个
- 直到累计完成 5 个 Pod(受
completions限制),Job 标记为完成
3. 关于 Job 的超时控制
示例中未涉及 activeDeadlineSeconds,补充说明:
yaml
spec:
activeDeadlineSeconds: 300 # Job 最长运行 300 秒(5 分钟)
如果 Job 运行时间超过此值,Job 会被标记为 Failed,即使重试次数未用完。超时控制常用于防止任务因异常而无限执行。