【问题标题】:Prevent two jobs from running in parallel in Kubernetes防止两个作业在 Kubernetes 中并行运行
【发布时间】:2020-10-14 19:26:03
【问题描述】:

ATT:我不知道为什么,但有时一个 pod 突然将状态变为未知,这就是新 pod 开始的地方

我在 gcloud 中使用 kubernetes。

我为需要运行的 cron 作业构建了 yaml 文件:

apiVersion: batch/v1beta1
kind: CronJob
metadata: 
  name: etl-table-feed-from-schema-vtex-to-schema-sale-all
spec:
  schedule: "* * * * *"
  concurrencyPolicy: "Forbid"
  failedJobsHistoryLimit: 3
  successfulJobsHistoryLimit: 1
  startingDeadlineSeconds: 60 # 1 min
  jobTemplate:
    spec:
      backoffLimit: 0
      #activeDeadlineSeconds: 3600 # 1 hora
      template:
        spec:
          containers:
            - name: etl-table-feed-from-schema-vtex-to-schema-sale-all
              image: (myimage)
              command: ["/bin/sh", "-c"]
              args: (mycommands)
              env:
              - name: PYTHONUNBUFFERED
                value: "1"
              envFrom:
              - secretRef:
                  name: etl-secret
          restartPolicy: Never
          nodeSelector:
        #<labelname>:value
            etlnode: etl-hi-cpu

我一次只需要运行一个 pod,就一个。但有时,我不知道为什么,而且我无法重现,一次运行多个 pod。

我已经把concurrencyPolicy写成了Forbid,但是好像还不够。

我在 gcloud 的抢占式池中运行它。

同时运行的两个 pod:

【问题讨论】:

  • Pods/Jobs 状态如何?他们是成功完成还是有任何错误?您使用的是哪个 GKE 版本?
  • 你能检查一下你没有 2 个相等的 cronjobs 吗?
  • 它们停止运行后不会出现在 kubectl get pods 命令中。我只能在 gcloud 的审核日志中查看这些 pod。在那里我看到一次有两个豆荚在运行。只有一个 cronjob。我认为这是版本:1.14.10-gke.36
  • 我有同样的用例,每分钟运行一个作业。在我的情况下,似乎当一个工作被标记为 DeadlineExceeded 时,下一个工作立即开始,在前一个 Pod 终止之前......
  • 如果作业每分钟都在运行,则它不是 cronjob。这是一个守护进程。这样设置。

标签: kubernetes google-kubernetes-engine gcloud kubernetes-cronjob


【解决方案1】:

您设置了schedule: "* * * * *",这意味着每分钟都会创建一个作业。

concurrencyPolicy: "Forbid" 正在按描述工作。

cron 作业不允许并发运行;如果是运行新作业的时间,而之前的作业运行尚未完成,则 cron 作业会跳过新作业的运行

意思是,如果还有未完成工作,则不允许创建新工作。如果工作完成,那么concurrencyPolicy 将允许创建另一个。它不允许运行 2 个未完成的作业。

activeDeadlineSeconds: 根据Kubernetes docs

activeDeadlineSeconds 适用于作业的持续时间,无论创建了多少 Pod。一旦 Job 达到 activeDeadlineSeconds,其所有正在运行的 Pod 都将终止,并且 Job 状态将变为 type: Failed with reason: DeadlineExceeded。

也如Jobs cleanup policy中所述。

如果 Job 由更高级别的控制器直接管理,例如 CronJobs,则可以由 CronJobs 根据指定的基于容量的清理策略来清理 Job。

为了测试我使用了busyboxsleep 20 命令,因为我不知道你的工作在做什么。

意思是,如果你保持默认设置

spec:
  failedJobsHistoryLimit: 3
  successfulJobsHistoryLimit: 1

它将保留successful 作业直到创建下一个作业,如果您想检查日志等,它将保留一段时间。

$ kubectl get cronjob,job,pod
NAME                                                               SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all   * * * * *   False     1        17s             51s

NAME                                                                      COMPLETIONS   DURATION   AGE
job.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all-1593018780   0/1           14s        14s

NAME                                                                  READY   STATUS    RESTARTS   AGE
pod/etl-table-feed-from-schema-vtex-to-schema-sale-all-1593018h9pnh   1/1     Running   0          13s
---
$ kubectl get cronjob,job,pod
NAME                                                               SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all   * * * * *   False     1        33s             2m7s

NAME                                                                      COMPLETIONS   DURATION   AGE
job.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all-1593018780   1/1           23s        90s
job.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all-1593018840   1/1           21s        29s

NAME                                                                  READY   STATUS      RESTARTS   AGE
pod/etl-table-feed-from-schema-vtex-to-schema-sale-all-1593018h9pnh   0/1     Completed   0          89s
pod/etl-table-feed-from-schema-vtex-to-schema-sale-all-1593018k7b58   0/1     Completed   0          29s
---
$ kubectl get cronjob,job,pod
NAME                                                               SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all   * * * * *   False     0        34s             2m8s

NAME                                                                      COMPLETIONS   DURATION   AGE
job.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all-1593018840   1/1           21s        30s

NAME                                                                  READY   STATUS      RESTARTS   AGE
pod/etl-table-feed-from-schema-vtex-to-schema-sale-all-1593018k7b58   0/1     Completed   0          30s

但是,如果您将 successfulJobsHistoryLimit 设置为 0,它将在一段时间后删除作业,甚至在下一个计划作业之前。

spec:
  failedJobsHistoryLimit: 3
  successfulJobsHistoryLimit: 0

输出:

$ kubectl get cronjob,job,pod
NAME                                                               SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all   * * * * *   False     1        18s             31s

NAME                                                                      COMPLETIONS   DURATION   AGE
job.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all-1593018540   0/1           15s        15s

NAME                                                                  READY   STATUS    RESTARTS   AGE
pod/etl-table-feed-from-schema-vtex-to-schema-sale-all-15930182r5bn   1/1     Running   0          15s
---
$ kubectl get cronjob,job,pod
NAME                                                               SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all   * * * * *   False     1        31s             44s

NAME                                                                      COMPLETIONS   DURATION   AGE
job.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all-1593018540   1/1           22s        28s

NAME                                                                  READY   STATUS      RESTARTS   AGE
pod/etl-table-feed-from-schema-vtex-to-schema-sale-all-15930182r5bn   0/1     Completed   0          28s
---
$ kubectl get cronjob,job,pod
NAME                                                               SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/etl-table-feed-from-schema-vtex-to-schema-sale-all   * * * * *   False     0        34s             47s

这个时间也取决于工作持续时间。

此外,如果作业成功完成(退出代码 0),则 pod 将状态更改为已完成,并且不再使用 cpu/内存资源。

您还可以阅读有关TTL Mechanism 的信息,但不幸的是,我认为它不会在这里工作,因为 Master 由 google 管理,并且此功能需要在 Kubelet Feature Gates 中添加一些标志。

【讨论】:

    【解决方案2】:

    就我而言,问题在于concurrencyPolicy: "Forbid"activeDeadlineSeconds 还不够。我之前的 pod 收到了SIGTERM,但在它实际被杀死之前又继续运行了 30 秒,所以我最终得到了两个并行运行 30 秒的作业。

    看到这个问题:Kubernetes Cron Job Terminate Pod before creation of next schedule,在我的情况下,这个答案提供了解决方案:https://stackoverflow.com/a/63721120/5868044。两种选择:

    1. 让 pod 在 SIGTERM 上立即停止(例如,使用 bash trap 'exit' SIGTERM
    2. 通过设置比计划间隔更小的activeDeadlineSeconds,在作业之间留出 30 多秒的时间间隔。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-07
      • 1970-01-01
      • 1970-01-01
      • 2019-02-16
      • 2023-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多