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.

Previous Post