如何将 kubernetes 命名空间动态传递给 k8s cronjob

How to pass kubernetes namespaces dynamically to k8s cronjob

我有一个 cronjob 可以清理一些工作,因为我的 kubernetes 是旧版本所以不能使用 ttlafterfinished。我如何才能获取已部署此作业的命名空间并动态传递命名空间名称,而不是多次重复相同的命令?

这是我的定时任务:

kind: CronJob
metadata:
  name: jobs-cleanup
spec:
  schedule: "*/30 * * * *"
  successfulJobsHistoryLimit: 1
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: cleanup-operator
          containers:
          - name: jobs-cleanup
            image: google.io/test/job:1.0
            args:
            - -c
            - |
              for i in $(seq 9);do 
              kubectl get jobs --sort-by=.metadata.creationTimestamp -n dev$i | grep "job-init" | cut -d' ' -f1 | tac | tail -n +2 | xargs -I % kubectl delete jobs % -n dev$i;done
              kubectl get jobs --sort-by=.metadata.creationTimestamp -n stg1 | grep "fusionauth-job" | cut -d' ' -f1 | tac | tail -n +2 | xargs -I % kubectl delete jobs % -n stg1
              kubectl get jobs --sort-by=.metadata.creationTimestamp -n pt1 | grep "fusionauth-job" | cut -d' ' -f1 | tac | tail -n +2 | xargs -I % kubectl delete jobs % -n pt1
              kubectl get jobs --sort-by=.metadata.creationTimestamp -n sit1 | grep "fusionauth-job" | cut -d' ' -f1 | tac | tail -n +2 | xargs -I % kubectl delete jobs % -n sit1
            command:
            - /bin/sh
          restartPolicy: Never
          imagePullSecrets:
            - name: secret

比您现在所做的更灵活的替代方法是将要删除的作业名称列表存储在 list/array 中。然后,您可以遍历作业名称列表并执行命令。

下面是您的命令的一个更简单的 (IMO) 版本,它使用 -o=jsonpath 支持而不是 kubectl 来指定搜索条件。

# The list of jobs you want to delete from any/all namespaces.
jobs_list="job-init fusionauth-job"

for job_name in ${jobs_list}; do
    kubectl get jobs -A --sort-by=.metadata.creationTimestamp \
        -o=jsonpath="{range .items[?(@.metadata.name == '${job_name}')]}{.metadata.namespace} {.metadata.name}{'\n'}{end}" \
          | while read namespace job;do kubectl delete job ${job} -n ${namespace};done;
done

The following was added as a result of the comments/conversation below.

如果您的集群中的作业名称具有递增的后缀,例如 fusionauth-job-01fusionauth-job-02 等,并且您希望仅 保持最新该作业在特定命名空间中的实例,那么您将需要利用 jq 之类的东西,以便您可以进行一些正则表达式匹配。 kubectljsonpath 功能不支持正则表达式。

例如,假设您的集群具有如下所示的作业。

NAMESPACE   NAME
default     fusionauth-job-01
team1       fusionauth-job-01
team1       fusionauth-job-02
team1       job-init-01
team1       job-init-02 
team2       fusionauth-job-01
team2       fusionauth-job-02
team2       fusionauth-job-03

此外,作业按时间戳顺序列出,这意味着 fusionauth-job-03 是命名空间 team2 中的最新作业(其名称匹配 fusionauth-job*),job-init-02 是命名空间 team1 中的最新作业(其名称匹配 job-init*),fusionauth-job-02 是命名空间 team1 中的最新作业(具有该名称模式),而 fusionauth-job-01 是命名空间 default.

中唯一的作业 运行

在 运行 你的 jobs-cleanup 工作之后,预计将留下以下工作:

NAMESPACE   NAME
default     fusionauth-job-01
team1       fusionauth-job-02
team1       job-init-02 
team2       fusionauth-job-03

此处显示了生成这些结果的脚本:

# The list of job name prefixes you want to delete from any/all namespaces.
jobs_list="job-init fusionauth-job"

for job_name in ${jobs_list}; do
    ns_observed=""
    echo "Searching for ${job_name}*"
    kubectl get jobs -A --sort-by=.metadata.creationTimestamp -o json \
        | jq -r '.items[] | select(.metadata.name | test('\"${job_name}\"')) | .metadata.namespace + " " + .metadata.name' \
        | tac \
        | while read namespace job;do
            if test "${ns_observed#*$namespace}" != "$ns_observed";then
                # If we've seen this namespace already for this job, then delete the
                # job, since the one we found previously is the newest.
                kubectl delete job ${job} -n ${namespace};
            else
                # Otherwise, if this is the first time observing this namespace, then
                # this is the newest job that starts with this job name in this namespace.
                ns_observed="$ns_observed $namespace";
            fi;
        done;
done