Bonnes pratiques Ansible - annexes

Voir :

https://docs.ansible.com/ansible/latest/tips_tricks/ansible_tips_tricks.html

https://www.ansible.com/blog/ansible-best-practices-essentials

https://www.redhat.com/sysadmin/10-great-ansible-practices

https://redhat-cop.github.io/automation-good-practices/

https://www.gaige.net/separating-ansible-roles-for-fun-and-profit.html

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html

https://ansible.readthedocs.io/projects/awx/en/24.6.1/userguide/best_practices.html

https://docs.ansible.com/ansible/latest/tips_tricks/sample_setup.html

https://docs.ansible.com/ansible/2.8/user_guide/playbooks_best_practices.html

https://timgrt.github.io/Ansible-Best-Practices/ansible/playbook/

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_advanced_syntax.html

https://spacelift.io/blog/how-to-improve-ansible-performance

https://ansible.readthedocs.io/projects/lint/rules

Principes

Zen de Python

https://fr.wikipedia.org/wiki/Zen_de_Python

import this

Plan

Bonnes pratiques propres à Ansible 1

Idempotent

Ansible-lint

Bonnes pratiques propres à Ansible 2

Bonnes pratiques IT

Logs

Proterger les secrets

Assert sur les cibles

Bonnes pratiques code

DRY

Ne pas réinventer le roue

Pas de code spacelift

Controler tous les inputs

Faire les contrôle de plus tôt possible.

Fichiers

find . -type f -wholename "*/files/*" -size +100k find . -type f -wholename "*/files/*" -size -100k -exec file --mime-encoding {} + | awk -F: '/binary/ { print $1 }'

Garder une arborescence similaire aux petits textes : le chemin doit contenir le nom de rôles ou du playbook

Une référence unique. Un seul rôle (ou un seul playbook) fait appel directement à ce fichier.

Si deux roles ou besoin de ce même fichier : créer un 3em rôle et faire un dépendance de rôle.

DRY

Factoriser - Éviter de dupliquer du code - Don't Repeat Yourself (DRY) (RA_GEN_N3) Dans la mesure du possible, seulement se répéter est mieux que d'écrire un code difficilement lisible. Car “à la pureté, privilégie l'aspect pratique.”

En créant des rôles en les appelant avec des arguments / variables

module_defaults (If you frequently call the same module with the same arguments)

En utilisant import* et include* (attention aux notify avec include)

En utilsant block

Classification

Ne pas utiliser de module obsolète “Deprecated” (RA_QUA_N2)

Les noms de tâche devraient être uniques (RA_QUA_N3)

Si pas besoin des facts : mettre gather_facts à false (RA_PERF_N3)

Si besoin de facts récuper seulement les facts utiles (RA_PERF_N3)

Playbook pouvant fonctionner un Dry-Run (--check) (RA_TEST_N2)

Ne pas utilisez ignore_errors: true et encore moins pour un playbook entier. Préferez “failed_when:” (RA_QUA_N1)

Éviter d’utiliser delegate_to surtout, dans les rôles (RA_QUA_N1)

Pour les templates et les fichiers, systématiquement sauf si non applicable mettre en commentaire que ce fichier est géré par Ansible. (RA_QUA_N1)

Ne pas utiliser M(vars_prompt) (remplacé par les “Surveys” et extra-vars) (RA_QUA_N1)

Ne pas utiliser M(pause) sans timeout (RA_QUA_N1)

Utiliser des inventaires dynamiques (If you have an external source of truth) (RA_QUA_N3)

Larger Host Counts - Consider setting “forks” on a job template to larger values to increase parallelism of execution runs. Voir : Strategy, Mitogen, Slicing, Async (Asynchronous) (RA_PERF_N3)

Ne pas mettre les facts des nœuds dans la base de données - Ne pas activer “Enable Fact Storage” Le cache des facts doit être sur les managed_hosts et non coté serveur (RA_GEN_N1)

Ne pas faire de command: ansible-galaxy ni de shell: ansible-galaxy, mais utiliser la manière native de AAP / AWX (RA_QUA_N1)

Pour les facts (facts caching) (RA_PERF_N3)

Assert extra_var, controler les inputs des utilisateurs (RA_SEC_N1)

Assert sur les cibles (RA_SEC_N2)

Utiliser un logiciel de gestion de versions tel que Git (RA_GEN_N1) Use Source Control https://ansible.readthedocs.io/projects/awx/en/24.6.1/userguide/best_practices.html

Utiliser SonarQube ou équivalent (RA_GEN_N4)

Utiliser l'encodage UTF8 (RA_GEN_N1)

Remplacer les tabulations par 2 espaces (A config si ce n'est pas le cas dans l'IDE) (RA_GEN_N1)

DRY - Factoriser - Éviter de dupliquer du code - Don't Repeat Yourself (DRY) (RA_GEN_N3) Dans la mesure du possible, seulement se répéter est mieux que d'écrire un code difficilement lisible. Car “à la pureté, privilégie l'aspect pratique.”

Mettre les become_user: root que sur les tâches nécessitant les privilèges, et non sur tous le playbook (RA_SEC_N1)

Utiliser no_log: true pour les taches utilisant des secrets (RA_SEC_N1)

Pour les données sensibles utiliser ansible-vault ou les Crendential AWX (RA_SEC_N1)

Mettre en cache les facts (fact_caching) (mais sur les noeuds, pas en DB) (RA_PERF_N3)

Eviter de boucler innutilement - vérifier si le module prends des listes (RA_PERF_N2)

Nommer les templates Jinja avec l’extension j2 (RA_CONV_REQ)

Préférer les variables a plat plutôt que les variables dictionnaires (RA_CONV_OPT)

De préférence nommer la variable de boucle (loop_var) à la place d'utiliser le nom par défaut item (RA_CONV_OPT)

? Pour les roles contenants beaucoup de fichiers dans “files/” privilégier une arborescence comme suit (RA_CONV_OPT) (ex files/etc/nginx/sites-available/plop)

Bonnes pratiques IT

Tester les playbooks sur un environnement hors prod.

https://www.commitstrip.com/fr/2013/04/16/tester-ou-ne-pas-tester-telle-est-la-question/?

Mettre en place des tests unitaires :

https://www.commitstrip.com/fr/2017/02/08/where-are-the-tests/

Molecule

Utiliser le cache que cela est possible :

Pour les facts (facts caching) (RA_PERF_N3)

Mais éviter “Enable Fact Storage” qui met les fact dans la base de données

Pour les inventaires (cache_plugin, Fact Cache)

[inventory] cache = True cache_plugin = memory cache_timeout = 1800

Idempotence

Si Appel API → Changed (par défaut)

Utiliser les handlers pour redémarrer les services Mais attention avec les modules (import*), les handlers ne sont pas déclenchés par défaut. Faire ansible.builtin.meta: flush_handlers

Fichiers

Devraient être dans <role_name>/files/ (ou dans files/ si appelé directement depuis un playbook ?)