6

我有一个在 GKE 上运行并运行 Cucumber JVM 测试的 Kubernetes Cronjob。如果由于断言失败、某些资源不可用等原因导致 Step 失败,Cucumber 会正确抛出异常,导致 Cronjob 作业失败,并且 Kubernetes pod 的状态更改为ERROR. 这会导致创建一个新的 pod,它会再次尝试运行相同的 Cucumber 测试,但会再次失败并再次重试。

我不希望任何这些重试发生。如果 Cronjob 作业失败,我希望它保持失败状态并且根本不重试。基于,我已经尝试过设置backoffLimit: 0with restartPolicy: Neverin combination with concurrencyPolicy: Forbid,但它仍然通过创建新的 pod 并再次运行测试来重试。

我错过了什么?这是我的 Cronjob 的 kube 清单:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: quality-apatha
  namespace: default
  labels:
    app: quality-apatha
spec:
  schedule: "*/1 * * * *"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      backoffLimit: 0
      template:
        spec:
          containers:
            - name: quality-apatha
              image: FOO-IMAGE-PATH
              imagePullPolicy: "Always"
              resources:
                limits:
                  cpu: 500m
                  memory: 512Mi
              env:
                - name: FOO
                  value: BAR
              volumeMounts:
                - name: FOO
                  mountPath: BAR
              args:
                - java
                - -cp
                - qe_java.job.jar:qe_java-1.0-SNAPSHOT-tests.jar
                - org.junit.runner.JUnitCore
                - com.liveramp.qe_java.RunCucumberTest
          restartPolicy: Never
          volumes:
            - name: FOO
              secret:
                secretName: BAR

我可以使用其他 KubernetesKind来停止重试吗?

谢谢!

4

1 回答 1

12

为了使事情尽可能简单,我使用官方 kubernetes 文档中的这个示例对其进行了测试,对其进行了微小的修改以说明在不同场景中实际发生的情况。

我可以确认 whenbackoffLimit设置为0restartPolicytoNever 一切都按预期工作,并且没有重试。请注意,Job在您的示例中计划以60 秒( )的间隔运行的每次运行都不会被视为重试schedule: "*/1 * * * *"

让我们仔细看看下面的例子(base yamlavialable here):

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      backoffLimit: 0
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - non-existing-command
          restartPolicy: Never

every 60 seconds它会根据生成新的 cron 作业schedule,无论它是失败还是成功运行。在此特定示例中,它被配置为在我们尝试运行时失败non-existing-command

您可以通过运行检查发生了什么:

$ kubectl get pods
NAME                     READY   STATUS              RESTARTS   AGE
hello-1587558720-pgqq9   0/1     Error               0          61s
hello-1587558780-gpzxl   0/1     ContainerCreating   0          1s

如您所见,没有重试。虽然第一个Pod失败了,但根据我们的规范,新的会在 60 秒后准确生成。我想再次强调一下。这不是重试。

另一方面,当我们修改上面的例子并设置backoffLimit: 3时,我们可以观察到重试。如您所见,现在新Pods创建的频率比每 60 秒创建的频率高得多。这是重试。

$ kubectl get pods
NAME                     READY   STATUS   RESTARTS   AGE
hello-1587565260-7db6j   0/1     Error    0          106s
hello-1587565260-tcqhv   0/1     Error    0          104s
hello-1587565260-vnbcl   0/1     Error    0          94s
hello-1587565320-7nc6z   0/1     Error    0          44s
hello-1587565320-l4p8r   0/1     Error    0          14s
hello-1587565320-mjnb6   0/1     Error    0          46s
hello-1587565320-wqbm2   0/1     Error    0          34s

上面我们可以看到与job相关的3 次重试Pod创建尝试)和与hello-1587565260 job相关的4 次重试(包括未计入的原始第一次尝试backoffLimit: 3)。hello-1587565320

如您所见,作业本身仍按计划运行,间隔为 60 秒

kubectl get jobs
NAME               COMPLETIONS   DURATION   AGE
hello-1587565260   0/1           2m12s      2m12s
hello-1587565320   0/1           72s        72s
hello-1587565380   0/1           11s        11s

但是由于我们backoffLimit将这个时间设置为3,每次Pod负责运行作业的负责人失败时,都会发生 3 次额外的重试

我希望这有助于消除有关cronJobskubernetes中运行的任何可能的困惑。

如果您对只运行一次而不是定期运行某些东西感兴趣,请查看简单的Job而不是CronJob.

如果您仍想定期运行此特定作业,也可以考虑更改您的Cron配置,但假设是 24 小时一次,而不是每分钟一次。

于 2020-04-22T15:01:09.780 回答