Monitor Kubernetes CronJobs — without an operator
One curl line inside the job command reports success or
failure. Absence detection covers everything the job can't report
itself — a suspended CronJob, a missed schedule, a pod that never
started. No agent, no operator, nothing installed in the cluster.
Free, no monitor cap.
CronJob failures live where nobody looks
Kubernetes retries, backs off, records an event — and tells no human anything.
Failures buried in kubectl
A failed Job leaves a red pod and an event — visible only if
someone happens to run
kubectl get jobs in the right namespace. When
backoffLimit is exhausted, the retries stop and so
does the evidence trail.
The job that's never scheduled
suspend: true left over from a migration, a missed
startingDeadlineSeconds, a node pool scaled to zero —
the CronJob doesn't fail, it just never happens. Nothing inside
the job can report that.
The heavyweight alternative
The "proper" fix is kube-state-metrics + Prometheus + Alertmanager and a PromQL alert per job — a full observability stack to learn whether one nightly backup ran.
The dead-man's-switch approach needs none of it: the job pings when it completes, and LastPing alerts when the ping doesn't arrive — whatever the reason. The failure modes the job can't see are covered by the same silence.
Setup: one line in the job command
A copy-paste manifest — adapt the image and command to your workload.
Create a heartbeat monitor
In the console,
create a monitor with the same schedule as your CronJob's
spec.schedule (cron expressions with an IANA
timezone are supported) plus a grace window. Copy the ping URL:
Add the ping to the CronJob manifest
Success pings the monitor URL; failure pings /fail
(so you're alerted immediately) and exits non-zero, which keeps
Kubernetes' own retry and backoff semantics intact:
Minimal images: use busybox wget
Alpine and busybox-based images ship wget even when
curl is absent — the ping accepts GET, HEAD, or
POST, so either client works:
busybox wget has no retry flag; if your image has
curl, prefer it with --retry 3.
Optional: keep the ping URL in a Secret
The ping URL is a capability URL — anyone who has it can ping your monitor. Treat it like a credential:
What this catches
The job reports what it can; the silence reports the rest.
- The workload failed — the
/failping opens an incident immediately, and the non-zero exit still lets Kubernetes retry perbackoffLimit. - The job never ran — suspended CronJob, missed
startingDeadlineSeconds, image pull failure, node pool at zero, controller trouble. No ping in the expected window → incident. - The pod never completed — eviction, OOMKill mid-run, a hung process. The success ping never fires; the grace window raises the alert.
- Recovery — the next successful run closes the incident and sends a recovery notice automatically.
- Flap protection — a run that fails once and recovers within the damping window doesn't page you.
Running the same job outside the cluster too? The pattern is identical for plain cron and systemd timers. For CI pipelines, see monitoring GitHub Actions — or browse all guides.
Questions people ask
Front-loaded answers — the most important fact first.
-
How do I get alerted when a Kubernetes CronJob fails?
Add one
curlline to the job command: run the workload, then on success curl the monitor URL, and on failure curl the/failendpoint and exit non-zero. LastPing opens an incident and alerts you by email, Telegram, Slack, Discord, or webhook — and the non-zero exit keeps Kubernetes' retry and backoff semantics intact. -
Do I need an operator, agent, or Prometheus stack?
No. Nothing is installed in the cluster — the job itself makes one outbound HTTP request (GET, HEAD, or POST) when it finishes.
curlor busyboxwgetboth work, so it runs in minimal images. -
What about CronJobs that never run at all?
That's exactly what absence detection covers. LastPing expects the ping on the schedule you set plus a grace window. A CronJob that is suspended, misses its
startingDeadlineSeconds, can't pull its image, or lives in a cluster whose controller stopped scheduling produces no ping — and the silence itself opens an incident. -
Is this free?
Yes. LastPing is free and fully hosted with no monitor cap and no paid tier. See how it compares to Healthchecks.io and Cronitor.
kubectl won't call you at 3 a.m. This will.
One line in the manifest now beats spelunking through events later. First alert wired up in minutes — and LastPing monitors itself the same way.