1. Know how a CronJob can go quiet
The Kubernetes documentation says a CronJob creates a Job approximately once per schedule, and in some circumstances creates none. If the controller finds more than 100 missed schedules, it does not start the Job and logs "too many missed start times". A suspended CronJob, an image that no longer pulls, or a cluster that was down at the scheduled time all look the same from inside: no Job, and no failure to alert on.
2. Create the heartbeat and store the URL as a Secret
Add a monitor with Check type Heartbeat (cron), set the interval to the schedule's period and a grace period for the run time, and copy the ping URL. Put it in a Kubernetes Secret and expose it to the container as the environment variable PING_URL.
3. Wrap the container command
Set the container's command to run the work and then ping: ["/bin/sh", "-c", "curl -fsS $PING_URL/start; ./run-job && curl -fsS $PING_URL || curl -fsS --data-raw $? $PING_URL/fail"]. The image needs curl or wget. The start ping lets the monitor time each run and flag one that hangs, once you set a maximum runtime on the monitor's page.
4. Set startingDeadlineSeconds and the grace period together
startingDeadlineSeconds is how late Kubernetes may still start a missed run. Make the heartbeat's grace at least that deadline plus the job's normal run time, so a run Kubernetes started late but still started does not page anyone. The check runs from outside the cluster, so a cluster-wide outage is caught too.
Go deeper
The full reference lives in the docs: Heartbeat monitors documentation. Error codes named above are each explained in the error-code reference.