Pages

Monday, 3 August 2026

Kubernetes CronJob


A Kubernetes CronJob creates and manages short-lived Jobs on a scheduled, repeating basis. It is the Kubernetes equivalent of a standard Unix crontab file, making it ideal for periodic tasks like database backups, report generation, or maintenance scripts.

Minimal Example Manifest

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-backup
spec:
  schedule: "0 2 * * *" # Runs every day at 02:00 UTC
  timeZone: "Etc/UTC"   # Optional: set preferred timezone (Kubernetes 1.27+)
  concurrencyPolicy: Forbid
  startingDeadlineSeconds: 100
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup-task
            image: alpine:latest
            command:
            - /bin/sh
            - -c
            - echo "Running database backup..."; sleep 5
          restartPolicy: OnFailure


Schedule Syntax Quick Reference


The schedule field uses standard cron syntax with 5 fields:

minute hour day-of-month month day-of-week

Schedule Format Interpretation


*    * * * *             Every minute
*/15 * * * *              Every 15 minutes
0    0 * * *              Every day at midnight
0    9 * * 1              Every Monday at 9:00 AM

Critical Settings

  • concurrencyPolicy: Controls how overlapping executions are handled when a previous run hasn't finished:
    • Allow (default): Runs concurrent jobs simultaneously. 
    • Forbid: Skips the new job if the previous one is still running. 
    • Replace: Cancels the currently running job and starts the new one. 
  • startingDeadlineSeconds: The deadline (in seconds) for starting a job if it missed its scheduled time (e.g., cluster was temporarily down).
  • successfulJobsHistoryLimit / failedJobsHistoryLimit: Number of completed or failed Job/Pod records to keep for auditing before automatic cleanup.
  • restartPolicy: Must be set on the pod template spec to either OnFailure or Never (Always is invalid for Jobs).  

Helpful kubectl Commands


Task                                            Command 
====                                           ========
List CronJobs                              kubectl get cronjobs
Inspect configuration                  kubectl describe cronjob <name>
Manually trigger immediately    kubectl create job --from=cronjob/<cronjob-name>                        <manual-job-name>
Pause schedule                           kubectl patch cronjob <name> -p '{"spec":                             {"suspend":true}}'
View logs of latest run               kubectl logs job/<job-name>



CronJobs Inner Mechanism


Under the hood, Kubernetes CronJobs rely on a decentralized control loop pattern. They are not handled by a traditional Linux cron daemon running on a single server, but rather by the Kubernetes Control Plane through cascading controllers.

How CronJobs Are Implemented


The implementation follows a 3-tier hierarchical model:

CronJob Object --> Job Object --> Pod(s)

Rather than running code directly, a CronJob acts as a factory for Job objects, which in turn manage the Pods where your container actually executes


┌─────────────────────────────────────────────────────────┐
│                 kube-controller-manager                 │
│                                                         │
│   ┌─────────────────┐       Creates      ┌─────────┐  │
│   │ CronJob Controller│ ─────────────────> │   Job   │  │
│   └──────────────────┘                    └───┬───┘  │
└──────────────────────────────────────────────────┼──────┘
                                                   │
                                                Creates
                                                   │
                                                   ▼
                                              ┌─────────┐
                                              │   Pod   │
                                              └─────────┘


The Control Loop Mechanism

  1. Synchronization Loop: The CronJob Controller runs inside kube-controller-manager. Every ~10 seconds, it iterates through all CronJob objects defined in the cluster.  
  2. Schedule Checking: The controller parses the schedule field (e.g., 0 * * * *) and compares the current time against the last time the job was executed.  
  3. Job Spawning: If a run is due, the CronJob controller reads the embedded jobTemplate and creates an actual Job resource.  
  4. Execution: The cluster's separate Job Controller detects the newly created Job resource and spawns one or more Pods to execute your container workload to completion.  
  5. Garbage Collection: Depending on successfulJobsHistoryLimit and failedJobsHistoryLimit, the CronJob controller periodically deletes old completed Job objects (and their associated logs/pods).  


Who Controls Them?


Control over CronJobs is split between system components (automation) and users/roles (permissions).

System Component Control

  • kube-controller-manager: The core control plane component where the CronJob controller code actually executes. If this component is down, scheduled triggers will pause until it recovers.  
  • kube-apiserver: Stores the desired state in etcd and validates user manifests.
  • kube-scheduler: Assigns the individual Pods spawned by the resulting Jobs to healthy worker nodes.

User & Permission Control (RBAC)

Human administrators and automated service accounts control CronJobs via Kubernetes Role-Based Access Control (RBAC):

Role / Action              Required API Permissions (batch/v1)
=============     ==============================
Manage Schedules     create, update, patch, delete on cronjobs
View Status                get, list, watch on cronjobs
Manual Trigger          create permissions on jobs (to invoke kubectl create job --from=cronjob/...)


Example RBAC Role for CronJob Operators:


apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: prod
  name: cronjob-operator
rules:
- apiGroups: ["batch"]
  resources: ["cronjobs", "jobs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]


Technical Considerations

  • At-Least-Once Execution: Kubernetes schedules are designed around at-least-once execution semantics. Due to control loop timing or network hiccups, a scheduled job might occasionally run twice or run slightly late. Workloads should always be designed to be idempotent
  • Timezones: Controller clocks default to UTC or the local time of kube-controller-manager unless explicit timezones are passed via spec.timeZone (supported in K8s 1.27+). 


CronJob is a controller object


In Kubernetes, a controller is a control loop that watches the state of your cluster through the API server and makes changes attempting to move the current state toward the desired state.

Here is how a CronJob fits into the controller pattern:

Why CronJob is a Controller

  • Custom Resource / Spec & Status Model: Like Deployment, ReplicaSet, and Job, a CronJob has an API object schema (spec defining desired behavior, status tracking execution state).
  • Control Loop Execution: The CronJob implementation runs as a control loop inside the kube-controller-manager component.
  • Cascading Controller Pattern: CronJob sits at the top of a controller hierarchy:

CronJob Controller --[creates/manages]--> Job Controller --[creates/manages]--> Pods

  • The CronJob Controller reconciles the CronJob spec: it checks the schedule, creates Job resources when a execution is due, cleans up old jobs based on history limits, and handles concurrency policies.
  • The Job Controller reconciles those created Job resources to manage individual Pods to completion.

Summary Table


Controller                        API Group      What it Watches      What it Creates/Manages
========                       =========     =============      ===================
CronJob Controller            batch/v1          CronJob specs            Job objects
Job Controller                    batch/v1          Job specs                    Pod objects
Deployment Controller      apps/v1           Deployment specs      ReplicaSet objects


No comments:

Post a Comment