暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Kubernetes 模式:Cronjob模式

云原生CTO 2021-09-16
328

 CTO 

               

「【只做懂你de云原生干货知识共享】」

Kubernetes 模式:Cronjob模式

从早期版本开始,Cronjob就是 UNIX 系统的一部分。当 GNU 和 Linux 出现时,cron 已经是系统的一部分。cron job只是计划定期运行的命令、程序或 shell 脚本。例如,一个自动执行日志轮换的程序必须定时运行(每天、每周、每月等)。

但是,随着应用程序规模的增长和需要高可用性,我们也需要我们的 cronjob具有高可用性。这种方法可能面临以下挑战:

「1」 如果我们有多个节点托管应用程序以获得高可用性,哪个节点处理 cron?

「2」 如果多个相同的 cronjob同时运行会发生什么?

应对这些挑战的一种可能解决方案是创建一个更高级别的“控制器”来管理 cronjob。控制器安装在每个节点上,并选举出一个领导节点。领导节点是唯一可以执行 cronjob的节点。如果该节点宕机,则选举另一个节点。

但是,您需要通过第三方供应商安装此控制器或编写自己的控制器。幸运的是,您可以使用 Kubernetes CronJob 控制器来执行周期性任务,这为传统的 Job 控制器增加了一个时间维度。在本文中,我们将演示 CronJob 类型、它的用例以及它解决的问题类型。

Cronjob示例
apiVersion: batch/v1beta1
kind: CronJob
metadata:
 name: sender
spec:
 schedule: "*/15 * * * *"
 jobTemplate:
   spec:
     template:
       spec:
         containers:
         - image: bash
           name: sender
           command: ["bash","-c","echo 'Sending information to API/database'"]
         restartPolicy: OnFailure

复制

上述定义文件的目的是创建一个 CronJob 资源,每十五分钟向 API 或数据库发送数据。我们使用 bash Docker 镜像中的 echo 命令来模拟发送操作以保持示例简单。让我们看看这个定义中的关键属性:

.spec.schedule(第 6 行):schedule 参数定义了job应该运行的频率。它使用与 Linux 相同的 cron 格式。如果您不熟悉 cron 格式,这很简单。我们有五个时段:分钟、小时、天、月和星期几。如果我们想忽略其中一个(例如,在所有月份运行),我们在插槽 (*) 中放置一颗星。

您还可以使用 * / 符号来表示“每 x 个单位”。在我们的示例中,* /15 表示每 15 分钟,剩余的槽有 *,因此它将在所有小时、所有天、所有月和一周中的所有天运行。

与 Job 资源一样,CronJob 使用 Pod 模板来定义该 Pod 托管的容器以及这些容器的规格(镜像、启动命令等)。

.spec.jobTemplate.spec.template.spec.restartPolicy
(第 15 行)定义是否重新启动job。您可以将此值设置为 Never 或 OnFailure。

我的 Cronjob没有按时开始。我该怎么办?

在某些情况下,CronJob 可能不会在指定时间触发。在这种情况下,有两种情况:

「1」 我们需要执行即使延迟也没有启动的job。只有在没有超过特定时间限制的情况下,我们才需要执行未启动的job。

「2」 在我们的第一个示例中,job向 API 发送信息,该 API 每十五分钟需要一次此信息。如果数据迟到,则无用,API 会自动丢弃它。CronJob 资源提供了。规格 startDeadlineSeconds 参数:

.spec.startingDeadlineSeconds
:如果job错过了预定时间并且没有超过该秒数,它应该被执行。否则,在下一个预定时间执行。

请注意,如果未设置此参数,则 CronJob 会计算自上次成功执行以来所有错过的job,并重新安排它们,最多 100 个错过的job。如果丢失的job数超过 100,则不会重新安排 cronjob。

我的 Cronjob花费了很长时间,以至于它会跨越到下一次执行时间

如果 CronJob 需要很长时间才能完成,您可能会遇到另一个job实例在其预定时间启动的情况。CronJob 资源提供了。规范并发策略。此参数为您提供以下选项:

「1」 concurrencyPolicy:
始终允许运行同一 CronJob 的并发实例。这是默认行为。

「2」concurrencyPolicy:
Replace 如果当前job尚未完成,则将其杀死并启动新调度的job。

「3」concurrencyPolicy:
在不希望杀死正在运行的job时禁止;在开始一个新的之前,我们需要让它完成。

我只需要执行一次 Cronjob

在 Linux 中,我们有 at 命令。at 命令允许您安排程序完成但只能完成一次。可以使用 Kubernetes 上的 CronJob 资源来实现此功能。spec.suspend 参数。

.spec.suspend:将其设置为true,此参数会暂停所有后续的CronJob 执行。但是,请注意,您还必须与它一起使用 startingDeadlineSeconds
。原因是如果您将 suspend 值更改为 false,Kubernetes 会检查所有由于 suspend 参数打开而未执行的错过的job。如果job计数小于 100,它们将被执行。使用startingDeadlineSeconds
设置,您可以避免这种行为,因为它可以防止错过的job在超过定义的秒数时被执行。

Cron Job 是否保留了成功和失败的工作历史?

大多数情况下,您需要知道 cronjob上次运行时发生了什么。如果未发生数据库更新、未更新 API 服务器或由于 CronJob 运行而应发生的任何其他操作,您需要知道原因。默认情况下,CronJob 会记住最后三个成功的job和最后一个失败job。但是,可以通过设置以下参数根据您的喜好更改这些值:

spec.successfulJobsHistoryLimit:
如果未设置,则默认为 3。它指定要保留在历史记录中的成功job数。spec.failedJobsHistoryLimit
:如果未设置,则默认为 1。它指定要保留在历史记录中的失败job数。如果您不需要保留任何执行历史,您可以将两个值都设置为 0。

结论

Cronjob可以追溯到 UNIX 和 Linux 的悠久历史。与其他 Kubernetes 技术(如 Pod、容器、调度程序以及用于 Pod 放置和健康探测的智能算法)相结合,CronJobs 被证明比传统的操作系统级对应物更强大。

由于它们在容器上运行,CronJobs 为开发人员提供了很大的灵活性。他们不必担心 cronjob在哪个平台上运行,以及所需的依赖项的存在,因为一切都在容器上运行。

Kubernetes 处理 CronJob 执行,当它错过执行时间时会发生什么,以及job应该运行多少次。这使开发人员可以更专注于编写代码和解决业务问题,而不是担心代码执行的内部结构。

业务应用程序仍负责处理 cronjob运行、未运行、取消或并发运行时发生的情况。


文章转载自云原生CTO,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论