Home > database >  how to run a kubernetes cronjob with modified values at runtime
how to run a kubernetes cronjob with modified values at runtime

Time:05-04

So I have a kubernetes cronjob object set to run periodically.

NAME                            SCHEDULE       SUSPEND   ACTIVE   LAST SCHEDULE   AGE
ticketing-job-lifetime-manager  45 */4 * * *   False     0        174m            25d

and I know how to call it manually:

# ticketing-job-manual-call will be the name of the job that runs
kubectl create job --from=cronjobs/ticketing-job-lifetime-manager ticketing-job-manual-call

BUT - what I want to do is call the job, but modify portions of it (shown below) before it is called. Specifically items.metadata.annotations and items.spec.jobTemplate.spec.containers.args.

If this is possible on-the-fly, I'd be over the moon. If it requires creating a temporary object, then I'd appreciate an approach to doing this that is robust, performant - and safe. Thanks!

    apiVersion: v1
    items:
      - apiVersion: batch/v1
        kind: CronJob
        metadata:
          annotations:
            <annotation-1>              <- want to modify these
            <annotation-2>
            ..
            <annotation-n>
          creationTimestamp: "2022-05-03T13:24:49Z"
          labels:
            AccountID: foo
            FooServiceAction: "true"
            FooServiceManaged: "true"
            CronName: foo
          name: foo
          namespace: my-namespace
          resourceVersion: "298013999"
          uid: 57b2-4612-88ef-a0d5e26c8
        spec:
          concurrencyPolicy: Replace
          jobTemplate:
            metadata:
              annotations:
                <annotation-1>          <- want to modify these
                <annotation-2>
                ..
                <annotation-n>
              creationTimestamp: null
              labels:
                AccountID: 7761777c38d93b
                TicketServiceAction: "true"
                TicketServiceManaged: "true"
                CronName: ticketing-actions-7761777c38d93b-0
              name: ticketing-actions-7761777c38d93b-0
              namespace: rias
            spec:
              containers:
                - args:
                    - --accountid=something     <- want to modify these
                    - --faultzone=something
                    - --type=something
                    - --cronjobname=something
                    - --plans=something
                  command:
                    - ./ticketing-job
                  env:
                    - name: FOO_BAR             <- may want to modify these
                      value: "false"
                    - name: FOO_BAZ
                      value: "true"

CodePudding user response:

The way to think about this is that Kubernetes resources are defined (definitively) by YAML|JSON config files. A useful advantage to having config files is that these can be checked into source control; you automatically audit your work if you create unique files for each resource (for every change).

Kubernetes (kubectl) isn't optimized|designed to tweak Resources although you can use kubectl patch to update deployed Resources.

I encourage you to consider a better approach that is applicable to any Kubernetes resource (not just Job's) and this focuses on use YAML|JSON files as the way to represent state:

  1. kubectl get the resource and output it as YAML|JSON (--output=json|yaml) persisting the result to a file (that could be source-controlled)
  2. Mutate the file using any of many tools but preferably YAML|JSON processing tools (e.g. yq or jq)
  3. kubectl create or kubectl apply the file that results that reflects the intended configuration of the new resource.

By way of example, assuming you use jq:

# Output 'ticketing-job-lifetime-manage' as a JSON file
kubectl get job/ticketing-job-lifetime-manage \
--namespace=${NAMESPACE} \
--output=json > ${PWD}/ticketing-job-lifetime-manage.json

# E.g. replace '.metadata.annotations' entirely
jq '.metadata.annotations=[{"foo":"x"},{"bar":"y"}]' \
${PWD}/${PWD}/ticketing-job-lifetime-manage.json \
> ${PWD}/${PWD}/new-job.json

# E.g. replace a specific container 'foo' specific 'args' key with value
jq '.spec.jobTemplate.spec.containers[]|select(.name=="foo").args["--key"]="value" \
${PWD}/${PWD}/new-job.json \
> ${PWD}/${PWD}/new-job.json

# Etc.

# Apply
kubectl create \
--filename=${PWD}/new-job.json \
--namespace=${NAMESPACE}

NOTE You can pipe the output from the kubectl get through jq and into kubectl create if you wish but it's useful to keep a file-based record of the resource.

Having to deal with YAML|JSON config file is a common issue with Kubernetes (and every other technology that uses them). There are other tools e.g. jsonnet and CUE that try to provide a more programmatic way to manage YAML|JSON.

  • Related