【问题标题】:how to have only one Pod created for/by Cronjob如何只为/由 Cronjob 创建一个 Pod
【发布时间】:2022-01-06 10:13:42
【问题描述】:

我在凌晨 2 点运行这个 Cronjob:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: postgres-backup
spec:
  # Backup the database every day at 2AM
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: postgres-backup
            image: postgres:10.4
            command:
            - "/bin/sh"
            - -c
            - |
              pg_dump -Fc -d postgresql://$DBUSER:$DBPASS@$DBHOST:$DBPORT/$DBNAME > /var/backups/backup_$(date +"%d-%m-%Y_%H-%M").bak;
            env:
            - name: DBHOST
              valueFrom:
                configMapKeyRef:
                  name: dev-db-config
                  key: db_host
            - name: DBPORT
              valueFrom:
                configMapKeyRef:
                  name: dev-db-config
                  key: db_port
            - name: DBNAME
              valueFrom:
                configMapKeyRef:
                  name: dev-db-config
                  key: db_name
            - name: DBUSER
              valueFrom:
                secretKeyRef:
                  name: dev-db-secret
                  key: db_username
            - name: DBPASS
              valueFrom:
                secretKeyRef:
                  name: dev-db-secret
                  key: db_password
            volumeMounts:
            - mountPath: /var/backups
              name: postgres-backup-storage
          - name: postgres-restore
            image: postgres:10.4
            volumeMounts:
            - mountPath: /var/backups
              name: postgres-backup-storage
          restartPolicy: OnFailure
          volumes:
          - name: postgres-backup-storage
            hostPath:
            # Ensure the file directory is created.
              path: /var/volumes/postgres-backups
              type: DirectoryOrCreate

作业已成功执行,但我不喜欢的是每次作业执行都会创建一个新 Pod:

有没有办法清理以前(旧)创建的 Pod? 或者也许有办法每次都重新运行同一个 Pod/Job?

【问题讨论】:

    标签: kubernetes kubernetes-cronjob kyma


    【解决方案1】:

    有两种方法可以解决这个问题

    第一种方法,有工作规范

    将 Job 的 .spec.activeDeadlineSeconds 字段添加到秒数。 activeDeadlineSeconds 适用于作业的持续时间

    一旦 Job 达到 activeDeadlineSeconds,其所有正在运行的 Pod 都将终止,并且 Job 状态将变为 type: Failed with reason: DeadlineExceeded。

    将 activeDeadlineSeconds 设置为比预期的运行时间长得多

    第二种方法,用吊舱

    制作 pod 以便在作业完成时自行终止。类似于将命令更改为

    pg_dump -Fc -d postgresql://$DBUSER:$DBPASS@$DBHOST:$DBPORT/$DBNAME > /var/backups/backup_$(date +"%d-%m-%Y_%H-%M").bak; exit
    

    【讨论】:

    • 此解决方案确实会清理/删除 Pod,但作业仍然存在。有没有办法删除作业本身?因为当 Job 被删除时,所有依赖的 Pod 也会被自动删除。
    【解决方案2】:

    您可以尝试设置ttlSecondsAfterFinished,了解更多尝试:

    kubectl explain cronjob.spec.jobTemplate.spec.ttlSecondsAfterFinished --api-version=batch/v1beta1
    

    ttlSecondsAfterFinished 限制已完成作业的生命周期 执行(完成或失败)。如果设置了这个字段, Job 完成后 ttlSecondsAfterFinished 有资格成为 自动删除。当 Job 被删除时,它的生命周期 保证(例如终结者)将被兑现。如果未设置此字段,则 作业不会被自动删除。如果此字段设置为零,则作业 完成后立即有资格被删除。这个字段是 alpha 级别,仅由启用 TTLAfterFinished 的服务器支持 功能。

    很快,CronJob 创建的Job 将在指定秒后被删除。


    在你的情况下:

    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
      name: postgres-backup
    spec:
      # Backup the database every day at 2AM
      schedule: "0 2 * * *"
      jobTemplate:
        spec:
          template:
            spec:
              ttlSecondsAfterFinished: 60 # after 1 minute the job and the pods will be deleted by kubernetes
    ...
    

    请注意,如果作业成功终止,将应用ttlSecondsAfterFinished

    【讨论】:

    • 这将是一个很好的解决方案,因为它还可以清理作业本身,但是该功能仅在 Kubernetes v1.21 及更高版本中可用,并且仍处于测试阶段,不幸的是我正在使用旧版本不止于此。
    • 有趣,我在 v1.15.11 上使用它,它可以工作,可能我们的集群上安装了 TTL 控制器。
    • 但它是删除 Job 还是只删除 Pod,但 Job 仍然存在?
    • AFAIK,它会删除作业和 pod。当然,CronJob 仍然存在
    【解决方案3】:

    如果只需要保留最后一个作业和 pod,可以使用 .spec.successfulJobsHistoryLimit 字段设置为 1

    这样只会保留最后一个作业和相应的 pod。默认情况下,它设置为3。也可以将此值设置为0,cronjob 执行后不会保存任何内容。

    同样的逻辑有.spec.failedJobsHistoryLimit字段,默认有1

    jobs history limits


    这是我从 cronjob 获取事件时的样子:

    $ kubectl describe cronjob test-cronjob
    ...
    Events:
      Type    Reason            Age    From                Message
      ----    ------            ----   ----                -------
      Normal  SuccessfulCreate  2m31s  cronjob-controller  Created job test-cronjob-27304493
      Normal  SawCompletedJob   2m30s  cronjob-controller  Saw completed job: test-cronjob-27304493, status: Complete
      Normal  SuccessfulCreate  91s    cronjob-controller  Created job test-cronjob-27304494
      Normal  SawCompletedJob   90s    cronjob-controller  Saw completed job: test-cronjob-27304494, status: Complete
      Normal  SuccessfulDelete  90s    cronjob-controller  Deleted job test-cronjob-27304493
      Normal  SuccessfulCreate  31s    cronjob-controller  Created job test-cronjob-27304495
      Normal  SawCompletedJob   30s    cronjob-controller  Saw completed job: test-cronjob-27304495, status: Complete
      Normal  SuccessfulDelete  30s    cronjob-controller  Deleted job test-cronjob-27304494
    

    只显示最后一项工作:

    $ kubectl get jobs
    NAME                    COMPLETIONS   DURATION   AGE
    test-cronjob-27304496   1/1           1s         3s
    

    还有一个吊舱:

    $ kubectl get pods
    NAME                               READY   STATUS      RESTARTS   AGE
    test-cronjob-27304496-r4qd8        0/1     Completed   0          38s
    

    【讨论】:

    • 这个解决方案看起来是解决我的问题的最可行的选择。但是我注意到我的作业永远不会完成也不会失败,因为 Pod 始终处于“未就绪”状态。发生这种情况是因为“postgres-backup”容器在执行后终止,因为它已成功完成。你知道吗,有没有办法“手动”设置容器的就绪状态?
    • @f.bele 好吧,我注意到根据标签您有istio,我尝试将它与istio 一起使用并得到相同的结果。发生的情况是创建了 pod,注入了 istio sidecar,带有 postrgres 的容器已完成,但 istio 的 sidecar 容器仍在运行。这就是为什么 pod 是 notReady。一种选择是避免将istio sidecar 容器注入到作业创建的 Pod 中。可以在具有sidecar.istio.io/inject: "false" 值的cronjob 中使用template.metadata.annotations 完成。所以此时的问题是关于“如何处理 istio”
    • 你是对的,我们使用istio。我尝试了您的解决方案,我放置您的解决方案的完整路径是spec.jobTemplate.spec.template.metadata.annotations,然后是您建议的值sidecar.istio.io/inject: "false"。不幸的是,在此之后 Pod 崩溃并立即终止,但作业仍然存在。
    • 我建议asking another question,因为这是一个完全不同的问题。此设置仅保留 1 个作业和相应的 pod。至于使用 istio 完成作业,您需要提供所有详细信息:使用的 istio 版本、作业规范(您可以从 simple test cronjob 开始)、日志、事件以及有助于理解为什么会发生这种情况的所有内容。因为在我在 GKE 上的测试台中,此选项可以正常工作,所以不会向该 pod 注入边车。
    • the 5th point。这就是它应该的样子。 + 其他要检查的潜在选项。它可以是我们不知道的其他依赖项或 istio 配置。
    猜你喜欢
    • 2022-01-28
    • 2021-05-12
    • 2019-07-15
    • 2019-08-08
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 2019-07-15
    • 2020-09-13
    相关资源
    最近更新 更多