Compte rendu de TP : Déploiement de Chrony et utilisation des Handlers (Atelier 12)¶
Objectif
Déployer et configurer le service de synchronisation NTP Chrony sur un parc Rocky Linux en utilisant un handler pour ne redémarrer le service que lorsque la configuration a effectivement changé illustration concrète de l'idempotence.
Durée
~25 minutes
Objectif du TP¶
L'objectif de cet atelier est de déployer et configurer un service de synchronisation d'horloge NTP (Chrony) sur un parc de machines Rocky Linux. Ce TP met particulièrement l'accent sur le concept d'idempotence via l'utilisation d'un handler : le service ne doit être redémarré que si le fichier de configuration a été effectivement modifié.
1. Préparation de l'environnement¶
Après le démarrage des machines (vagrant up) et la connexion au nœud de contrôle (vagrant ssh control), nous nous déplaçons dans le répertoire de travail pour charger l'environnement automatisé par direnv :
L'inventaire étant déjà configuré avec le groupe [redhat] regroupant nos trois cibles sous Rocky Linux, nous nous plaçons dans le dossier des playbooks pour commencer l'écriture :
2. Écriture du playbook avec Handler¶
Sur Rocky Linux (famille RedHat), le gestionnaire de paquets est dnf, le paquet à installer est chrony et le service correspondant se nomme chronyd.
Pour assurer l'idempotence, nous utilisons la directive notify dans la tâche de copie du fichier de configuration. Cette directive appellera un handler qui se chargera de redémarrer le service (state: restarted) uniquement si une modification a eu lieu.
Nous créons le fichier chrony.yml :
---
# chrony.yml
- hosts: redhat
tasks:
- name: Install chrony
dnf:
name: chrony
state: present
- name: Start & enable chrony
service:
name: chronyd
state: started
enabled: true
- name: Configure chrony
copy:
dest: /etc/chrony.conf
mode: '0644'
content: |
# /etc/chrony.conf
server 0.fr.pool.ntp.org iburst
server 1.fr.pool.ntp.org iburst
server 2.fr.pool.ntp.org iburst
server 3.fr.pool.ntp.org iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony
notify: Restart chronyd
handlers:
- name: Restart chronyd
service:
name: chronyd
state: restarted
...
3. Validation syntaxique et première exécution¶
Avant de lancer le déploiement, nous prenons l'habitude de valider la syntaxe YAML du playbook à l'aide de l'outil yamllint :
Nous exécutons ensuite le playbook une première fois :
Lors de cette première exécution,ansible va installer le paquet, démarrer le service et copier la nouvelle configuration. La copie modifiant l'état du système (changed), la notification est déclenchée et le handler Restart chronyd est exécuté à la fin du play.
4. Vérification de l'idempotence¶
Pour vérifier que notre playbook est parfaitement idempotent, nous relançons exactement la même commande :
Résultat attendu :
1. Les tâches d'installation et de démarrage du service affichent ok (rien n'a changé).
2. La tâche de copie de la configuration affiche également ok (le contenu correspond déjà à ce qui est défini dans le playbook).
3. Le handler n'est pas déclenché. Le récapitulatif final (PLAY RECAP) doit indiquer changed=0.

Le service chronyd n'est donc pas redémarré inutilement, validant ainsi l'idempotence de notre code.
5. Nettoyage de l'environnement¶
L'atelier étant validé, nous quittons le Control Host et procédons à la destruction des machines virtuelles pour libérer les ressources :
Je retiens
notifydéclenche un handler uniquement si la tâche a produit un changement (changed).- Les handlers s'exécutent à la fin du play, pas immédiatement après le
notify. yamllintest une bonne habitude pour valider la syntaxe YAML avant l'exécution.- L'idempotence se vérifie en relançant le playbook :
changed=0confirme qu'aucune action inutile n'est effectuée.
Cheatsheet¶
| Symptôme | Cause probable | Correction |
|---|---|---|
| Le handler n'est jamais exécuté même après modification du fichier | Le nom dans notify: ne correspond pas exactement au name: du handler (casse, espaces) |
Copier-coller le nom du handler dans la directive notify: ; les deux doivent être strictement identiques |
| Le handler se déclenche sur chaque exécution | La tâche notifiante n'est pas idempotente (par ex. shell: sans changed_when) |
Vérifier que la tâche qui notifie ne repasse pas à changed en permanence |
Une tâche après le notify échoue → le handler n'est jamais joué |
Par défaut les handlers s'exécutent en fin de play, donc sautés si une tâche suivante échoue | Utiliser force_handlers: true au niveau du play, ou forcer avec meta: flush_handlers au bon moment |
| Besoin de redémarrer le service tout de suite (avant la fin du play) | Comportement par défaut = fin du play | Ajouter une tâche ansible.builtin.meta: flush_handlers après le notify (cf. Workshop 13) |
yamllint affiche too many blank lines ou line too long |
Style YAML non conforme à la config par défaut | Ajuster le style ou créer .yamllint avec des règles adaptées au projet |
Sources (principales)¶
- Docs
ansibleHandlers: running operations on change - Docs
ansibleHandlers : directivelisten(topics) - Docs
ansiblemetamodule (tâches spéciales) - Docs
ansiblemeta: flush_handlers - Docs
ansibleforce_handlers(forcer l'exécution en cas d'erreur) - Docs
ansiblenotifyavec plusieurs handlers - Chrony Documentation officielle
- Chrony
chronycreference (tracking,sources)
Précédent : Simple Web Server Suite : Variables