1

基本上我的 cron 每 2 分钟更新一次数据库。但我需要运行另一个每 24 小时更新一次数据库的 cron。我需要确保在第二个 cron(每天)运行时没有竞争条件,即两个 cron 不能一起运行并重叠。这需要在 Kubernetes 集群中使用作业来实现。
我的解决方案是每 2 分钟运行一次第一个 cron,但在第二个 cron 运行时(每天)延迟 5 分钟。
欢迎任何替代解决方案。

4

1 回答 1

0

我试图考虑一些可能性,但事情可能会出错,主要是因为你有一份工作需要每 2 分钟运行一次,让我们假设你的日常工作出于任何原因花费的时间比你预期的要多,一份新的 2 分钟工作将开始,这不可能发生。

最好的解决方案是在代码级别解决这个问题。您可以在应用程序中创建一个锁,以防止这些作业同时运行。

如果您真的无法在代码中提出任何解决方案来解决此问题,那么 Kubernetes 上有一种机制可以阻止来自同一个 cronjob 的新作业启动。您可以设置标志spec.concurrencyPolicy: Forbid因此如果您的作业启动时间超过 2 分钟,则将跳过新作业。这不是全局标志,这仅适用于每个 cronjob。

您可以使用spec.initContainers聚合这种可能性,并找到一种方法在同一个 cronjob 中运行这两个任务。

spec.initContainers 是在应用容器之前运行的专用容器。

这是一个例子:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  concurrencyPolicy: Forbid
  schedule: "*/2 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          initContainers
          - name: hello1
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          containers:
          - name: hello2
            image: busybox
            args:
            - /bin/sh
            - -c
            - DATE=`date +"%H:%M"`; if [[ $DATE == "00:00" ]]; then date; echo Hello from the Kubernetes cluster; fi
          restartPolicy: OnFailure

此清单定义了一个 cronJob,它将每 2 分钟运行一次,并将启动一个 initContainer(您的 2 分钟作业),并且还将每 2 分钟运行第二个容器。问题是在第二个容器中,我们有一个 shell 脚本检查它是否是午夜(忽略秒,因为我们不能确定它什么时候开始)。

您可能需要调整这部分代码:

DATE=`date +"%H:%M"; if [[ $DATE == "00:00" ]

假设您的第一个容器执行时间超过一分钟,它将是 00:01,您的第二个作业将永远不会执行。

让我知道这些信息和解决方案是否对您有所帮助。

于 2020-03-20T13:51:34.273 回答