Aller au contenu

Surveiller un CronJob Kubernetes

Un CronJob Kubernetes peut cesser de produire des Jobs sans qu’aucun Pod n’échoue : il n’y a alors rien à observer. Un ping envoyé à la fin du conteneur transforme cette absence en alerte.

Un CronJob crée un Job à chaque échéance, et le Job crée un Pod. Les pannes visibles (Pod en erreur, Failed) se surveillent avec les outils habituels. Mais plusieurs situations n’en produisent aucune :

  • le CronJob est suspendu (spec.suspend: true) et le reste sans que personne s’en souvienne ;
  • la politique de concurrence (concurrencyPolicy) fait sauter une exécution : avec Forbid, si la précédente tourne encore, la nouvelle n’est pas créée ;
  • une échéance est manquée au-delà de startingDeadlineSeconds (cluster indisponible, contrôleur redémarré) ;
  • le fuseau horaire n’est pas celui que vous pensiez : le champ spec.timeZone existe depuis Kubernetes 1.27, et sans lui l’heure du contrôleur s’applique ;
  • le cluster entier ou son contrôleur est à l’arrêt.

Dans tous ces cas, aucun Pod n’est créé, donc aucun Pod n’échoue. C’est exactement ce qu’un dead man’s switch détecte.

L’URL de ping est un secret : stockez-la dans un Secret, et appelez-la à la fin du conteneur, seulement en cas de succès.

cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup
spec:
schedule: "0 2 * * *"
timeZone: "Europe/Paris"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: mon-image:latest
command: ["/bin/sh", "-c"]
args:
- |
curl -fsS -m 10 --retry 3 "$PING_URL/start" || true
/app/backup.sh
code=$?
curl -fsS -m 10 --retry 3 "$PING_URL/$code" || true
exit $code
env:
- name: PING_URL
valueFrom:
secretKeyRef:
name: silencewatch
key: ping-url

Le conteneur appelle /start au début, puis l’URL suffixée du code de sortie à la fin : 0 réussit, tout autre code fait passer le check en panne immédiatement. L’image doit contenir curl ; sinon, ajoutez-le ou utilisez un second conteneur.

  • Planification : la même expression cron que spec.schedule, avec le même fuseau horaire.
  • Délai de grâce : plus que la durée normale du job, plus la latence habituelle de démarrage du Pod.
  • Un check par CronJob, avec l’environnement (production, staging) pour ne pas mélanger les clusters.

Voir aussi les exemples pour d’autres environnements et les états d’un check.

Comment savoir si un CronJob Kubernetes ne s’est pas exécuté ?

Faites envoyer un ping à la fin du conteneur et surveillez son arrivée avec SilenceWatch : si le ping manque à l’échéance plus le délai de grâce, vous êtes alerté, que le Pod ait échoué ou n’ait jamais été créé.

Pourquoi un CronJob ne crée-t-il plus de Job ?

Causes courantes : le CronJob est suspendu, la concurrencyPolicy Forbid saute l’exécution quand la précédente tourne encore, une échéance a été manquée au-delà de startingDeadlineSeconds, ou le fuseau horaire n’est pas celui attendu.

Le ping fait-il échouer mon Job s’il est injoignable ?

Pas si vous ajoutez || true après le curl : un ping perdu ne change alors pas le code de sortie du job.