I stumbled upon some kubernetes cronjobs recently, that were using several ENV variables as arguments to the script being run.
When the necessity to run the command with a specific argument arose, I had to patch the container's image using a kubectl patch
command.
After I was done, I wondered if there is a better way. To explain my thoughts, let's walk trough a small setup.
So, granted that you ave a cronjob
apiVersion: batch/v1
kind: CronJob
metadata:
name: rafspiny-cronjob1-manual
labels:
app: rafspiny
spec:
schedule: "0 * * * *" # Runs every hour
jobTemplate:
spec:
template:
spec:
containers:
- name: rafspiny-container
image: your-image:latest
env:
- name: ARG1
value: "" # set to --only-ids=1,2,3,4 to only process a list of entities
- name: ARG2
value: "" # set to --filter=4,5 to restrict processing to these other entities
- name: ARG3
value: "" # set to --verbose
restartPolicy: OnFailure
Exceptionally, there was a need to pass ARG2, so I first got the description of the resource, to make sure I will patch the right path.
kubectl describe cronjob rafspiny-cronjob1-manual
would give something like this (more or less)
Name: rafspiny-cronjob1-manual
Namespace: default
Labels: app=rafspiny
Annotations: <none>
Schedule: 0 * * * *
Concurrency Policy: Allow
Suspend: False
Successful Jobs History Limit: 3
Failed Jobs History Limit: 1
Starting Deadline Seconds: <unset>
Selector: <unset>
Parallelism: 1
Completions: 1
Pod Template:
Labels: <none>
Service Account: <default>
Containers:
rafspiny-container:
Image: your-image:latest
Port: <none>
Environment Variables:
ARG1:
ARG2:
ARG3:
Volumes: <none>
Last Schedule Time: Thu, 20 Dec 2024 12:55:00 +0000
Active Jobs: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 5m cronjob-controller Created job rafspiny-cronjob1-manual-42786503
Confirming that ARG2 is the item in the env
list, I could write the patch command
`kubectl patch cronjob rafspiny-cronjob1-manual --type='json' -p='[{"op": "replace", "path": "/spec/jobTemplate/spec/template/spec/containers/0/env/1/value", "value": "--filter=4,5"}]'
I confirmed that I patched the right variable
Name: rafspiny-cronjob1-manual
Namespace: default
Labels: app=rafspiny
Annotations: <none>
Schedule: 0 * * * *
Concurrency Policy: Allow
Suspend: False
Successful Jobs History Limit: 3
Failed Jobs History Limit: 1
Starting Deadline Seconds: <unset>
Selector: <unset>
Parallelism: 1
Completions: 1
Pod Template:
Labels: <none>
Service Account: <default>
Containers:
rafspiny-container:
Image: your-image:latest
Port: <none>
Environment Variables:
ARG1:
ARG2:
ARG3: --filter=4,5
Volumes: <none>
Last Schedule Time: Thu, 20 Dec 2024 12:55:00 +0000
Active Jobs: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 5m cronjob-controller Created job rafspiny-cronjob1-manual-42786503
Then, I placed the cronjob. The logical conclusion I reached is that it is inconvenient to use several ENV variables, one for each argument of your script. It may be better to have one variable SCRIPT_EXTRA_ARGS
.
At the same time, this will only help if one has only one ENV variable. So back to square one if you have a bunch of them.
I did double check if it was possible to use a selector in the JSON expression.
kubectl path
can use three types of merge. I was using the JSON patch. It relies on the RFC6902 that clear states that the format of the replace path must be JSON-Pointer complaint with RFC6901. That translates to No selector, just index.
You can test JSON Pointer here, if you need.