Choisir la bonne politique de rattrapage pour les tâches cron manquées
Lorsque les serveurs redémarrent pendant des tâches planifiées, des omissions silencieuses ou d'importants retards peuvent entraîner une perte de données ou des bannissements d'API. Découvrez comment configurer systemd, Kubernetes et des scripts personnalisés
Traduit automatiquement depuis l’original en anglais.
Un serveur redémarrant pour appliquer des correctifs du noyau à 01h55 et revenant en ligne à 02h10 a fait disparaître sans laisser de trace une tâche de sauvegarde critique programmée pour 02h00. Comme les démons cron standards ne regardent pas en arrière dans le temps, le système a silencieusement ignoré l'exécution, laissant l'organisation sans sauvegardes pendant toute une journée. Cet incident met en évidence un mode de défaillance courant mais souvent négligé dans les infrastructures auto-hébergées, où le comportement par défaut des outils de planification ne correspond pas aux exigences de continuité d'activité.
Ce qui s'est passé
Le problème fondamental réside dans la manière dont différents systèmes de planification interprètent les écarts temporels causés par les indisponibilités. Dans l'incident rapporté, le démon cron classique vérifiait les tâches correspondant à la minute courante. Comme la machine était hors ligne à 02h00, cette minute spécifique n'a jamais existé du point de vue du démon. Par conséquent, aucune erreur n'a été journalisée, aucune alerte n'a été déclenchée, et la prochaine exécution réussie n'a eu lieu que le jour suivant. Ce comportement d'« omission silencieuse » est le défaut de nombreux outils de planification Unix traditionnels, ce qui est dangereux pour les tâches critiques comme les dumps de base de données ou les scans de sécurité.
À l'inverse, une autre équipe a connu l'extrême opposé. Leur ordonnanceur était en panne pendant six heures et, au retour en service, il a tenté de « rattraper » le retard en lançant simultanément 72 instances d'une tâche de synchronisation toutes les cinq minutes. Cette rafale d'activité a saturé une API partenaire, déclenchant des limites de débit qui ont perturbé le service pour le reste de la journée. Les deux équipes ont souffert parce qu'elles n'avaient pas explicitement défini de politique de rattrapage pour leurs tâches. Le comportement par défaut de l'ordonnanceur, plutôt qu'un choix d'ingénierie délibéré, a dicté le résultat.
Détails clés
- Trois politiques principales : Lorsqu'une heure planifiée est manquée, les systèmes généralement soit ignorent l'exécution, soit l'exécutent une fois en retard, soit tentent d'exécuter chaque créneau manqué.
- Cron classique : Ignore par défaut entièrement les exécutions manquées, sans mécanisme de rattrapage ni journalisation de l'événement manqué.
- Timers systemd : L'utilisation de
Persistent=truepermet à un timer de se déclencher une fois peu après le démarrage si une exécution a été manquée, idéal pour les sauvegardes quotidiennes. - Kubernetes CronJobs : Peut être configuré avec
startingDeadlineSecondspour autoriser des démarrages tardifs dans une fenêtre donnée, etconcurrencyPolicy: Forbidpour empêcher les exécutions chevauchantes. - Tâches par période : Les tâches comme la facturation nécessitent le traitement de chaque intervalle manqué séquentiellement, ce qui doit être géré par la logique de la tâche elle-même, et non par l'ordonnanceur.
- La détection est cruciale : Quelle que soit la politique, les équipes doivent mettre en place une surveillance pour détecter quand une tâche a été ignorée ou exécutée avec un retard significatif.
Contexte
Pour comprendre ces modes de défaillance, il est utile de distinguer les synchronisations sans état (stateless) des opérations avec état (stateful). Une synchronisation sans état, comme la récupération de données météo publiques, n'a généralement pas besoin de récupérer des données passées ; la prochaine exécution récupérera simplement l'état actuel. Pour celles-ci, ignorer l'exécution est souvent acceptable. Cependant, les opérations avec état comme les sauvegardes ou la facturation financière accumulent une dette lorsqu'elles manquent un cycle. Une sauvegarde manquée signifie que les données restent non protégées plus longtemps, et un cycle de facturation manqué signifie une fuite de revenus.
Le cron traditionnel est conçu pour la simplicité, pas pour la résilience. Il suppose que la machine est toujours allumée. Des alternatives modernes comme les timers systemd et anacron ont été construites pour gérer les machines qui dorment ou redémarrent fréquemment. Anacron, par exemple, suit le dernier temps d'exécution sur disque et lance les tâches si leur période (quotidienne, hebdomadaire) est écoulée depuis la dernière exécution. Comprendre quel outil correspond aux besoins de fiabilité de votre charge de travail est essentiel pour une conception robuste de l'infrastructure.
Pourquoi c'est important
Pour les équipes qui exploitent leur propre logiciel, le comportement par défaut de votre ordonnanceur est un risque caché. Si vous comptez sur le cron standard pour les sauvegardes quotidiennes de base de données, un simple redémarrage pendant les fenêtres de maintenance peut vous laisser vulnérable pendant 24 heures sans aucune alerte. Ce silence est particulièrement dangereux car il crée un faux sentiment de sécurité. Les équipes opérationnelles peuvent voir des voyants verts sur leurs tableaux de bord parce que le démon cron tourne, sans savoir que la charge de travail réelle a été ignorée.
Inversement, des mécanismes de rattrapage agressifs peuvent provoquer un déni de service auto-infligé. Comme vu dans l'exemple de limitation de débit de l'API, rejouer aveuglément les tâches manquées peut submerger les services en aval ou épuiser les ressources locales. Cela est particulièrement pertinent pour les architectures microservices où l'arriéré d'un service peut entraîner des défaillances en cascade dans l'ensemble du système. Définir explicitement comment chaque tâche gère les indisponibilités évite ces surprises et garantit que les actions de récupération sont proportionnelles à l'importance de la tâche.
Ce que vous pouvez faire
- Auditez vos tâches cron : Identifiez quelles tâches sont critiques (sauvegardes, facturation) et lesquelles sont éphémères (synchronisations, logs). Documentez le comportement souhaité pour chacune si une exécution est manquée.
- Migrez les tâches critiques vers les timers systemd : Utilisez
Persistent=truepour les tâches quotidiennes ou hebdomadaires afin de garantir qu'elles s'exécutent une fois après un redémarrage si elles ont été manquées. - Configurez les délais Kubernetes : Définissez
startingDeadlineSecondssur les CronJobs pour spécifier une fenêtre valide pour l'exécution tardive, empêchant les retries indéfinies ou les omissions totales. - Implémentez une logique de rattrapage idempotente : Pour les tâches par période comme la facturation, écrivez la tâche pour calculer les intervalles manquants à partir d'un enregistrement de base de données plutôt que de compter sur l'ordonnanceur pour déclencher plusieurs exécutions.
- Ajoutez une surveillance par battement de cœur (heartbeat) : Utilisez des outils de surveillance externes pour alerter si une tâche n'a pas signalé son succès dans sa période attendue plus une marge de grâce.
- Journalisez les heures planifiées vs réelles : Assurez-vous que les logs de votre application distinguent le moment où une tâche aurait dû s'exécuter et celui où elle a réellement commencé, pour aider au débogage des problèmes de latence.



