Kubernetes
Kubectl
CronJob
Job Scheduling
Command Overrides

Kubectl create job from cronjob and override args

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

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

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.