Skip to content

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 :

cd ~/ansible/projets/ema/

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 :

cd playbooks

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 :

yamllint chrony.yml
Si la commande ne retourne rien, la syntaxe est correcte.

Nous exécutons ensuite le playbook une première fois :

ansible-playbook chrony.yml
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 :

ansible-playbook chrony.yml

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. Validation de l'idempotence

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 :

exit
vagrant destroy -f

Je retiens

  • notify dé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.
  • yamllint est une bonne habitude pour valider la syntaxe YAML avant l'exécution.
  • L'idempotence se vérifie en relançant le playbook : changed=0 confirme 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)


Précédent : Simple Web Server Suite : Variables