如何自动删除由 CronJob 创建的已完成 Kubernetes 作业?
Posted
技术标签:
【中文标题】如何自动删除由 CronJob 创建的已完成 Kubernetes 作业?【英文标题】:How to automatically remove completed Kubernetes Jobs created by a CronJob? 【发布时间】:2017-05-14 02:46:03 【问题描述】:除了制作 CronJob 来清理已完成的 Jobs 之外,还有其他方法可以自动删除已完成的 Jobs 吗?
K8s Job Documentation 声明已完成作业的预期行为是让它们保持已完成状态,直到手动删除。因为我每天通过 CronJobs 运行数千个作业,我不想保留已完成的作业。
【问题讨论】:
【参考方案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 中执行,类似于其他答案。
-
创建一个服务帐户,例如
my-sa-name
为资源作业创建具有列表和删除权限的角色
在服务帐户中附加角色(角色绑定)
创建一个将使用服务帐户的 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/1
或1/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
【讨论】:
请不要只发布一些工具或库作为答案。至少在答案本身中展示how it solves the problem。【参考方案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')
不要这样做。这也会删除正在运行的作业以上是关于如何自动删除由 CronJob 创建的已完成 Kubernetes 作业?的主要内容,如果未能解决你的问题,请参考以下文章