kubernetes中离线业务编排详解JobCronJob之Job 应用
在 Kubernetes 中编排离线业务(如批处理任务、定时任务或计算密集型作业)通常需要结合 Job 和 CronJob 等资源对象,同时合理管理资源分配、任务调度和依赖关系。
Job用来管理一次性任务,确保任务成功完成;CronJob则类似于Linux的Cron,定时执行任务
1.在线业务和离线业务
在线业务
Deployment、StatefulSet以及 DaemonSet 这三个编排概念的共同之处是:它们主要编排的对象,都是"在线业务",即:Long Running Task(长作业)。比如常用的 Nginx、Tomcat,以及 MySQL 等等。这些应用一旦运行起来,除非出错或者停止,它的容器进程会一直保持在 Running 状态。
离线业务
指的是批处理任务、定时任务或者计算密集型但不需要实时响应的作业,比如数据分析、机器学习训练、视频渲染等。这类任务的特点是运行时间较长,不需要一直运行,一旦完成就会终止。
1.1. Job 的核心概念
- 一次性执行:确保任务运行到完成(完成后 Pod 不会重启)。
- 失败自动重试:通过
backoffLimit
控制重试次数。 - 并行控制:支持指定并行运行的 Pod 数量(
parallelism
)和总完成数(completions
)。 - 适用场景:数据处理、定时任务(结合
CronJob
)、测试任务等。
2.Job 的核心定义
2.1.YAML 结构示例
apiVersion: batch/v1
kind: Job
metadata:name: example-job
spec:completions: 3 # 需要成功完成的任务总次数(默认 1)parallelism: 2 # 允许同时运行的 Pod 数量(默认 1)backoffLimit: 4 # 失败后重试的最大次数(默认 6)template:spec:containers:- name: taskimage: busyboxcommand: ["sh", "-c", "echo Processing item $ITEM && exit 0"]env:- name: ITEMvalue: "123"restartPolicy: OnFailure # 必须为 OnFailure 或 Never
关键字段说明
completions
:任务需要成功完成的总次数(适用于需要多次执行的任务)。parallelism
:允许同时运行的 Pod 数量(控制并发)。backoffLimit
:任务失败后的最大重试次数。restartPolicy
:仅支持OnFailure
或Never
(确保任务完成后不再重启)。
2.2. 实战场景与操作
场景 1:单次任务
运行一个简单的 Job,打印消息后退出。
[root@master ~]# mkdir job
[root@master ~]# cd job/
[root@master job]# vim test_jobs.yml
apiVersion: batch/v1
kind: Job
metadata:name: test-task
spec:template:spec:containers:- name: helloimage: busyboxcommand: ["sh", "-c", "echo 'Hello Kubernetes Job!' && exit 0"]restartPolicy: OnFailure[root@master job]# kubectl apply -f test_jobs.yml
job.batch/test-task created[root@master job]# kubectl describe jobs test-task #查看job的详细信息
Name: test-task
Namespace: default
Selector: batch.kubernetes.io/controller-uid=8ac0999b-59ea-4f64-b8c3-8a19803985a3
Labels: batch.kubernetes.io/controller-uid=8ac0999b-59ea-4f64-b8c3-8a19803985a3batch.kubernetes.io/job-name=test-taskcontroller-uid=8ac0999b-59ea-4f64-b8c3-8a19803985a3job-name=test-task
Annotations: <none>
Parallelism: 1
Completions: 1
Completion Mode: NonIndexed
Suspend: false
Backoff Limit: 6
Start Time: Fri, 02 May 2025 16:28:03 +0800
Completed At: Fri, 02 May 2025 16:28:29 +0800
Duration: 26s
Pods Statuses: 0 Active (0 Ready) / 1 Succeeded / 0 Failed
Pod Template:Labels: batch.kubernetes.io/controller-uid=8ac0999b-59ea-4f64-b8c3-8a19803985a3batch.kubernetes.io/job-name=test-taskcontroller-uid=8ac0999b-59ea-4f64-b8c3-8a19803985a3job-name=test-taskContainers:hello:Image: busyboxPort: <none>Host Port: <none>Command:sh-cecho 'Hello Kubernetes Job!' && exit 0Environment: <none>Mounts: <none>Volumes: <none>Node-Selectors: <none>Tolerations: <none>
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal SuccessfulCreate 4m36s job-controller Created pod: test-task-9mmsnNormal Completed 4m10s job-controller Job completed
为了避免不同 Job 对象所管理的 Pod 发生重合,Job 对象在创建后,它的 Pod 模板,被自动加上了一个 controller-uid=< 一个随机字符串 > 这样的 Label。而这个 Job 对象本身,则被自动加上了这个 Label 对应的 Selector,保证了 Job 与它所管理的 Pod 之间的匹配关系。
[root@master job]# kubectl get jobs # 查看 Job 状态(COMPLETIONS 应为 1/1)
NAME STATUS COMPLETIONS DURATION AGE
test-task Complete 1/1 26s 28s[root@master job]# kubectl get pods --selector=job-name=test-task # 查看关联的 Pod
NAME READY STATUS RESTARTS AGE
test-task-9mmsn 0/1 Completed 0 66s
Pod 进入了 Running 状态说明它正在打印消息,打印完了之后这个 Pod 就会进入 Completed 状态。
[root@master job]# kubectl logs test-task-9mmsn # 查看输出日志(应显示 "Hello Kubernetes Job!")
Hello Kubernetes Job!
离线任务的 Pod 永远都不应该被重启
实现方式是在 Pod 模板中定义 restartPolicy=Never
事实上restartPolicy 在 Job 对象里只允许被设置为 Never 和 OnFailure;而在 Deployment 对象里,restartPolicy 则只允许被设置为 Always。
场景2:并行任务
运行一个并行处理任务的 Job,模拟批量处理数据
离线业务之所以被称为 Batch Job,是因为它们可以以"Batch",也就是并行的方式去运行。
负责并行控制的参数有两个:
spec.parallelism:
定义一个 Job 在任意时间最多可以启动多少个 Pod 同时运行;
spec.completions:
定义 Job 至少要完成的 Pod 数目,即 Job 的最小完成数。
[root@master job]# cat test_jobs2.yml
apiVersion: batch/v1
kind: Job
metadata:name: task-job2
spec:completions: 6 # 总共需要完成 6 个任务parallelism: 2 # 同时运行 2 个 Podtemplate:spec:containers:- name: workerimage: busyboxcommand: ["sh", "-c", "echo Processing item $ITEM && sleep 5 && exit 0"]env:- name: ITEMvalueFrom:fieldRef:fieldPath: metadata.name # 使用 Pod 名称作为参数restartPolicy: OnFailure[root@master job]# kubectl apply -f test_jobs2.yml
job.batch/task-job2 created
这个 Job 首先创建了两个并行运行的 Pod 来执行任务:
[root@master job]# kubectl get pod
NAME READY STATUS RESTARTS AGE
task-job2-8n4xk 0/1 ContainerCreating 0 4s
task-job2-w4kkh 0/1 ContainerCreating 0 4s
这时可以看到,每当有一个 Pod 完成计算进入 Completed 状态时,就会有一个新的 Pod 被自动创建出来,并且快速地从 Pending 状态进入到 ContainerCreating 状态:
[root@master job]# kubectl get pod
NAME READY STATUS RESTARTS AGE
task-job2-8n4xk 1/1 Running 0 47s
task-job2-jwjkd 0/1 ContainerCreating 0 17s
task-job2-w4kkh 0/1 Completed 0 47s[root@master job]# kubectl get pod
NAME READY STATUS RESTARTS AGE
task-job2-8n4xk 0/1 Completed 0 84s
task-job2-ds5jq 0/1 ContainerCreating 0 31s
task-job2-jwjkd 0/1 Completed 0 54s
task-job2-pn7lc 0/1 ContainerCreating 0 9s
task-job2-w4kkh 0/1 Completed 0 84s
也可以实时查看
[root@master job]# kubectl get pods -w # 实时观察 Pod 的创建和完成情况
NAME READY STATUS RESTARTS AGE
task-job2-dhljh 1/1 Running 0 6s
task-job2-wvzl7 1/1 Running 0 6s
test-task-9mmsn 0/1 Completed 0 28m
task-job2-wvzl7 0/1 Completed 0 8s
task-job2-dhljh 0/1 Completed 0 9s
task-job2-wvzl7 0/1 Completed 0 9s
task-job2-wvzl7 0/1 Completed 0 9s
task-job2-pxnjw 0/1 Pending 0 0s
task-job2-pxnjw 0/1 Pending 0 0s
task-job2-wvzl7 0/1 Completed 0 10s
task-job2-pxnjw 0/1 ContainerCreating 0 0s
task-job2-dhljh 0/1 Completed 0 10s
task-job2-dhljh 0/1 Completed 0 10s
task-job2-pxnjw 0/1 ContainerCreating 0 1s
task-job2-lplw2 0/1 Pending 0 0s
task-job2-lplw2 0/1 Pending 0 0s
task-job2-lplw2 0/1 ContainerCreating 0 0s
task-job2-dhljh 0/1 Completed 0 11s
task-job2-lplw2 0/1 ContainerCreating 0 0s
task-job2-pxnjw 1/1 Running 0 3s
task-job2-lplw2 1/1 Running 0 3s
task-job2-pxnjw 0/1 Completed 0 8s
task-job2-lplw2 0/1 Completed 0 8s
task-job2-pxnjw 0/1 Completed 0 9s
task-job2-pxnjw 0/1 Completed 0 9s
task-job2-r8bn5 0/1 Pending 0 0s
task-job2-r8bn5 0/1 Pending 0 0s
task-job2-pxnjw 0/1 Completed 0 10s
task-job2-r8bn5 0/1 ContainerCreating 0 0s
task-job2-lplw2 0/1 Completed 0 9s
task-job2-lplw2 0/1 Completed 0 9s
task-job2-r8bn5 0/1 ContainerCreating 0 1s
task-job2-s5k4g 0/1 Pending 0 0s
task-job2-s5k4g 0/1 Pending 0 0s
task-job2-lplw2 0/1 Completed 0 10s
task-job2-s5k4g 0/1 ContainerCreating 0 0s
task-job2-s5k4g 0/1 ContainerCreating 0 1s
task-job2-r8bn5 1/1 Running 0 3s
task-job2-s5k4g 1/1 Running 0 3s
task-job2-r8bn5 0/1 Completed 0 8s
task-job2-s5k4g 0/1 Completed 0 8s
task-job2-r8bn5 0/1 Completed 0 9s
task-job2-r8bn5 0/1 Completed 0 9s
task-job2-r8bn5 0/1 Completed 0 10s
task-job2-s5k4g 0/1 Completed 0 9s
task-job2-s5k4g 0/1 Completed 0 9s
task-job2-s5k4g 0/1 Completed 0 10s
查看jobs的完成状态
[root@master job]# kubectl get jobs # COMPLETIONS 应为 6/6
NAME STATUS COMPLETIONS DURATION AGE
task-job2 Complete 6/6 31s 103s
查看生成的pod
[root@master job]# kubectl get pod
NAME READY STATUS RESTARTS AGE
task-job2-dhljh 0/1 Completed 0 2m43s
task-job2-lplw2 0/1 Completed 0 2m32s
task-job2-pxnjw 0/1 Completed 0 2m33s
task-job2-r8bn5 0/1 Completed 0 2m23s
task-job2-s5k4g 0/1 Completed 0 2m22s
task-job2-wvzl7 0/1 Completed 0 2m43s[root@master job]# kubectl logs task-job2-lplw2
Processing item task-job2-lplw2
[root@master job]# kubectl logs task-job2-s5k4g
Processing item task-job2-s5k4g
Job Controller工作原理总结
Job Controller 控制的对象,直接就是 Pod。
Job Controller 在控制循环中进行的调谐(Reconcile)操作,是根据实际在 Running 状态 Pod 的数目、已经成功退出的 Pod 的数目,以及 parallelism、completions 参数的值共同计算出在这个周期里,应该创建或者删除的 Pod 数目,然后调用 Kubernetes API 来执行这个操作。
场景3:失败重试
离线作业失败处理方式
离线作业失败后 Job Controller 就会不断地尝试创建一个新 Pod,这个尝试肯定不能无限进行下去。所以,在 Job 对象的 spec.backoffLimit 字段里定义了重试次数为 3(即,backoffLimit=3,默认值是 6)
如果restartPolicy=OnFailure,离线作业失败后,Job Controller 就不会去尝试创建新的 Pod。但是,它会不断地尝试重启 Pod 里的容器。
模拟任务失败并观察 Job 的重试机制。
[root@master job]# cat test_jobs3.yml
apiVersion: batch/v1
kind: Job
metadata:name: task-job3
spec:backoffLimit: 3 # 最多重试 3 次template:spec:containers:- name: task-3image: busyboxcommand: ["sh", "-c", "echo 'Attempting...' && exit 1"] # 故意失败restartPolicy: OnFailure[root@master job]# kubectl apply -f test_jobs3.yml
job.batch/task-job3 created
观察 Pod 的重启次数(RESTARTS 列)
[root@master job]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
task-job3-tbhst 0/1 ContainerCreating 0 2s
task-job3-tbhst 0/1 Error 0 24s
task-job3-tbhst 0/1 Error 1 (23s ago) 46s
task-job3-tbhst 0/1 CrashLoopBackOff 1 (1s ago) 47s
task-job3-tbhst 0/1 Error 2 (37s ago) 83s
task-job3-tbhst 0/1 CrashLoopBackOff 2 (12s ago) 95s
task-job3-tbhst 0/1 Error 3 (48s ago) 2m11s
task-job3-tbhst 0/1 Terminating 3 (49s ago) 2m12s
task-job3-tbhst 0/1 Terminating 3 2m12s
task-job3-tbhst 0/1 Terminating 3 2m12s
task-job3-tbhst 0/1 Terminating 3 2m13s
task-job3-tbhst 0/1 Error 3 2m13s
task-job3-tbhst 0/1 Error 3 2m13s
task-job3-tbhst 0/1 Error 3 2m13s[root@master job]# kubectl get jobs
NAME STATUS COMPLETIONS DURATION AGE
task-job3 Failed 0/1 2m49s 2m49s
到此只是重启了3次之后即停止重启。
修改restartPolicy为Never,再次查看
[root@master job]# kubectl delete -f test_jobs3.yml
[root@master job]# vim test_jobs3.yml
apiVersion: batch/v1
kind: Job
metadata:name: task-job3
spec:backoffLimit: 3 # 最多重试 3 次template:spec:containers:- name: task-3image: busyboxcommand: ["sh", "-c", "echo 'Attempting...' && exit 1"] # 故意失败restartPolicy: Never[root@master job]# kubectl apply -f test_jobs3.yml
重新创建3次pod
[root@master job]# kubectl get pods -w #实时查看
NAME READY STATUS RESTARTS AGE
task-job3-pjxzt 0/1 ContainerCreating 0 2s
task-job3-pjxzt 0/1 Error 0 23s
task-job3-pjxzt 0/1 Error 0 24s
task-job3-pjxzt 0/1 Error 0 24s
task-job3-pjxzt 0/1 Error 0 25s
task-job3-l6b45 0/1 Pending 0 0s
task-job3-l6b45 0/1 Pending 0 0s
task-job3-l6b45 0/1 ContainerCreating 0 0s
task-job3-l6b45 0/1 ContainerCreating 0 0s
task-job3-l6b45 0/1 Error 0 23s
task-job3-l6b45 0/1 Error 0 24s
task-job3-l6b45 0/1 Error 0 24s
task-job3-l6b45 0/1 Error 0 25s
task-job3-dh8xp 0/1 Pending 0 0s
task-job3-dh8xp 0/1 Pending 0 0s
task-job3-dh8xp 0/1 ContainerCreating 0 0s
task-job3-dh8xp 0/1 ContainerCreating 0 0s
task-job3-dh8xp 0/1 Error 0 2s
task-job3-dh8xp 0/1 Error 0 3s
task-job3-dh8xp 0/1 Error 0 4s
task-job3-dh8xp 0/1 Error 0 4s
task-job3-xkwjc 0/1 Pending 0 0s
task-job3-xkwjc 0/1 Pending 0 0s
task-job3-xkwjc 0/1 ContainerCreating 0 0s
task-job3-xkwjc 0/1 ContainerCreating 0 0s
task-job3-xkwjc 0/1 Error 0 23s
task-job3-xkwjc 0/1 Error 0 24s
task-job3-xkwjc 0/1 Error 0 25s
task-job3-xkwjc 0/1 Error 0 26s
以上,就是一个 Job API 对象最主要的概念和用法