CronJobs in Kubernetes — Complete Guide
In this tutorial, you will learn about CronJobs in Kubernetes. We cover key concepts, practical examples, and best practices to help you master this topic.
Use Kubernetes CronJobs for cluster-level scheduling: define CronJob resources, configure job templates, handle concurrency, set timezones, manage history limits, and monitor job execution.
What You Learn
You will learn how to create and manage Kubernetes CronJob resources, configure job templates with resource limits, handle concurrency policies, manage job history, set timezone-aware schedules, and monitor CronJob execution.
Why It Matters
Kubernetes CronJobs are the standard way to run scheduled tasks in container Orchestration. Unlike traditional cron, they provide declarative configuration, automatic retry, concurrency control, and integration with Kubernetes monitoring.
Real-World Use
DodaTech uses Kubernetes CronJobs for database backups (daily), cache warming (every 30 minutes), certificate renewal (monthly), and data cleanups (hourly). CronJobs run on the same cluster as applications, sharing secrets, configmaps, and network policies.
Basic CronJob Definition
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-backup
namespace: production
spec:
schedule: "0 3 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: dodatech/backup-tool:1.0
command:
- /usr/local/bin/backup.sh
env:
- name: DB_HOST
value: postgres-service
- name: BACKUP_BUCKET
value: s3://dodatech-backups
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
restartPolicy: OnFailure
kubectl apply -f cronjob-basic.yaml
kubectl get cronjobs
kubectl get jobs
kubectl describe cronjob daily-backup
kubectl logs job.batch/daily-backup-123456
kubectl delete cronjob daily-backup
CronJob with Concurrency Policy
apiVersion: batch/v1
kind: CronJob
metadata:
name: cache-warming
spec:
schedule: "*/30 * * * *"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 120
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
backoffLimit: 2
activeDeadlineSeconds: 300
template:
spec:
containers:
- name: warmer
image: dodatech/cache-warmer:1.0
env:
- name: REDIS_HOST
value: redis-service
restartPolicy: Never
ConcurrencyPolicy options: Allow (default) multiple simultaneous jobs, Forbid skip if previous still running, Replace cancel running and start new.
Timezone-Aware CronJobs
apiVersion: batch/v1
kind: CronJob
metadata:
name: business-hours-report
spec:
schedule: "0 9 * * 1-5"
timeZone: "America/New_York"
jobTemplate:
spec:
template:
spec:
containers:
- name: reporter
image: dodatech/reporter:1.0
command: ["/usr/local/bin/generate-report.sh"]
env:
- name: TZ
value: "America/New_York"
restartPolicy: Never
For clusters without timeZone support, set TZ in containers or use init containers to configure timezone.
Suspending and Starting CronJobs
# Suspend a CronJob (stop future executions)
kubectl patch cronjob daily-backup -p '{"spec":{"suspend":true}}'
# Resume a CronJob
kubectl patch cronjob daily-backup -p '{"spec":{"suspend":false}}'
# Manually create a Job from a CronJob
kubectl create job --from=cronjob/daily-backup manual-backup-001
# Check missed schedules
kubectl get events --field-selector involvedObject.kind=CronJob
Monitoring CronJobs
# Watch CronJob status
kubectl get cronjob --watch
# View job history
kubectl get jobs --selector=job-name=daily-backup
# Check pod status for recent job
kubectl get pods --selector=job-name=daily-backup-28374651
# View logs from last job run
kubectl logs job.batch/daily-backup-28374651
# Set up alerts with Prometheus
# Use kube-state-metrics for CronJob metrics:
# kube_cronjob_status_active
# kube_cronjob_status_last_schedule_time
# kube_job_status_failed
# PrometheusRule alert for failed CronJobs
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: cronjob-alerts
spec:
groups:
- name: cronjob
rules:
- alert: CronJobFailed
expr: time() - kube_cronjob_status_last_schedule_time > 120
for: 5m
labels:
severity: critical
annotations:
summary: "CronJob {{ $labels.cronjob }} failed"
Common Mistakes
1. No Resource Limits
Without resource limits, a CronJob pod can consume all node resources. Always set CPU and memory requests and limits.
2. Ignoring History Limits
Successful/failed jobs accumulate and fill etcd. Set successfulJobsHistoryLimit and failedJobsHistoryLimit to 3 or fewer.
3. Wrong restartPolicy
CronJob pods must use restartPolicy: OnFailure or Never. restartPolicy: Always is invalid for Jobs.
4. Not Handling ImagePullBackoff
If the image is not found, the job never runs. Ensure images are available in the cluster's container registry.
5. Missing BackoffLimit
Without backoffLimit, a failing job retries forever. Set a reasonable limit (2-3 retries).
Practice Questions
1. What is the difference between a Job and a CronJob?
A Job runs a task once. A CronJob creates Jobs on a schedule. CronJob adds the schedule, concurrency, and history management on top of Job.
2. How do you prevent overlapping CronJob executions?
Set concurrencyPolicy: Forbid. This skips a new execution if the previous one is still running.
3. What does successfulJobsHistoryLimit control?
The number of completed Job resources to retain. Old Jobs are garbage collected. Default is 3.
4. How do you manually trigger a CronJob?
Use kubectl create job --from=cronjob/name manual-job-name to create an ad-hoc Job from the CronJob template.
Challenge
Deploy a Kubernetes CronJob that: runs every 15 minutes, has a 10-minute timeout, retries up to 3 times on failure, forbids concurrency, keeps last 2 successful and 1 failed job, sets resource limits of 128Mi memory and 100m CPU, and writes logs to stdout for kubectl logs.
FAQ
Mini Project: CronJob Management
apiVersion: batch/v1
kind: CronJob
metadata:
name: db-maintenance
namespace: production
spec:
schedule: "0 4 * * 0"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 300
successfulJobsHistoryLimit: 2
failedJobsHistoryLimit: 1
jobTemplate:
spec:
backoffLimit: 2
activeDeadlineSeconds: 600
template:
spec:
serviceAccountName: db-maintenance-sa
containers:
- name: maintenance
image: dodatech/db-tools:1.2
command:
- /scripts/maintenance.sh
env:
- name: DB_HOST
valueFrom:
secretKeyRef:
name: db-secret
key: host
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
restartPolicy: OnFailure
kubectl apply -f cronjob-maintenance.yaml
kubectl get cronjob db-maintenance -o yaml
kubectl describe cronjob db-maintenance
What's Next
Now that you understand Kubernetes CronJobs, explore systemd timers and other cron alternatives, then learn about cron monitoring best practices.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro