Kubernetes
Kubectl
CronJob
Job Scheduling
Command Overrides

Kubectl create job from cronjob and override args

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Kubernetes lets you manually trigger a Job from an existing CronJob using kubectl create job --from=cronjob/<name>. This is useful for testing, one-off runs, or running a CronJob's task with different arguments without waiting for the schedule. However, kubectl create job --from does not directly support overriding command args. To override arguments, you must extract the CronJob's job template, modify it, and apply it manually.

Create a Job from a CronJob

bash
1# Create a one-off job from an existing cronjob
2kubectl create job my-manual-job --from=cronjob/my-cronjob
3
4# Check the job status
5kubectl get jobs
6kubectl describe job my-manual-job
7
8# View the pod logs
9kubectl logs job/my-manual-job

This creates a Job with the exact same spec as the CronJob's job template — same container image, command, args, volumes, and environment variables.

Override Args (Extract and Modify)

kubectl create job --from does not support -- to pass command overrides. To override args, extract the job template and modify it:

bash
# Extract the job template from the cronjob as YAML
kubectl get cronjob my-cronjob -o yaml | \
  sed 's/CronJob/Job/' > /tmp/manual-job.yaml

A cleaner approach using kubectl create job --from --dry-run:

bash
1# Generate the job YAML without creating it
2kubectl create job my-override-job \
3  --from=cronjob/my-cronjob \
4  --dry-run=client -o yaml > /tmp/manual-job.yaml
5
6# Edit the args
7# Change spec.template.spec.containers[0].args
8vi /tmp/manual-job.yaml
9
10# Apply the modified job
11kubectl apply -f /tmp/manual-job.yaml

Override with a One-Liner (jq/yq)

Using yq (YAML processor) to override args inline:

bash
1# Override args using yq
2kubectl create job my-override-job \
3  --from=cronjob/my-cronjob \
4  --dry-run=client -o yaml | \
5  yq '.spec.template.spec.containers[0].args = ["--mode", "full", "--verbose"]' | \
6  kubectl apply -f -
7
8# Override the command entirely
9kubectl create job my-override-job \
10  --from=cronjob/my-cronjob \
11  --dry-run=client -o yaml | \
12  yq '.spec.template.spec.containers[0].command = ["/bin/sh", "-c", "echo custom run"]' | \
13  kubectl apply -f -

Using jq (JSON processor):

bash
1kubectl create job my-override-job \
2  --from=cronjob/my-cronjob \
3  --dry-run=client -o json | \
4  jq '.spec.template.spec.containers[0].args = ["--date", "2024-01-15"]' | \
5  kubectl apply -f -

Override Environment Variables

bash
1# Add or override an environment variable
2kubectl create job my-env-job \
3  --from=cronjob/my-cronjob \
4  --dry-run=client -o yaml | \
5  yq '.spec.template.spec.containers[0].env += [{"name": "RUN_MODE", "value": "manual"}]' | \
6  kubectl apply -f -

Example CronJob and Manual Override

yaml
1# cronjob.yaml
2apiVersion: batch/v1
3kind: CronJob
4metadata:
5  name: data-sync
6spec:
7  schedule: "0 2 * * *"
8  jobTemplate:
9    spec:
10      template:
11        spec:
12          containers:
13          - name: sync
14            image: myapp/data-sync:latest
15            args: ["--mode", "incremental", "--date", "today"]
16          restartPolicy: OnFailure
bash
1# Run a manual full sync for a specific date
2kubectl create job data-sync-manual \
3  --from=cronjob/data-sync \
4  --dry-run=client -o yaml | \
5  yq '.spec.template.spec.containers[0].args = ["--mode", "full", "--date", "2024-01-15"]' | \
6  kubectl apply -f -
7
8# Verify
9kubectl get pods -l job-name=data-sync-manual
10kubectl logs job/data-sync-manual

Cleaning Up Manual Jobs

bash
1# Delete a specific manual job
2kubectl delete job my-manual-job
3
4# Delete all completed jobs
5kubectl delete jobs --field-selector status.successful=1
6
7# Set TTL on the job to auto-delete (Kubernetes 1.23+)
8kubectl create job my-ttl-job \
9  --from=cronjob/my-cronjob \
10  --dry-run=client -o yaml | \
11  yq '.spec.ttlSecondsAfterFinished = 3600' | \
12  kubectl apply -f -
13# Job auto-deletes 1 hour after completion

Checking CronJob History

bash
1# List recent jobs created by a cronjob
2kubectl get jobs --sort-by=.metadata.creationTimestamp | grep my-cronjob
3
4# View cronjob status
5kubectl get cronjob my-cronjob
6# NAME         SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE
7# my-cronjob   0 2 * * *   False     0        2h ago
8
9# View the last successful job's logs
10kubectl logs job/$(kubectl get jobs -o name | grep my-cronjob | tail -1 | cut -d/ -f2)

Common Pitfalls

  • Job name conflicts: kubectl create job fails if a job with the same name already exists. Always use a unique name (e.g., include a timestamp: my-job-$(date +%s)) or delete the previous job first.
  • Assuming --from supports arg overrides: kubectl create job --from=cronjob/x -- custom-arg does not work. The -- flag is not supported with --from. You must use the dry-run + yq/jq pipeline to modify args.
  • Forgetting to clean up manual jobs: Manual jobs persist after completion. Unlike CronJob-created jobs (which respect successfulJobsHistoryLimit), manually created jobs are not automatically cleaned up. Use ttlSecondsAfterFinished or manual deletion.
  • CronJob's concurrencyPolicy not applying to manual jobs: The concurrencyPolicy (Forbid, Replace) only applies to jobs created by the CronJob scheduler. Manually created jobs always run regardless of this policy, potentially causing conflicts.
  • Missing RBAC permissions: Creating jobs requires create permission on the jobs resource. In restricted namespaces, your service account may have permission to view CronJobs but not create Jobs.

Summary

  • Use kubectl create job name --from=cronjob/name to manually trigger a CronJob
  • Override args by piping --dry-run=client -o yaml through yq to modify the YAML before applying
  • Use yq '.spec.template.spec.containers[0].args = [...]' to set custom arguments
  • Set ttlSecondsAfterFinished on manual jobs for automatic cleanup
  • Manual jobs are not subject to the CronJob's concurrencyPolicy or history limits
  • Always use unique job names to avoid conflicts with existing jobs

Course illustration
Course illustration

All Rights Reserved.