KubernetesDevOps10 min read

Kubernetes CronJob Guide: Scheduling Tasks in K8s

Kubernetes CronJob runs scheduled tasks as batch jobs in your cluster. This guide covers the full spec, concurrency control, timezone support, history management, and how to debug jobs that fail silently.

Minimal CronJob Example

apiVersion: batch/v1
kind: CronJob
metadata:
  name: db-backup
spec:
  schedule: "0 2 * * *"   # 2:00 AM UTC every day
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: my-backup-image:latest
            command: ["/scripts/backup.sh"]
          restartPolicy: OnFailure

# Apply and verify

kubectl apply -f cronjob.yaml
kubectl get cronjobs
kubectl describe cronjob db-backup

Key Spec Fields

FieldReq?Description
scheduleRequiredStandard 5-field cron expression (UTC by default)
timeZoneOptionalIANA timezone name (e.g. America/New_York). Kubernetes 1.27+ only.
concurrencyPolicyOptionalAllow, Forbid, or Replace. Controls what happens if the previous job is still running when the next fires.
successfulJobsHistoryLimitOptionalNumber of completed job records to keep. Default: 3. Set to 0 to delete immediately.
failedJobsHistoryLimitOptionalNumber of failed job records to keep. Default: 1.
startingDeadlineSecondsOptionalIf the job misses its schedule by more than this many seconds, skip it. Useful for time-sensitive jobs.
suspendOptionalSet to true to temporarily pause the CronJob without deleting it.

concurrencyPolicy: Allow vs Forbid vs Replace

Allow

Multiple job instances can run simultaneously. Default. OK for idempotent jobs.

Forbid

If a job is still running when the next fires, skip the new one. Use for jobs that must not overlap.

Can cause missed runs under high load.

Replace

If a job is still running, terminate it and start a fresh one. Use when fresh state is more important than completion.

Previous job is terminated abruptly.

Production-Ready Example

apiVersion: batch/v1
kind: CronJob
metadata:
  name: weekly-report
  namespace: production
spec:
  schedule: "0 9 * * 1"          # Every Monday 9:00 AM
  timeZone: "America/New_York"    # K8s 1.27+ only
  concurrencyPolicy: Forbid       # Don't overlap runs
  successfulJobsHistoryLimit: 3   # Keep last 3 successful jobs
  failedJobsHistoryLimit: 1       # Keep last 1 failed job
  startingDeadlineSeconds: 300    # Skip if 5+ min late

  jobTemplate:
    spec:
      backoffLimit: 2             # Retry up to 2 times
      activeDeadlineSeconds: 600  # Kill job after 10 min

      template:
        spec:
          restartPolicy: OnFailure
          serviceAccountName: report-runner
          containers:
          - name: report
            image: my-report-image:1.2.3
            resources:
              requests:
                cpu: "100m"
                memory: "128Mi"
              limits:
                cpu: "500m"
                memory: "256Mi"
            env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: url

Debugging CronJob Failures

kubectl get cronjobs

List all CronJobs and their last schedule time

kubectl get jobs --selector=job-name=<name>

Find Jobs created by a specific CronJob

kubectl describe cronjob <name>

Check events — including missed/failed runs

kubectl logs -l job-name=<job-name>

Get logs from the Job's pod(s)

kubectl get pods --selector=job-name=<job-name>

List pods for a specific Job

kubectl describe pod <pod-name>

Debug pod-level issues (image pull, OOM, etc.)

Build your Kubernetes CronJob schedule

Use our platform guide and visual builder to create and validate Kubernetes-compatible cron expressions.