当前位置: 首页 > web >正文

kubernetes中离线业务编排详解JobCronJob之Job 应用

在 Kubernetes 中编排离线业务(如批处理任务、定时任务或计算密集型作业)通常需要结合 JobCronJob 等资源对象,同时合理管理资源分配、任务调度和依赖关系。

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:仅支持 OnFailureNever(确保任务完成后不再重启)。

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工作原理总结

  1. Job Controller 控制的对象,直接就是 Pod。

  2. 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 对象最主要的概念和用法

http://www.xdnf.cn/news/3566.html

相关文章:

  • 泰迪杯特等奖案例学习资料:基于时空图卷积网络的物流车辆路径动态优化系统
  • 创意效率双提升,AIGC让增长更轻盈
  • LeetCode算法题 (移除链表元素)Day15!!!C/C++
  • 基于STM32的带恒温系统智能外卖柜设计
  • Linux——进程终止/等待/替换
  • LWIP带freeRTOS系统移植笔记
  • Linux 常用命令 - tar【归档与压缩】
  • 初识日志技术
  • 当LLM遇上Agent:AI三大流派的“复仇者联盟”
  • NVIDIA Omniverse在数字孪生中的算力消耗模型构建方法
  • Python智能体开发
  • LeetCode[102]二叉树的层序遍历
  • 走进AI的奇妙世界:探索历史、革命与未来机遇
  • Mybatis中的一级二级缓存扫盲
  • 如何使用模块
  • [FPGA Video] AXI4-Stream Remapper
  • vue3+ts项目 配置vue-router
  • TS 安装
  • 仿腾讯会议——注册登录实现
  • AI算法可视化:如何用Matplotlib与Seaborn解释模型?
  • Bootstrap(自助法)​​:无需假设分布的统计推断工具
  • 「Mac畅玩AIGC与多模态13」开发篇09 - 基于多插件协同开发智能体应用(天气+名言查询助手)
  • DeepSeek实战--各版本对比
  • 【AI科技】AMD ROCm 6.4 新功能:突破性推理、即插即用容器和模块化部署,可在 AMD Instinct GPU 上实现可扩展 AI
  • [原创](现代Delphi 12指南):[macOS 64bit App开发]: [2]如何使用跨平台消息框?
  • 低代码/AI是否会取代前端开发?
  • C++之类和对象基础
  • 开启 Spring AI 之旅:从入门到实战
  • 【c++】【STL】priority_queue详解
  • 网络原理 - 13(HTTP/HTTPS - 4 - HTTPS)