22、Kubernetes 中 Job 和 CronJob 的使用指南

Kubernetes 中 Job 和 CronJob 的使用指南

1. 引言

在 Kubernetes 里,有时我们需要运行一次性任务或者按特定时间间隔执行任务。虽然独立的 Pod 具备执行一次性任务的能力,但 Job 能提供更强大的功能,确保任务顺利完成。而 CronJob 则可用于按计划定期执行任务。接下来,我们将详细探讨 Job 和 CronJob 的使用方法。

2. Job 的基本概念

Job 是 Kubernetes 中的一种高阶控制器,其作用与 Deployment 和 StatefulSet 类似,都是用于管理 Pod。不过,它们的侧重点有所不同:
- Deployment :用于创建一组持续运行的 Pod。
- StatefulSet :适用于具有唯一序号且可通过持久卷模板挂载磁盘的 Pod。
- Job :用于需要运行至完成(可能多次)的 Pod。

3. 使用 Job 运行一次性任务
3.1 Job 的优势

Job 非常适合运行一次性任务。例如,执行清除缓存等维护任务时,相较于使用 kubectl exec 在现有 Pod 上执行命令,使用 Job 有诸多好处:
- 任务会作为一个独立进程运行,拥有自己的资源,避免与现有 Pod 共享资源,从而影响性能。
- 能确保任务按要求完成,若失败会报告失败状态。
- 方便重复执行。

3.2 配置维护任务为代码

将常规维护任务定义为 Job,而非使用一系列需要复制粘贴的 shell 命令,这样可以构建可重复使用的配置。若采用 GitOps 方法,生产环境的更改通过 Git 进行,那么维护任务也能经过常规的代码审查流程后部署到生产环境。

3.3 创建 Job

以下是一个用于执行 python3 add_tasks.py 任务的 Job 定义示例:

apiVersion: batch/v1
kind: Job
metadata:
  name: addwork
spec:
  backoffLimit: 2
  template:
    spec:
      containers:
      - name: pi
        image: docker.io/wdenniss/pi_worker:v2
        command: ["python3",  "add_tasks.py"]
        env:
        - name: REDIS_HOST
          value: redis-0.redis-service
        - name: PYTHONUNBUFFERED
          value: "1"
      restartPolicy: Never

在这个示例中, backoffLimit 决定了 Job 尝试运行的次数, restartPolicy 则控制着容器失败时是否重启。对于 Job 而言, restartPolicy 可设置为 OnFailure Never Always 选项对 Job 没有意义。

创建并观察 Job 的执行情况:

$ kubectl create -f Chapter10/10.2.1_Job/job_addwork.yaml
$ kubectl get job,pods

若 Job 成功完成,可观察到相关 Pod 的状态变为 Completed 。需要注意的是,若要再次运行同名的 Job,需先将其删除:

$ kubectl delete -f Chapter10/10.2.1_Job/job_addwork.yaml
4. 使用 CronJob 调度任务
4.1 CronJob 的作用

对于需要按固定时间间隔重复执行的任务,Kubernetes 提供了 CronJob。CronJob 封装了 Job 对象,并添加了一个频率参数,允许设置每天、每小时或其他任意时间间隔来运行 Job。

4.2 创建 CronJob

以下是一个 CronJob 的定义示例:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: addwork
spec:
  schedule: "*/5 * * * *"
  jobTemplate:
    spec:
      backoffLimit: 2
      template:
        spec:
          containers:
          - name: pi
            image: docker.io/wdenniss/pi_worker:v2
            command: ["python3",  "add_tasks.py"]
            env:
            - name: REDIS_HOST
              value: redis-0.redis-service
            - name: PYTHONUNBUFFERED
              value: "1"
          restartPolicy: Never

在这个示例中, schedule 字段使用 Unix cron 格式定义任务执行的频率。例如, */5 * * * * 表示每 5 分钟执行一次。

创建并观察 CronJob 的执行情况:

$ kubectl create -f Chapter10/10.2.2_CronJob/cronjob_addwork.yaml
$ kubectl get cronjob,job

等待几分钟后,可查看 CronJob 创建的 Job 及其生成的 Pod:

$ kubectl get cronjob,job,pods
4.3 时区问题

CronJob 会在集群所在的时区运行。对于许多平台(如 GKE),时区通常为 UTC。可通过以下命令检查集群的时区:

$ kubectl run date --restart=Never -it --rm --image ubuntu date +%Z

虽然可以添加 CRON_TZ=<timezone> 前缀,但在 Kubernetes 1.21 版本中,这并非官方 API 合约的一部分,因此不建议使用。

5. 使用 Job 进行批量任务处理
5.1 动态队列处理

若有一个动态工作队列数据库,且希望工作节点在队列为空时完全关闭,Job 是理想的选择。与 Deployment 不同,使用 Job 时,工作节点 Pod 可在工作完成后向 Job 控制器发出信号,从而关闭自身并释放资源。

为了让任务工作节点在 Job 环境中正常工作,我们需要对其进行修改,使其在队列为空时发出成功信号。以下是修改后的代码示例:

import os
import signal
import redis
from pi import *

redis_host = os.environ.get('REDIS_HOST')
assert redis_host != None
r = redis.Redis(host=redis_host, port= '6379', decode_responses=True)
running = True

def signal_handler(signum, frame):
    print("got signal")
    running = False

signal.signal(signal.SIGTERM, signal_handler)
print("starting")

while running:
    job = r.blpop('queue:task', 5)
    if task != None:
        iterations = int(task[1])
        print("got task: " + str(iterations))
        pi = leibniz_pi(iterations)
        print (pi)
    else:
        if os.getenv('COMPLETE_WHEN_EMPTY', '0') != '0':
            print ("no more work")
            running = False

创建一个 Kubernetes Job 来运行这个任务:

apiVersion: batch/v1
kind: Job
metadata:
  name: jobworker
spec:
  backoffLimit: 2
  parallelism: 2
  template:
    spec:
      containers:
      - name: pi
        image: docker.io/wdenniss/pi_worker:v3
        imagePullPolicy: Always
        env:
        - name: REDIS_HOST
          value: redis-0.redis-service
        - name: PYTHONUNBUFFERED
          value: “1”
        - name: COMPLETE_WHEN_EMPTY
          value: “1”
      restartPolicy: Never
5.2 操作步骤
  1. 清理环境 :若之前运行过相关示例,需删除 Deployment 和 CronJob,并重置 Redis 队列。
$ kubectl delete -f 10.1.2_TaskQueue2
$ kubectl delete -f 10.2.1_Job
$ kubectl delete -f 10.2.2_CronJob
kubectl exec -it pod/redis-0 -- redis-cli ltrim queue:task 0 0
  1. 添加工作任务 :使用 Job 向 Redis 队列添加工作任务。
$ kubectl create -f 10.2.1_Job
  1. 运行任务队列 :确保 “addwork” Job 完成后,运行新的 Job 队列处理工作。
$ kubectl get job,pod
6. 总结

Job 和 CronJob 是 Kubernetes 中非常实用的工具,能帮助我们更高效地管理一次性任务和定期任务。通过合理使用这两个工具,我们可以确保任务按要求完成,提高资源利用率。

以下是一个简单的流程图,展示了使用 Job 处理动态队列任务的流程:

graph LR
    A[清理环境] --> B[添加工作任务]
    B --> C{“addwork” Job 完成?}
    C -- 是 --> D[运行任务队列]
    C -- 否 --> B

同时,为了更清晰地对比 Deployment 和 Job 的区别,我们可以列出以下表格:
| 控制器类型 | 适用场景 | 任务完成处理 | 资源管理 |
| ---- | ---- | ---- | ---- |
| Deployment | 持续运行的任务 | 需要额外系统(如 HPA)进行伸缩 | 持续占用资源 |
| Job | 运行至完成的任务 | 工作节点可自行信号完成并关闭 | 工作完成后释放资源 |

7. 静态队列处理与索引作业

除了动态队列处理,Job 还能用于静态工作队列的处理,这种方式甚至无需数据库。假设我们知道队列中有 100 个任务需要处理,就可以运行 Job 100 次。但问题是,Job 系列中的每个 Pod 实例都需要知道要处理这 100 个任务中的哪一个,这就涉及到索引作业的使用。

7.1 索引作业原理

索引作业允许每个 Pod 实例获取唯一的索引,从而明确自己要处理的任务。通过这种方式,我们可以使用一个 Job 对象描述来处理一批任务。

7.2 实现步骤
  1. 定义任务索引 :在 Job 的定义中,为每个 Pod 实例分配一个唯一的索引。可以通过环境变量或其他方式实现。
  2. 修改任务代码 :让任务代码根据分配的索引来确定要处理的具体任务。

以下是一个简单的示例,假设我们有一个包含 100 个任务的列表,每个任务用一个数字表示:

import os

# 获取分配的索引
index = int(os.environ.get('TASK_INDEX'))

# 假设任务列表
task_list = list(range(100))

# 处理对应的任务
task = task_list[index]
print(f"Processing task {task}")

在 Job 的定义中,可以通过环境变量传递索引:

apiVersion: batch/v1
kind: Job
metadata:
  name: static-task-job
spec:
  completions: 100
  parallelism: 10
  template:
    spec:
      containers:
      - name: task-worker
        image: your-task-worker-image
        env:
        - name: TASK_INDEX
          valueFrom:
            fieldRef:
              fieldPath: metadata.annotations['batch.kubernetes.io/job-completion-index']
      restartPolicy: Never

在这个示例中, completions 表示需要完成的任务总数, parallelism 表示同时运行的 Pod 数量。通过 fieldRef 从 Pod 的注解中获取任务索引。

8. 任务处理参数:completions 和 parallelism

在前面的示例中,我们提到了 completions parallelism 这两个参数。这两个参数允许我们使用一个 Job 对象描述来处理一批任务。

8.1 completions 参数

completions 参数指定了 Job 需要完成的任务数量。当所有任务都成功完成后,Job 才会被标记为完成。例如,如果 completions 设置为 100,那么 Job 会确保有 100 个 Pod 成功完成任务。

8.2 parallelism 参数

parallelism 参数控制了同时运行的 Pod 数量。通过调整这个参数,我们可以控制任务的处理速度。例如,如果 parallelism 设置为 10,那么 Job 会同时启动 10 个 Pod 来处理任务。

以下是一个使用这两个参数的示例:

apiVersion: batch/v1
kind: Job
metadata:
  name: batch-task-job
spec:
  completions: 50
  parallelism: 5
  template:
    spec:
      containers:
      - name: batch-worker
        image: your-batch-worker-image
      restartPolicy: Never

在这个示例中,Job 会确保有 50 个任务成功完成,同时最多有 5 个 Pod 同时运行。

9. 注意事项与最佳实践

在使用 Job 和 CronJob 时,有一些注意事项和最佳实践可以帮助我们更好地管理任务。

9.1 Job 重复运行问题

如前文所述,若要再次运行同名的 Job,必须先将其删除。这是因为即使任务完成,Job 对象仍然存在于 Kubernetes 中。因此,在需要重复执行任务时,要注意及时删除已完成的 Job。

9.2 资源管理

合理设置 backoffLimit parallelism 参数,避免资源的过度使用或浪费。例如,在处理大规模任务时,可以适当增加 parallelism 以提高处理速度,但也要注意集群的资源限制。

9.3 错误处理

在任务代码中添加适当的错误处理机制,确保任务在遇到错误时能够正确处理并报告失败。同时,通过 backoffLimit 参数设置合理的重试次数,避免无限重试导致资源浪费。

9.4 日志记录

确保任务代码有详细的日志记录,方便后续的调试和问题排查。可以通过设置 PYTHONUNBUFFERED 等环境变量来确保日志实时输出。

10. 深入理解对象组合

在 Kubernetes 中,Job 和 CronJob 的设计采用了对象组合的方式。CronJob 封装了 Job 对象,而 Job 又封装了 Pod。这种设计方式虽然可能看起来有些复杂,但带来了很大的灵活性。

10.1 对象嵌套关系
  • CronJob :包含一个 jobTemplate ,用于定义要运行的 Job。
  • Job :包含一个 template ,用于定义要创建的 Pod。
  • Pod :包含具体的容器和相关配置。

以下是一个对象组合的示意图:

graph LR
    A[CronJob] --> B[Job]
    B --> C[Pod]
    C --> D[Container]
10.2 好处与应用

这种对象组合的方式使得我们可以在不同的上下文中复用相同的 Pod 配置。例如,同一个 Pod 模板可以在 Job 和 Deployment 中使用。同时,通过修改上层对象的配置,我们可以灵活地控制任务的执行频率和方式。

11. 总结与展望

Job 和 CronJob 为 Kubernetes 用户提供了强大的任务管理能力,无论是一次性任务、定期任务还是批量任务,都能高效地完成。通过合理运用 completions parallelism 等参数,以及遵循最佳实践,我们可以更好地管理任务,提高资源利用率。

未来,随着 Kubernetes 的不断发展,Job 和 CronJob 可能会有更多的功能和优化。例如,更智能的任务调度、更灵活的资源管理等。我们可以持续关注这些发展,进一步提升任务管理的效率。

为了方便大家快速回顾,以下是一个总结表格:
| 工具 | 适用场景 | 关键参数 | 注意事项 |
| ---- | ---- | ---- | ---- |
| Job | 一次性任务、批量任务 | backoffLimit, completions, parallelism | 重复运行需先删除 |
| CronJob | 定期任务 | schedule | 注意时区问题 |

同时,我们可以用一个流程图来总结使用 Job 和 CronJob 的整体流程:

graph LR
    A[确定任务类型] --> B{一次性任务?}
    B -- 是 --> C[使用 Job]
    B -- 否 --> D{定期任务?}
    D -- 是 --> E[使用 CronJob]
    D -- 否 --> F{批量任务?}
    F -- 是 --> G[使用 Job 处理批量任务]
    F -- 否 --> H[其他情况]
    C --> I[配置 Job 参数]
    E --> J[配置 CronJob 参数]
    G --> K[设置 completions 和 parallelism]
    I --> L[创建并运行 Job]
    J --> M[创建并运行 CronJob]
    K --> N[运行批量任务 Job]

通过这个流程图,我们可以清晰地看到根据不同的任务类型选择合适的工具,并进行相应的配置和运行。希望本文能帮助大家更好地理解和使用 Kubernetes 中的 Job 和 CronJob。

内容概要:本文介绍了ENVI Deep Learning V1.0的操作教程,重点讲解了如何利用ENVI软件进行深度学习模型的训练与应用,以实现遥感图像中特定目标(如集装箱)的自动提取。教程涵盖了从数据准备、标签图像创建、模型初始化与训练,到执行分类及结果优化的完整流程,并介绍了精度评价与通过ENVI Modeler实现一键化建模的方法。系统基于TensorFlow框架,采用ENVINet5(U-Net变体)架构,支持通过点、线、面ROI或分类图生成标签数据,适用于多/高光谱影像的单一类别特征提取。; 适合人群:具备遥感图像处理基础,熟悉ENVI软件操作,从事地理信息、测绘、环境监测等相关领域的技术人员或研究人员,尤其是希望将深度学习技术应用于遥感目标识别的初学者与实践者。; 使用场景及目标:①在遥感影像中自动识别提取特定地物目标(如车辆、建筑、道路、集装箱等);②掌握ENVI环境下深度学习模型的训练流程与关键参数设置(如Patch Size、Epochs、Class Weight等);③通过模型调优与结果反馈提升分类精度,实现高效自动化信息提取。; 阅读建议:建议结合实际遥感项目边学边练,重点关注标签数据制作、模型参数配置与结果后处理环节,充分利用ENVI Modeler进行自动化建模与参数优化,同时注意软硬件环境(特别是NVIDIA GPU)的配置要求以保障训练效率。
内容概要:本文系统阐述了企业新闻发稿在生成式引擎优化(GEO)时代下的全渠道策略与效果评估体系,涵盖当前企业传播面临的预算、资源、内容与效果评估四大挑战,并深入分析2025年新闻发稿行业五大趋势,包括AI驱动的智能化转型、精准化传播、首发内容价值提升、内容资产化及数据可视化。文章重点解析央媒、地方官媒、综合门户自媒体四类媒体资源的特性、传播优势与发稿策略,提出基于内容适配性、时间节奏、话题设计的策略制定方法,并构建涵盖品牌价值、销售转化与GEO优化的多维评估框架。此外,结合“传声港”工具实操指南,提供AI智能投放、效果监测、自媒体管理与舆情应对的全流程解决方案,并针对科技、消费、B2B、区域品牌四大行业推出定制化发稿方案。; 适合人群:企业市场/公关负责人、品牌传播管理者、数字营销从业者及中小企业决策者,具备一定媒体传播经验并希望提升发稿效率与ROI的专业人士。; 使用场景及目标:①制定科学的新闻发稿策略,实现从“流量思维”向“价值思维”转型;②构建央媒定调、门户扩散、自媒体互动的立体化传播矩阵;③利用AI工具实现精准投放与GEO优化,提升品牌在AI搜索中的权威性与可见性;④通过数据驱动评估体系量化品牌影响力与销售转化效果。; 阅读建议:建议结合文中提供的实操清单、案例分析与工具指南进行系统学习,重点关注媒体适配性策略与GEO评估指标,在实际发稿中分阶段试点“AI+全渠道”组合策略,并定期复盘优化,以实现品牌传播的长期复利效应。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值