Bonnes pratiques
Les bonnes pratiques Ansible ne sont pas des conventions arbitraires. Elles répondent à des problèmes réels : playbooks qui cassent en prod, debugging de 3h pour une variable surchargée, rôle non réutilisable parce qu'il hardcode ses valeurs. Ce qui suit est tiré de l'expérience terrain.
Nommer toutes les tâches
Une tâche sans name est illisible dans les logs et impossible à retrouver dans un playbook de 200 lignes. Le nom doit être descriptif et refléter l'intention, pas la mécanique :
# Mauvais
- ansible.builtin.apt:
name: nginx
state: present
# Bon
- name: Installer nginx
ansible.builtin.apt:
name: nginx
state: present
# Encore mieux (contexte + action)
- name: Installer nginx (serveur web principal)
ansible.builtin.apt:
name: nginx
state: presentUtiliser les modules dédiés plutôt que command/shell
Chaque appel à command ou shell brise l'idempotence et rend le playbook plus fragile. Si un module existe, l'utiliser :
# Mauvais
- ansible.builtin.shell: "systemctl restart nginx"
# Bon
- ansible.builtin.systemd:
name: nginx
state: restarted
# Mauvais
- ansible.builtin.shell: "useradd -m -s /bin/bash appuser"
# Bon
- ansible.builtin.user:
name: appuser
shell: /bin/bash
create_home: trueVersionner les dépendances
Un requirements.yml sans versions est une bombe à retardement : la prochaine installation peut embarquer une version incompatible d'un rôle ou d'une collection.
# Mauvais
collections:
- name: community.general
# Bon
collections:
- name: community.general
version: ">=7.0.0,<8.0.0"Tags et --limit pour les déploiements partiels
# Tagguer les tâches par domaine fonctionnel
- name: Déployer la configuration nginx
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
tags:
- nginx
- config
- name: Déployer le code applicatif
ansible.builtin.git:
repo: https://github.com/example/myapp.git
dest: /srv/myapp
tags:
- app
- deploy# Ne lancer que les tâches taguées "config"
ansible-playbook site.yml --tags config
# Exclure les tâches taguées "deploy"
ansible-playbook site.yml --skip-tags deploy
# Combiner avec --limit
ansible-playbook site.yml --tags nginx --limit web01.example.comTester l'idempotence systématiquement
Après chaque modification d'un playbook, relancer deux fois et vérifier que le second run donne changed=0. Si ce n'est pas le cas, identifier la tâche non idempotente et la corriger (avec changed_when, creates, ou en remplaçant le module shell par le bon module).
ansible-lint en pre-commit
# .pre-commit-config.yaml
repos:
- repo: https://github.com/ansible/ansible-lint
rev: v24.2.0
hooks:
- id: ansible-lint
files: \.(yaml|yml)$pip install pre-commit
pre-commit installCe qui casse en production
Les incidents Ansible en production ont généralement les mêmes causes :
- Variable non définie sur un hôte particulier qui n'appartient pas au bon groupe
- gather_facts désactivé et utilisation d'un fact comme
ansible_distribution - Module shell non idempotent qui s'exécute à chaque run et crée des doublons
- Handler non déclenché parce que la tâche était en
oket nonchanged - serial trop élevé : rolling update qui coupe trop d'hôtes simultanément
- Vault password manquant en CI : le pipeline s'arrête sur tous les hôtes simultanément
La plupart de ces problèmes sont évités par des tests en staging avant la prod, et par --check --diff sur les changements critiques.