Aller au contenu
Infrastructure as Code medium

Module cron Ansible : planifier des jobs idempotents

9 min de lecture

Logo Ansible

ansible.builtin.cron gère les jobs cron avec idempotence garantie via le name:. Chaque job est identifié par son nom unique que Ansible inscrit en commentaire (#Ansible: <name>) au-dessus de la ligne du job. À chaque run, le job est mis à jour au lieu d'être empilé.

Le module sait gérer :

  • la crontab utilisateur (crontab -l), défaut ;
  • les fichiers /etc/cron.d/* via cron_file:, préférable pour la lisibilité ;
  • les variables d'environnement (MAILTO, PATH) au-dessus des jobs (env: true) ;
  • la désactivation (job commenté mais conservé pour référence).
  • La différence crontab user vs /etc/cron.d/, quand utiliser quoi.
  • Le mécanisme du name:, pourquoi il est obligatoire et comment Ansible s'en sert.
  • Comment poser des variables d'environnement (MAILTO, PATH) avec env: true.
  • L'option disabled: true, désactiver sans supprimer.
  • Connaître la syntaxe cron (5 champs : minute, hour, day, month, weekday).
  • Avoir cronie (RHEL) ou cron (Debian) installé sur le managed node, généralement présent par défaut.

name: est obligatoire et sert d'identifiant unique pour le job. Ansible l'inscrit en commentaire au-dessus de la ligne :

#Ansible: Backup horaire
0 * * * * root /usr/local/bin/backup.sh

Au prochain run, Ansible cherche #Ansible: Backup horaire, remplace la ligne juste en dessous par le job actualisé. Conséquence : idempotence garantie, jamais de duplication, jamais d'orphelin.

Ne jamais modifier le commentaire #Ansible: à la main, Ansible perdrait le repère et empilerait un nouveau job.

- name: Backup quotidien dans la crontab de root
ansible.builtin.cron:
name: "Backup base de donnees"
minute: "0"
hour: "2"
job: "/usr/local/bin/backup-db.sh > /var/log/backup.log 2>&1"

Sans cron_file:, le job va dans crontab -l -u root (ou l'utilisateur spécifié via user:). C'est l'équivalent de crontab -e exécuté en idempotent.

Inconvénient : la crontab user n'est pas dans /etc/, donc pas de configuration as code visible avec un simple cat /etc/cron.d/. Préférer cron_file: pour la traçabilité.

- name: Healthcheck monitoring (toutes les 5 min)
ansible.builtin.cron:
name: "Healthcheck monitoring"
minute: "*/5"
job: "/usr/local/bin/healthcheck.sh"
cron_file: monitoring
user: root

cron_file: monitoring crée le fichier /etc/cron.d/monitoring. Plusieurs jobs peuvent y être ajoutés via plusieurs tâches cron: avec le même cron_file: mais des name: différents.

Avantages :

  • Fichier visible dans /etc/cron.d/, review facile.
  • Spécifie le user: sur chaque ligne (contrairement à crontab user où tout est sous l'utilisateur courant).
  • Versionnable proprement (un fichier par rôle).
- name: Definir MAILTO pour les jobs lab
ansible.builtin.cron:
name: MAILTO
env: true
value: admin@lab.local
cron_file: lab-rhce
user: root

env: true change la sémantique : name: devient le nom de la variable, value: est sa valeur. La ligne générée est MAILTO="admin@lab.local" (Ansible quote automatiquement).

Variables utiles :

  • MAILTO, destinataire des emails de cron (sortie stderr du job).
  • PATH, défini par défaut très restrictif sur la plupart des systèmes (/usr/bin:/bin). Override si vos scripts ont besoin de /opt/myapp/bin.
  • SHELL, défaut /bin/sh. Override si vos jobs ont besoin de bash.
- name: Suspendre temporairement le backup
ansible.builtin.cron:
name: "Backup base de donnees"
minute: "0"
hour: "2"
job: "/usr/local/bin/backup-db.sh"
disabled: true

disabled: true commente la ligne du job dans la crontab/le fichier, le job est conservé pour référence mais ne s'exécute plus. Pour le réactiver, repasser disabled: false.

Cas d'usage : maintenance programmée, debugging d'un script qui plante, plans annulés.

FormeÉquivalentUsage
special_time: hourly0 * * * *Toutes les heures
special_time: daily0 0 * * *Tous les jours à minuit
special_time: weekly0 0 * * 0Tous les dimanches à minuit
special_time: monthly0 0 1 * *Le 1er de chaque mois à minuit
special_time: reboot@rebootÀ chaque démarrage
- name: Job hourly avec raccourci
ansible.builtin.cron:
name: "Healthcheck rapide"
special_time: hourly
job: "/usr/local/bin/healthcheck.sh"

special_time: exclut les options minute/hour/day/month/weekday, utiliser soit l'un, soit les autres.

- name: Supprimer l ancien job de migration
ansible.builtin.cron:
name: "Migration v1 vers v2"
state: absent
cron_file: lab-rhce
user: root

Ansible cherche le commentaire #Ansible: Migration v1 vers v2 et supprime cette ligne + la ligne du job juste en dessous. Sans state: absent, un job renommé/déplacé devient orphelin, toujours faire le ménage explicite.

SymptômeCauseFix
Jobs empilés à chaque runname: modifié entre 2 runsNe jamais changer le name: (clé d'identification)
MAILTO=admin@lab.local n'envoie rienPas de MTA installéInstaller postfix ou rediriger les jobs avec > /dev/null 2>&1
PATH: non pris en compteenv: true oublié, name: PATH créé un job nommé "PATH"Ajouter env: true
cron_file: créé mais perms incorrectesLe module ne gère pas les permissions, Linux veut 0644Combiner avec une tâche file: mode: "0644" post-création
Job ne tourne pasService crond arrêtésystemd_service: name=crond state=started enabled=true
  • name: est obligatoire et sert de clé d'idempotence, ne jamais le modifier après création.
  • cron_file: dans /etc/cron.d/ est préférable à la crontab user, review et versioning faciles.
  • env: true pour les variables (MAILTO, PATH, SHELL), pas dans la même tâche que les jobs.
  • disabled: true désactive sans supprimer, utile pour les maintenances.
  • special_time: hourly|daily|weekly|monthly|reboot raccourcit les schedules courants.

Cette page a un lab d'accompagnement : labs/modules-services/cron/ dans stephrobert/ansible-training.

Challenge, sur db1.lab :

  1. Créer /etc/cron.d/lab-rhce avec :
    • MAILTO=admin@lab.local
    • Job Backup horaire à minute 0 de chaque heure.
    • Job Cleanup quotidien à 3h du matin.
  2. Vérifier l'idempotence (pas de duplication au second run).

Validation pytest+testinfra :

Fenêtre de terminal
ansible-playbook solution.yml
ansible-playbook solution.yml # Doit etre ok=N, changed=0
pytest -v labs/modules-services/cron/challenge/tests/

5 tests vérifient l'existence du fichier, la variable MAILTO, les 2 jobs et les markers #Ansible:.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn