How to run shell script using CronJobs in Kubernetes?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
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.
Related reading
- How to scale k8s pods according to rabbitmq queue message rate?
- How to scale knative service based on custom metrics?
- how to scale kubernetes daemonset to 0?
- How to schedule pods restart
- How to run Tensorflow on SLURM cluster with properly configured parameter server?
- How to save/restore a model after training?
- How to scrape metrics-server to prometheus outside kubernetes cluster
- How to see logs of terminated pods

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack 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.