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:
kubectl get
the resource and output it as YAML|JSON (--output=json|yaml
) persisting the result to a file (that could be source-controlled)- Mutate the file using any of many tools but preferably YAML|JSON processing tools (e.g.
yq
orjq
) kubectl create
orkubectl 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
throughjq
and intokubectl 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.