Les meilleures pratiques d'Ansible
Mise à jour :
Ça fait maintenant 7 ans que j’utilise Ansible quotidiennement pour provisionner et configurer des infrastructures. Comme j’ai vu plusieurs implémentations au fil de mes changements de poste, je vous propose deux billets sur les bonnes pratiques et les meilleurs patterns Ansible que j’ai pu rencontrer.
Qualité de code
Le DSL Ansible : YAML
Ansible utilise le YAML comme DSL. Un fichier yaml débute toujours avec
---
sur la première ligne et ...
sur la dernière ligne.
Utilisez deux espaces pour l’indentation.
Utilisez des espaces cohérents : Pour bien séparer les choses et améliorer la
lisibilité, envisagez de laisser une ligne vierge entre les blocks
, les tasks
,
les handlers
.
Outils d’assistance d’écriture
Pour vous aider à écrire votre code Ansible, utilisez un éditeur permettant d’installer l’extension fournit par Redhat.
Pour valider votre code, utilisez les outils ansible-lint ou spotter qui vous indiquera comment en améliorer la qualité.
Mettre en place des règles de nommage
Utilisez une stratégie de nommage cohérente pour les variables, les playbooks, les taches, les rôles et modules.
Exemples de règles de nommage :
- Tous les fichiers doivent utiliser l’extension
.yml
et non.YML
, ni.yaml
, … - Toutes les variables devant être passé dans la ligne de commande débute par
cli_
. - Toutes les variables globales débutent par
g_
. - Toutes les variables utilisées la convention snake case.
- **Toutes les variables globales des rôles doivent posséder le nom du rôle
comme préfixe
install_nginx_g_nginx_version
. - **Seules les variables pouvant être modifié doivent être placé dans
default/main.yml
. Toutes les autres dansvars/main.yml
. - Toutes les variables se trouvant dans
vars/main.yml
doivent commencer par un_
. - On utilise
_
comme séparateur de noms de variables, de nom de playbooks, de roles … - **Les noms de variables Jinja sont encadrés par des espaces
{{ variable_1 }}
. - …
Exemple de nommage de variables :
Mettre en place des règles de programmation
Sur le code
- Comme pour tout langage de programmation, lorsque votre code nécessite une
explication supplémentaire pour sa compréhension, n’hésitez pas à ajouter un
commentaire. Un commentaire débute par le caractère
#
.
- Éviter de construire des usines à gaz !; Comme tout langage de programmation, Ansible offre de nombreuses façons de découper son code. Une règle que je me fixe depuis toujours : programmer en utilisant les algorithmes les plus simples possibles -> Votre code sera plus facile à maintenir.
- Dont Repeat Yourself : Factoriser un maximum votre code en ayant
recours aux rôles (un rôle rempli un objectif) et collections Ansible. Les
rôles doivent être stockés dans un gestionnaire de code et posséder un
pipeline d’intégration permettant de tester si le code fonctionne toujours à
chaque montée de versions des dépendances :
ansible-core
, les collections, les librairies python, … - Pour les tests d’intégration la meilleure solution est d’utilisée molecule via les drivers mis à disposition : docker, podman, vagrant, ec2, gcp …
- Le recours aux modules
raw
,shell
etcommand
ne doit être fait qu’en dernier recours. En effet, ses modules cassent l’idempotence de votre code Ansible. - Découper vos fichiers
yaml
pour les rendre lisibles. Utilisez un fichier chapeaumain.yml
pour orchestrer d’autres taches de niveau inférieur en les regroupant par tâches. - Définissez toujours des valeurs par défaut pour vos variables
- Indiquez toujours l’état des paramètres booléens même si cela n’est pas nécessaire en raison de la valeur par défaut. Rien ne dit qu’à la prochaine version la valeur par défaut change !
- Évitez un maximum le recours à
ignore_errors
. Pour cela, vous pouvez :- Pour toutes les taches qui ne doivent s’exécuter que si une des précédentes a
provoqué un changement, pensez à utiliser les
handlers
.
- Pour toutes les taches qui ne doivent s’exécuter que si une des précédentes a
provoqué un changement, pensez à utiliser les
- Utilisez les conditions
when
:
Sur les inventaires
- Utilisez des inventaires séparés pour chaque environnement pour les isoler les uns des autres et éviter ainsi les erreurs en ciblant les mauvais environnements.
- Pensez à utiliser le regroupement dynamique au moment de l’exécution à l’aide
du module
group_by
. - Utilisez des groupes d’inventaire : Hôtes de groupe basés sur des attributs communs qu’ils pourraient partager (géographie, objectif, rôles, environnement). Attention à la précédence des variables Ansible.
- Ne mettre dans l’inventaire que des variables globales propre à l’infrastructure. Pour les autres variables les mettre au niveau du playbook;
- Utilisez la commande
ansible-inventory --list
pour vérifier le résultat.
Sécurité
Gestion des secrets
On utilise tous git pour stocker nos données (playbooks, inventaires, roles, collections …) Ansible. Mais attention à ne pas divulguer vos données secrètes comme des mots de passe, des clés SSH, des tokens d’API, …
Ansible met à disposition ansible-vault
(un
coffre-fort) qui permet de chiffrer ces données. Au besoin ansible saura
déchiffrer les données.
Utilisation des roles et collections disponibles sur Ansible Galaxy
Faites preuve de diligence raisonnable lorsque vous utilisez des rôles disponibles depuis Ansible Galaxy : Validez leur contenu et choisissez des rôles auprès de contributeurs fiables : gueerlinguy, robert-de-bock
Stockez vos rôles dans vos référentiels de code et utilisez un pipeline pour en contrôler le contenu (pas de secrets).
Au moment d’exécuter un playbook sur la production
Si vous n’êtes pas l’auteur d’un playbook, vous pouvez :
- Utiliser l’option
--check
qui ne réalise aucune modification. - Demander à juste visualiser les tâches qui s’exécuteront. Il faut juste
ajouter l’option
--list-tasks
à la commandeansible-playbook
.
- Vous pouvez aussi valider pour chaque tache quelles cibles sont concernées avec
l’option
--list-hosts
.
Plus loin
Si vous avez d’autres tips n’hésitez pas à me les remonter.