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é.

/etc/cron.d/ — pattern préféré pour les rôles

Section intitulée « /etc/cron.d/ — pattern préféré pour les rôles »
- 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 tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn