'How to pass kubernetes namespaces dynamically to k8s cronjob
I have a cronjob that cleans some job since my kubernetes is on older version so cannot use ttlafterfinished
. How can I fetch the namespaces that have this job deployed and pass the namespaces name dynamically instead of repeating the same command several times?
This is my cronjob:
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
Solution 1:[1]
A more flexible alternative to what you're doing now would be to store the list of job names you want to delete in a list/array. Then, you can iterate through the list of job names and execute the command.
Below is a simpler (IMO) version of your command that uses the -o=jsonpath
support instead in kubectl
to specify a search criteria.
# 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.
If the job names in your cluster have incrementing suffixes, such as fusionauth-job-01
, fusionauth-job-02
, etc, and you want to keep only the latest instance of that job in a particular namespace, then you will need to leverage something like jq
so you can do some regular expression matching. kubectl
's jsonpath
feature doesn't support regular expressions.
As an example, let's assume your cluster has the jobs shown below.
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
Furthermore, the jobs are listed in timestamp order, meaning fusionauth-job-03
is the newest job (whose name matches fusionauth-job*
) in namespace team2
, job-init-02
is the newest job (whose name matches job-init*
) in namespace team1
, fusionauth-job-02
is the newest job (of that name pattern) in namespace team1
, and fusionauth-job-01
is the only job running in namespace default
.
After running your jobs-cleanup
job, the expectation is that the following jobs would be left:
NAMESPACE NAME
default fusionauth-job-01
team1 fusionauth-job-02
team1 job-init-02
team2 fusionauth-job-03
A script to produce these results is shown here:
# 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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |