Kubernetes CronJobs
Kubernetes includes a built-in resource type for scheduled workloads: the CronJob. It creates Job objects on a cron schedule, and each Job spins up one or more Pod instances to run your container. When the Pod completes, the Job records the result and Kubernetes cleans up according to your configured retention policy.
This tutorial covers the Kubernetes CronJob spec, key configuration options, and how PandaStack uses Kubernetes under the hood to manage scheduled container workloads for you.
The CronJob Resource
A Kubernetes CronJob is defined in YAML. Here's a minimal example:
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-report
spec:
schedule: "0 6 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: report-generator
image: your-registry/report-generator:latest
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
restartPolicy: OnFailureApply it to your cluster:
kubectl apply -f daily-report-cronjob.yaml
# Verify the CronJob was created
kubectl get cronjobs
# Watch Jobs created by the CronJob
kubectl get jobs --watchKey Spec Fields
schedule
Standard five-field cron expression. Uses UTC by default, though you can configure a timezone in Kubernetes 1.27+.
# Common cron schedules
"*/5 * * * *" # Every 5 minutes
"0 2 * * *" # Every day at 2 AM UTC
"0 9 * * 1" # Every Monday at 9 AM UTC
"0 0 1 * *" # First of every monthconcurrencyPolicy
Controls what happens when a new scheduled run is triggered and a previous run is still executing.
spec:
concurrencyPolicy: Forbid # Skip new run if previous is still running (recommended for most jobs)
# concurrencyPolicy: Allow # Allow concurrent runs (default, can cause overlap issues)
# concurrencyPolicy: Replace # Cancel the running job and start a new oneUse Forbid for jobs that must not overlap — database migrations, data sync jobs that process all pending records, or any idempotency-sensitive workload.
startingDeadlineSeconds
If Kubernetes misses a scheduled run (e.g., the scheduler was down), this field controls how late a run can start before being skipped.
spec:
startingDeadlineSeconds: 300 # Skip if more than 5 minutes latesuccessfulJobsHistoryLimit and failedJobsHistoryLimit
Control how many completed and failed Job objects are retained for inspection.
spec:
successfulJobsHistoryLimit: 5
failedJobsHistoryLimit: 3A Complete Production CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: data-sync
namespace: production
spec:
schedule: "*/30 * * * *"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 120
successfulJobsHistoryLimit: 5
failedJobsHistoryLimit: 3
jobTemplate:
spec:
activeDeadlineSeconds: 600 # Kill job if it runs longer than 10 minutes
backoffLimit: 2 # Retry up to 2 times on failure
template:
spec:
restartPolicy: OnFailure
containers:
- name: sync
image: your-registry/sync:latest
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
envFrom:
- secretRef:
name: sync-secretsDebugging Kubernetes CronJobs
# List all CronJobs
kubectl get cronjobs -n production
# List Jobs created by a CronJob
kubectl get jobs -l job-name=data-sync -n production
# Get Pod logs from a specific Job
kubectl logs -l job-name=data-sync --tail=100 -n production
# Manually trigger a CronJob
kubectl create job --from=cronjob/data-sync manual-run-$(date +%s) -n production
# Describe a Job to see events and status
kubectl describe job data-sync-28123456 -n productionManaging Kubernetes CronJobs Without the YAML
Writing and maintaining Kubernetes YAML for every scheduled job adds operational overhead — you still need to manage cluster access, secrets, namespaces, and resource limits.
PandaStack uses Kubernetes internally to run scheduled container workloads, but abstracts away the YAML entirely. You interact through the CLI or dashboard, and PandaStack handles the CronJob spec, concurrency policy, and failure handling automatically.
npm install -g @pandastack/cli
# Create a scheduled container job — no YAML required
panda cronjob create \
--name data-sync \
--image your-registry/sync:latest \
--schedule "*/30 * * * *"
# Trigger a manual run
panda cronjob run data-sync
# View execution history
panda cronjob executions data-sync
# Stream logs from the latest run
panda cronjob logs data-sync --latestPandaStack tracks execution history for every run and streams logs in real time — the same visibility you'd get from kubectl logs without managing cluster credentials. View all job runs at [dashboard.pandastack.io](https://dashboard.pandastack.io).
Summary
Kubernetes CronJobs are a powerful primitive for scheduled workloads, with fine-grained control over concurrency, failure handling, and retention. For teams that want the power of containerized scheduling without managing Kubernetes directly, PandaStack provides a higher-level platform built on top of it. Visit [docs.pandastack.io](https://docs.pandastack.io) to learn more.