Amazon EKS — Jobs and CronJobs
Jobs run batch tasks to completion. CronJobs schedule recurring tasks. Both are commonly used on EKS for data processing, backups, report generation, and cleanup operations.
Jobs — One-Time Batch Processing
Basic Job
apiVersion: batch/v1
kind: Job
metadata:
name: data-migration
namespace: production
spec:
template:
spec:
containers:
- name: migrate
image: 123456789.dkr.ecr.us-east-1.amazonaws.com/migrator:v1.0
command: ["python", "migrate.py"]
env:
- name: DB_HOST
valueFrom:
secretKeyRef:
name: db-credentials
key: host
resources:
requests:
cpu: "500m"
memory: "512Mi"
restartPolicy: Never
backoffLimit: 3
ttlSecondsAfterFinished: 3600 # Clean up after 1 hour
Parallel Jobs
Process multiple items in parallel:
apiVersion: batch/v1
kind: Job
metadata:
name: image-processor
spec:
completions: 10 # Total items to process
parallelism: 3 # Process 3 at a time
template:
spec:
containers:
- name: processor
image: 123456789.dkr.ecr.us-east-1.amazonaws.com/processor:v1.0
resources:
requests:
cpu: "1"
memory: "1Gi"
restartPolicy: Never
backoffLimit: 5
Job on Fargate
Jobs are great candidates for Fargate — spin up, process, shut down. No idle nodes:
spec:
template:
metadata:
labels:
compute: fargate # Matches your Fargate profile selector
spec:
containers:
- name: batch
image: my-batch-job:latest
resources:
requests:
cpu: "1" # Set accurately — Fargate charges by resource tier
memory: "2Gi"
restartPolicy: Never
CronJobs — Scheduled Tasks
Basic CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-backup
namespace: production
spec:
schedule: "0 2 * * *" # 2 AM UTC daily
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: 123456789.dkr.ecr.us-east-1.amazonaws.com/backup:v1.0
command: ["./run-backup.sh"]
resources:
requests:
cpu: "250m"
memory: "256Mi"
restartPolicy: OnFailure
backoffLimit: 2
ttlSecondsAfterFinished: 86400 # Clean up after 24 hours
concurrencyPolicy: Forbid # Don't overlap with previous run
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
Cron Schedule Examples
| Schedule | Meaning |
|---|---|
0 2 * * * |
Daily at 2:00 AM |
*/15 * * * * |
Every 15 minutes |
0 0 * * 0 |
Weekly on Sunday midnight |
0 0 1 * * |
Monthly on the 1st |
0 8,20 * * 1-5 |
8 AM and 8 PM on weekdays |
Concurrency Policies
| Policy | Behavior |
|---|---|
Allow (default) |
Multiple Jobs can run concurrently |
Forbid |
Skip new Job if previous hasn’t finished |
Replace |
Cancel the running Job and start a new one |
TTL Controller for Cleanup
Finished Jobs stick around (and their pods) unless cleaned up:
spec:
ttlSecondsAfterFinished: 3600 # Delete Job 1 hour after completion
Without TTL, you’ll accumulate thousands of completed Job pods over time. Always set this.
Monitoring Jobs
# List all jobs
kubectl get jobs -n production
# Watch a specific job
kubectl describe job data-migration -n production
# Check pod logs
kubectl logs job/data-migration -n production
# List CronJob history
kubectl get cronjobs -n production
kubectl get jobs --selector=batch.kubernetes.io/controller-uid=<cronjob-uid>
Best Practices
- Always set
ttlSecondsAfterFinished— prevents accumulation of completed Job pods - Set
backoffLimit— avoid infinite retries on permanent failures - Use
concurrencyPolicy: Forbidfor CronJobs that shouldn’t overlap - Set proper resource requests — especially important on Fargate (determines pod sizing and cost)
- Use Fargate for bursty batch jobs — pay only for the time the job runs
- Log results to S3 or CloudWatch — Job pods are ephemeral; don’t rely on pod logs for audit trails
- Monitor failed Jobs — set up alerts for repeated failures