How to run shell script using CronJobs in Kubernetes?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A Kubernetes CronJob does not run a shell script by magic. It creates a Job on a schedule, and that Job starts a container. So the real question is how the container gets the script. In practice, the script is either baked into the image or mounted from a ConfigMap, then executed with a shell entrypoint.
The Simplest Mental Model
The chain is:
- CronJob schedule triggers
- Kubernetes creates a Job
- the Job creates a Pod
- the Pod runs a container
- the container executes your script
That means a shell script is not a first-class Kubernetes object. It is just part of what the container runs.
Put the Script in the Image
The most reliable pattern is to build the script into the image. A tiny Dockerfile could look like this:
Then define the CronJob:
This is the cleanest setup because the script and its runtime environment travel together.
Mount the Script from a ConfigMap
If the script is small and changes often, a ConfigMap can work well.
Then mount and execute it:
This keeps the script in cluster configuration rather than inside the image.
Use command and args Intentionally
When you need shell features such as environment expansion or several commands in sequence, invoke a shell explicitly:
This is useful, but do not overuse multi-line inline shell when the script is large. At that point, a real script file is easier to maintain.
Cron Settings That Matter
Beyond the script itself, CronJobs have behavior controls worth setting:
- '
concurrencyPolicyto prevent overlapping runs' - '
successfulJobsHistoryLimitandfailedJobsHistoryLimit' - '
startingDeadlineSecondsfor missed schedules'
Those settings often matter more operationally than the shell command syntax.
For example:
If your script is not safe to run twice at once, Forbid is an important guardrail.
Debugging the Script
If the CronJob appears to do nothing, inspect it step by step:
Most failures are one of these:
- wrong image
- script not executable
- wrong mount path
- shell missing from the image
- cron expression not what you expected
Common Pitfalls
- Assuming Kubernetes runs the script directly without a container runtime context.
- Mounting the script from a ConfigMap but forgetting execute permissions.
- Using
/bin/bashin an image that only contains/bin/sh. - Writing a CronJob that allows overlapping runs even though the script is not idempotent.
- Inlining large shell programs in YAML when they should live in a script file or image.
Summary
- A CronJob runs a container on a schedule; the container is what runs the shell script.
- The script should usually be baked into the image or mounted from a ConfigMap.
- Use
commandandargsdeliberately when shell features are needed. - Configure CronJob behavior such as concurrency, history, and deadlines, not just the schedule.
- If it fails, debug the chain from CronJob to Job to Pod to container logs.

