Monitor Kubernetes CronJobs without Prometheus
Kubernetes stores Job and pod status, but a CronJob that never creates a Job produces no application failure to alert on. A dead-man check catches the absence of the expected run, plus explicit failures and stuck executions.
Add one wrapper
Section titled “Add one wrapper”Put backupctl in the workload image and wrap the CronJob’s command:
apiVersion: batch/v1kind: CronJobmetadata: name: nightly-exportspec: schedule: "0 2 * * *" timeZone: "UTC" concurrencyPolicy: Forbid startingDeadlineSeconds: 900 jobTemplate: spec: template: spec: restartPolicy: Never containers: - name: export image: registry.example.com/nightly-export:latest env: - name: BACKPULSE_URL value: https://backpulse.aniicrite.dev - name: BACKPULSE_PING_KEY valueFrom: secretKeyRef: name: backpulse-nightly-export key: ping-key command: - backupctl - run - "--" - /app/exportStore the ping key as a Secret, never inline in the manifest:
kubectl create secret generic backpulse-nightly-export \ --from-literal=ping-key='<check-key>'Configure the check
Section titled “Configure the check”Match the backpulse cron expression and timezone to the Kubernetes schedule. Set grace to cover normal controller and image-pull jitter. Pick the failure threshold on purpose:
1: page on the first missed or failed production run.2or higher: forgive one transient failure for frequent, retryable jobs.
The wrapper sends /start, then /success or /fail with duration and exit
status. backpulse distinguishes a schedule that produced no Job, a Job that
failed, a Job that never finished, a late run, and overlapping starts.
What this does not replace
Section titled “What this does not replace”This is scheduled-work monitoring, not cluster observability. Keep your metrics and logs for node pressure, sizing, and debugging. The dead-man check answers one narrower question: did this specific recurring job run successfully when it was supposed to?