【问题标题】:How to automatically remove completed Kubernetes Jobs created by a CronJob?如何自动删除由 CronJob 创建的已完成 Kubernetes 作业?
【发布时间】:2017-05-14 02:46:03
【问题描述】:

除了制作 CronJob 来清理已完成的 Jobs 之外,还有其他方法可以自动删除已完成的 Jobs 吗?

K8s Job Documentation 声明已完成作业的预期行为是让它们保持已完成状态,直到手动删除。因为我每天通过 CronJobs 运行数千个作业,我不想保留已完成的作业。

【问题讨论】:

    标签: kubernetes cron kubernetes-cronjob kubernetes-jobs


    【解决方案1】:

    您现在可以设置历史记录限制,或完全禁用历史记录,这样失败或成功的 CronJobs 不会被无限期保留。见我的回答here。文档是here

    设置history limits

    .spec.successfulJobsHistoryLimit.spec.failedJobsHistoryLimit 字段是可选的。这些字段指定应保留多少已完成和失败的作业。默认情况下,它们分别设置为 3 和 1。将限制设置为 0 对应于在完成后不保留相应类型的作业。

    限制为 0 的配置如下所示:

    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
      name: hello
    spec:
      schedule: "*/1 * * * *"
      successfulJobsHistoryLimit: 0
      failedJobsHistoryLimit: 0
      jobTemplate:
        spec:
          template:
            spec:
              containers:
              - name: hello
                image: busybox
                args:
                - /bin/sh
                - -c
                - date; echo Hello from the Kubernetes cluster
              restartPolicy: OnFailure
    

    【讨论】:

    • 有没有办法设置历史的时间限制,比如一周后删除成功的作业?
    • 我不知道,抱歉。如果您找到方法,请在此处发布后续信息。据推测,我想您可以编写一个 cron 作业,查看旧的 pod 时间戳,然后逐个删除超过 X 天的。
    • 是的,我在 kubernetes 中创建了一个部署,一个 golang 项目,创建了一个通道来监听 pod 列表并观察状态的变化..
    • 请注意,链接的答案仅适用于 CronJob 对象(提问者提到的),但不适用于 Job 对象。
    • 也许也看看here,看起来有可能定义一个ttlSecondsAfterFinished“将级联删除作业,即删除其依赖对象,例如Pods,连同作业"
    【解决方案2】:

    这在 1.12 Alpha 版中可以使用ttlSecondsAfterFinished。来自Clean Up Finished Jobs Automatically的例子:

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: pi-with-ttl
    spec:
      ttlSecondsAfterFinished: 100
      template:
        spec:
          containers:
          - name: pi
            image: perl
            command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
          restartPolicy: Never
    

    【讨论】:

    • Note that this TTL mechanism is alpha, with feature gate TTLAfterFinished这个功能门部分我没看懂。
    • Feature gates 是启用或禁用 Kubernetes 功能的标志。我不知道如何设置它们,或者即使您有能力使用像 EKS 这样的托管服务来设置它们。我怀疑您也必须配置主节点,但我在推测。 @technazi
    • 谢谢@rath!是的,当我通过 helm 模板配置作业和 pod 时,我看不到可以配置功能门的地方,因此我无法使用 alpha 改进,基本上说ttlSecondsAfterFinished 没有功能没有效果大门。
    【解决方案3】:

    我发现下面的工作

    要删除失败的作业:

    kubectl delete job $(kubectl get jobs | awk '$3 ~ 0' | awk '{print $1}')
    

    要删除已完成的作业:

    kubectl delete job $(kubectl get jobs | awk '$3 ~ 1' | awk '{print $1}')
    

    【讨论】:

    • 我必须更新命令才能让它工作:kubectl delete jobs $(kubectl get jobs | awk '$2 ~ 1/1' | awk '{print $1}')
    • 如果没有完成的作业要删除,这个不会失败:kubectl get jobs | awk '$2 ~ "1/1" {print $1}' | xargs kubectl delete job
    【解决方案4】:

    另一种方式using a field-selector

    kubectl delete jobs --field-selector status.successful=1 
    

    这可以在 cronjob 中执行,类似于其他答案。

    1. 创建一个服务帐户,例如my-sa-name
    2. 为资源作业创建具有列表和删除权限的角色
    3. 在服务帐户中附加角色(角色绑定)
    4. 创建一个将使用服务帐户的 cronjob 来检查已完成的作业并删除它们
    # 1. Create a service account
    
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: my-sa-name
      namespace: default
    
    ---
    
    # 2. Create a role
    
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      namespace: default
      name: my-completed-jobs-cleaner-role
    rules:
    - apiGroups: [""]
      resources: ["jobs"]
      verbs: ["list", "delete"]
    
    ---
    
    # 3. Attach the role to the service account
    
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: my-completed-jobs-cleaner-rolebinding
      namespace: default
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: my-completed-jobs-cleaner-role
    subjects:
    - kind: ServiceAccount
      name: my-sa-name
      namespace: default
    
    ---
    
    # 4. Create a cronjob (with a crontab schedule) using the service account to check for completed jobs
    
    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
      name: jobs-cleanup
    spec:
      schedule: "*/30 * * * *"
      jobTemplate:
        spec:
          template:
            spec:
              serviceAccountName: my-sa-name
              containers:
              - name: kubectl-container
                image: bitnami/kubectl:latest
                # I'm using bitnami kubectl, because the suggested kubectl image didn't had the `field-selector` option
                command: ["sh", "-c", "kubectl delete jobs --field-selector status.successful=1"]
              restartPolicy: Never
    
    

    【讨论】:

    • 您能否添加一个示例,说明如何创建具有所需权限的服务帐户?
    • 谢谢!我只需要将角色更改为: - apiGroups: ["batch"]
    【解决方案5】:

    我正在使用wernight/kubectl 的 kubectl 镜像

    安排了一个 cron 删除任何内容

    • completed
    • 2 - 9 days old(所以我有 2 天的时间来审查任何失败的工作)

    它每 30 分钟运行一次,所以我没有考虑 10 天以上的工作

    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
      name: cleanup
    spec:
      schedule: "*/30 * * * *"
      jobTemplate:
        spec:
          template:
            spec:
              containers:
              - name: kubectl-runner
                image: wernight/kubectl
                command: ["sh", "-c", "kubectl get jobs | awk '$4 ~ /[2-9]d$/ || $3 ~ 1' | awk '{print $1}' | xargs kubectl delete job"]
              restartPolicy: Never
    

    【讨论】:

    • 对于您的 awk 命令,您不希望您的第二个条件是 $2 ~ /^1/ 而不是 $3 ~ 1 吗?我假设您正在查看第二列的完成列,至少对我而言,完成列打印为0/11/1,因此获取第一个字符很重要。也许kubectl get job 的输出不同。
    • 您也可以将两个awk 命令合二为一。我测试了以下内容,它将作为上述 awk 组件的替代品:awk '$4 ~ /^[2-9]d/ || $2 ~ /^1/ {print $1}'
    • 这是否需要集群角色绑定才能正确删除已完成的作业?
    【解决方案6】:

    我最近构建了一个 kubernetes-operator 来完成这项任务。

    部署后,它将监控选定的命名空间并删除已完成的作业/pod,如果它们完成且没有错误/重新启动。

    https://github.com/lwolf/kube-cleanup-operator

    【讨论】:

    【解决方案7】:

    使用 jsonpath:

    kubectl delete job $(kubectl get job -o=jsonpath='{.items[?(@.status.succeeded==1)].metadata.name}')
    

    【讨论】:

      【解决方案8】:

      如文档“删除旧作业由用户决定”中所述,请参阅http://kubernetes.io/docs/user-guide/jobs/#job-termination-and-cleanup

      我会根据作业名称和某些条件运行一个 pod 来执行此清理,从而让 kubernetes 至少在这里处理您的进程的可用性。您可以为此运行一个循环作业(假设您运行 kubernetes 1.5)。

      【讨论】:

      • 所以我不明白的是,一个用于清理的 pod 现在与其他 pod 位于相同的命名空间中,您如何配置它以最初连接到集群?
      • 仅当您以非常严格的方式进行安全设置时,命名空间才相关(并且 k8s 中的 pod 在 pod 上运行,您的安全性无论如何都会变弱一些)。幸运的是,取得了一些进展:允许闲置的作业数量已经增加(gcloud 大约 40k 而不是之前的 10k),并且使用 cronjobs,您可以通过限制您保留的旧作业数量让 k8s 为您管理它
      【解决方案9】:

      通过运行 cron 作业删除它们的简单方法:

      kubectl get jobs --all-namespaces | sed '1d' | awk '{ print $2, "--namespace", $1 }' | while read line; do kubectl delete jobs $line; done
      

      【讨论】:

      • 不建议解析文本输出。相反,您应该请求一个 json,用 jq 解析它并遍历结果。
      • kubectl delete job $(kubectl get jobs -o jsonpath='{.items[?(@.status.completionTime)].metadata.name}')
      • 不要这样做。这也会删除正在运行的作业
      猜你喜欢
      • 2018-07-23
      • 2020-03-11
      • 2021-05-12
      • 1970-01-01
      • 2021-06-02
      • 1970-01-01
      • 2021-10-24
      • 2019-07-31
      • 2020-02-03
      相关资源
      最近更新 更多