Quick Summary — TL;DR
A Kubernetes CronJob is a built-in resource that runs containerized workloads on a repeating schedule defined by a cron expression. Each time the schedule fires, the CronJob controller creates a Kubernetes Job, which in turn creates one or more Pods to execute the task. When the Pod completes, the Job is marked as finished and eventually cleaned up based on your retention settings.
The CronJob controller in the kube-controller-manager checks all CronJob resources approximately every 10 seconds. When a CronJob's schedule matches the current time, the controller creates a new Job object. The Job controller then creates a Pod from the template, the Pod runs to completion, and the Job records whether it succeeded or failed.
apiVersion: batch/v1
kind: CronJob
metadata:
name: db-cleanup
spec:
schedule: "0 3 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
jobTemplate:
spec:
template:
spec:
containers:
- name: cleanup
image: myapp/db-cleanup:latest
restartPolicy: OnFailure | Field | Purpose |
|---|---|
schedule | A five-field cron expression defining when to create Jobs |
concurrencyPolicy | Allow (default), Forbid (skip if previous still running), or Replace (kill previous, start new) |
startingDeadlineSeconds | How many seconds past the scheduled time a Job can still be created — missed beyond this window is skipped |
successfulJobsHistoryLimit | Number of completed Jobs to retain (default 3) |
failedJobsHistoryLimit | Number of failed Jobs to retain (default 1) |
suspend | Set to true to pause the CronJob without deleting it |
The concurrencyPolicy field addresses a common concurrency problem: what happens when a new run is due but the previous one hasn't finished. Forbid skips the new run entirely, Replace terminates the old run and starts fresh, and Allow lets them overlap. For most database maintenance and cleanup tasks, Forbid is the safest choice.
backoffLimit restarts the Pod on failure, but it uses a fixed exponential delay (10s, 20s, 40s...) with no customization. For tuned retry policies with exponential backoff and jitter, you need external logic.kubectl, but there's no built-in dashboard for execution history, response times, or failure trends.timeZone field (stable since Kubernetes 1.27) lets you set a timezone, but older clusters default to the controller's timezone, which can cause confusion.Kubernetes CronJobs are effective for cluster-internal tasks like database maintenance, log rotation, and cache warming. But when you need to trigger HTTP endpoints across services, get detailed execution logs with response bodies, or receive alerts on failure, an external scheduler like Recuro complements the CronJob model. You can use CronJobs for in-cluster work and an HTTP scheduler for cross-service orchestration, with a unified view of all your scheduled workloads. Validate your schedule expressions with the cron expression generator before deploying.
A Job runs a task once (or a fixed number of times) and terminates. A CronJob creates Jobs automatically on a repeating cron schedule. Think of the CronJob as the scheduler and the Job as a single execution.
Run kubectl describe cronjob <name> and check the Events section. Common causes: concurrencyPolicy: Forbid skipped the run because the previous Job was still active, the startingDeadlineSeconds window was exceeded, or the CronJob is suspended.
Yes. Use kubectl create job --from=cronjob/<name> manual-run to create a one-off Job from an existing CronJob's template without waiting for the next scheduled time.
Kubernetes CronJobs use standard cron expressions and act as the cluster-native equivalent of the cron daemon. Each execution is a job runner backed by a worker process in a Pod, with concurrency control built in. For scheduled tasks that span beyond the cluster, pairing CronJobs with an external HTTP scheduler provides the cross-service reach and observability that Kubernetes doesn't offer natively.
Recuro handles cron scheduling, retries, alerts, and execution logs -- so you can focus on building your product.
No credit card required