Introduction
Un paquet installé, un fichier de configuration existant et un service qui répond sont des résultats différents. Vous gérerez chacun explicitement : installer et supprimer un utilitaire, configurer nginx, déclarer son état d'exécution et recharger la configuration modifiée par un handler. Les réponses HTTP réelles des deux nœuds gérés établiront que le service fonctionne.
Déclarer les états installé et absent des paquets
Dans cette étape, vous installerez un petit utilitaire, l'examinerez et le supprimerez au moyen d'une déclaration de paquet réutilisable.
Le module apt gère les paquets Ubuntu sur l'hôte géré. Son state: present demande l'installation et state: absent la suppression. Cet environnement inclut des listes de paquets préparées et des téléchargements en cache : conservez donc update_cache: false ; actualiser les listes ou demander les dernières versions ajouterait des dépendances réseau inutiles. Les politiques de mise à jour en production peuvent différer.
Entrez dans le projet du contrôleur :
cd /home/labex/project
Créez un playbook dont une variable sélectionne l'état souhaité du paquet tree. Les opérations sur les paquets nécessitent become sur les cibles. install_recommends: false évite les paquets recommandés facultatifs.
cat > packages.yml <<'YAML'
- name: Declare a utility package state
hosts: all
gather_facts: false
become: true
vars:
utility_state: present
tasks:
- name: Converge the tree package
ansible.builtin.apt:
name: tree
state: "{{ utility_state }}"
update_cache: false
install_recommends: false
YAML
Installez l'utilitaire :
ansible-playbook packages.yml
La commande tree affiche les arborescences de répertoires ; ici, son option de version démontre que l'exécutable est réellement installé sur chaque nœud géré :
ansible all -m ansible.builtin.command -a 'tree --version'
Chaque cible doit renvoyer une version de tree. Répétez le playbook ; les paquets présents ne doivent pas nécessiter une autre installation :
ansible-playbook packages.yml
Demandez maintenant l'absence avec une variable supplémentaire au lieu de modifier la tâche réutilisable :
ansible-playbook packages.yml -e utility_state=absent
Répétez le même état d'absence souhaité. Les deux lignes du récapitulatif doivent maintenant afficher changed=0, failed=0 et unreachable=0 :
ansible-playbook packages.yml -e utility_state=absent
L'état d'un paquet est une déclaration sur l'installation, pas une preuve qu'un service s'exécute ou répond. Laissez tree absent tandis que l'étape suivante déploie nginx.
Configurer et démarrer un véritable service web
Dans cette étape, vous installerez nginx, déploierez une configuration complète validée et maintiendrez explicitement son service en cours d'exécution.
Les deux nœuds gérés sont des conteneurs avec des points de connexion SSH et des systèmes de fichiers séparés. Ils n'exécutent pas systemd. Le module service utilise leur gestionnaire de services disponible ; n'exécutez pas systemctl sur ces cibles. Nous gérerons l'état d'exécution actuel plutôt que de promettre une politique de démarrage systemd.
Créez une page statique sur le contrôleur. Elle se termine par un saut de ligne afin que ses octets gérés exacts soient prévisibles :
printf 'Ansible service ready\n' > page.txt
Écrivez une configuration nginx complète. events et http sont des contextes nginx de premier niveau, server définit un site, listen choisit le port 8080, root sélectionne son répertoire de documents et index sélectionne la page des requêtes /. Ce sont des paramètres nginx et non du YAML Ansible.
cat > nginx-course.conf <<'NGINX'
events {}
http {
server {
listen 8080;
root /var/www/ansible-site;
index index.html;
}
}
NGINX
Créez le playbook de déploiement. La tâche apt utilise policy_rc_d: 101 pour empêcher le gestionnaire de paquets de démarrer implicitement nginx ; la tâche service ultérieure déclare explicitement l'état d'exécution. Le validate de la tâche copy exécute le test de configuration de nginx sur un candidat temporaire (%s) avant de remplacer la destination.
Un handler est une action nommée répertoriée sous handlers. Une tâche de configuration modifiée notifie Reload nginx, qui s'exécute une seule fois à la fin du play. Aucune modification de configuration signifie aucune notification. La tâche service ordinaire utilise started, qui maintient un service déjà lancé sans redémarrage inconditionnel.
cat > web.yml <<'YAML'
- name: Deploy a working web service
hosts: all
gather_facts: false
become: true
tasks:
- name: Install nginx without refreshing the prepared package lists
ansible.builtin.apt:
name: nginx
state: present
update_cache: false
install_recommends: false
policy_rc_d: 101
- name: Prepare the site directory
ansible.builtin.file:
path: /var/www/ansible-site
state: directory
owner: root
group: root
mode: "0755"
- name: Deploy the static page
ansible.builtin.copy:
src: /home/labex/project/page.txt
dest: /var/www/ansible-site/index.html
owner: root
group: root
mode: "0644"
- name: Validate and deploy nginx configuration
ansible.builtin.copy:
src: /home/labex/project/nginx-course.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: "0644"
validate: /usr/sbin/nginx -t -c %s
notify: Reload nginx
- name: Keep nginx running
ansible.builtin.service:
name: nginx
state: started
handlers:
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
YAML
Vérifiez la syntaxe, puis appliquez le déploiement :
ansible-playbook web.yml --syntax-check
ansible-playbook web.yml
Les deux nœuds doivent installer nginx, recevoir les fichiers et démarrer avec succès. Une première modification de configuration programme aussi le handler de rechargement. Vérifier uniquement une version de paquet ne démontrerait aucun de ces comportements du service.
curl est un client HTTP. Son option --fail traite un statut HTTP infructueux comme un échec de commande ; --silent supprime la progression et --show-error conserve les détails d'échec. Exécutez-le sur chaque hôte géré vers sa propre interface de bouclage :
ansible all -m ansible.builtin.command -a 'curl --fail --silent --show-error http://127.0.0.1:8080/'
Chaque résultat doit contenir Ansible service ready. Le contrôleur et chaque cible possèdent des interfaces de bouclage séparées ; cette commande vérifie les deux services cibles plutôt que le contrôleur.
Appliquer une modification de configuration par un handler
Dans cette étape, vous modifierez un paramètre nginx actif, observerez le handler et confirmerez le paramètre par une réponse HTTP.
La directive nginx server_tokens contrôle si les en-têtes de réponse exposent la version de nginx. Ajoutez server_tokens off dans http en remplaçant la configuration du contrôleur par cette version complète :
cat > nginx-course.conf <<'NGINX'
events {}
http {
server_tokens off;
server {
listen 8080;
root /var/www/ansible-site;
index index.html;
}
}
NGINX
Appliquez le même playbook :
ansible-playbook web.yml
La copie de configuration doit indiquer changed et notifier Reload nginx sur les deux hôtes. Le handler recharge le service en cours après validation de la nouvelle configuration. Son exécution rend la configuration effective ; copier simplement un fichier ne démontre pas ce que le processus a chargé.
Le -I de curl demande les en-têtes HTTP. Examinez la réponse réelle du service sur les deux hôtes :
ansible all -m ansible.builtin.command -a 'curl --fail --silent --show-error -I http://127.0.0.1:8080/'
Les deux réponses doivent avoir un statut HTTP réussi et un en-tête Server égal à nginx sans suffixe de version. D'autres champs d'en-tête, tels que les dates, varient.
Répétez le playbook complet :
ansible-playbook web.yml
Les deux hôtes doivent indiquer changed=0 sans tâche en échec ou inaccessible, et aucun handler de rechargement ne doit être programmé. La page statique reste disponible, tree reste absent et nginx reste installé et en cours d'exécution.
Résumé
Vous avez déclaré la présence et l'absence de paquets, séparé l'installation de l'état d'exécution du service et déployé une configuration nginx complète avec validation du candidat. Une configuration modifiée a notifié un handler de rechargement, les réponses HTTP réelles ont établi le comportement actif et une répétition inchangée a évité des changements ou rechargements supplémentaires.



