Tools/Ansible/Best Practices

De MonPtitSite
Sauter à la navigation Sauter à la recherche
Accueil SysAdmin Hobbies                  


Ansible - Best Practices


Sites Références

Miser sur la simplicité

Lisibilité

Il est préférable d'utiliser la syntaxe YAML "native". ex :


- name: Postfix is installed and updated
  yum:
    name: postfix
    state: latest
    notify: update_postfix
- name: Postfix is running
  service:
    name: postfix
    state: started

et NON la forme suivante, moins lisible :


- name: Postfix is installed and updated
  yum: name=postfix state=latest
  notify: restart_postfix
- name: Postfix is running
  service: name=postfix state=started

Utilisation des modules

Une fois qu'un playbook fonctionne comme prévu, essayer de le divisez en composants plus petits et logiques à l'aide d'importations et d'inclusions.

Lorsque cela est possible, utiliser des modules à usage spécial fournis avec Ansible, plutôt que les modules command, shell, raw ou autres modules similaires.

Faire preuve d'organisation

nommage des variables

Le nom des variables peut être particulièrement important, car Ansible dispose d'un espace de noms assez plat. Utilisez des variables descriptives telles que apache_tls_port, plutôt qu'une variable moins descriptive comme p.

En ce qui concerne les rôles, il est recommandé de préfixer les variables de rôle avec le nom de rôle. Par exemple, si votre rôle est nommé myapp, vos noms de variables peuvent commencer par myapp_ pour les distinguer en fonction de leur espace de noms des variables figurant dans d'autres rôles et le playbook.

structuration d'un projet

Utiliser un modèle cohérent lors de la création de la structure des fichiers d'un projet Ansible sur un système de fichiers. Il existe un certain nombre de modèles utiles, mais le modèle suivant est un bon exemple :

 .
 ├── dbservers.yml
 ├── inventories/
 │   ├── prod/
 │   │   ├── group_vars/
 │   │   ├── host_vars/
 │   │   └── inventory/
 │   └── stage/
 │       ├── group_vars/
 │       ├── host_vars/
 │       └── inventory/
 ├── roles/
 │   └── std_server/
 │
 ├── site.yml
 ├── storage.yml
 └── webservers.yml

Le fichier site.yml est le playbook maître qui inclut ou importe les playbooks assurant des tâches spécifiques :

  • dbservers.yml,
  • storage.yml
  • webservers.yml.

Les rôles se trouvent dans des sous-répertoires du répertoire roles, tels que std_server. Il existe deux inventaires statiques dans les répertoires inventories/prod et inventories/stage avec des fichiers de variables d'inventaire distincts, de sorte que vous puissiez sélectionner différents ensembles de serveurs en modifiant l'inventaire que vous utilisez. La structure du playbook permet de diviser un grand playbook en fichiers plus petits afin d'en améliorer la lisibilité. De plus, ces sous-playbooks de taille inférieure peuvent contenir des plays destinés à tâches précises de manière indépendante.

Inventaires et avantages des groupes

Inventaires pseudo-dynamiques : module group_by

Il est possible d'utiliser le module group_by pour générer de manière dynamique l'appartenance à un groupe en fonction d'un fait. L'appartenance à un groupe est valide pour le reste du playbook.

exemple:

- name: Generate dynamic groups
  hosts: all
  tasks:
- name: Generate dynamic groups based on architecture
  group_by:
    key: arch_"{{ ansible_facts['architecture'] }}"
- name: Configure x86_64 systems
  hosts: arch_x86_64
  tasks:
  - name: First task for x86_64 configuration
    ...output omitted...

Avantages des groupes

Dans un inventaire, les hôtes peuvent appartenir à plusieurs groupes ce qui permet de les catégoriser. (géographiquement, type environnement prod/qual/..., services et/ou fonctionnalités rendus....)


IMPORTANT
Rappelez-vous que les hôtes hériteront des variables de tous les groupes auxquels ils appartiennent.

Si deux groupes ont des paramètres différents pour la même variable, et qu'un hôte est membre des deux, alors la valeur utilisée est la dernière qui a été chargée. S'il existe des différences entre des paramètres de deux groupes distincts qui peuvent être utilisés simultanément, prenez soin de déterminer la manière dont ces variables doivent être définies.

Séparation des variables de l'inventaire

Les sources d'inventaire définissent les hôtes et les groupes d'hôtes utilisés par Ansible, qu'il s'agisse de fichiers statiques ou d'un script d'inventaire dynamique. Si vous gérez votre inventaire en tant que fichiers statiques, vous pouvez définir des variables dans le ou les fichiers d'inventaire, dans les mêmes fichiers qui vous servent à définir vos listes d'hôtes et de groupes d'hôtes.

Cependant, il ne s'agit pas de la meilleure pratique. À mesure que votre environnement augmente en taille et en diversité, le fichier d'inventaire devient volumineux et difficile à lire.

De plus, vous souhaiterez probablement migrer vers des sources d'inventaire dynamique plutôt que des fichiers d'inventaire statique afin de faciliter la gestion de votre inventaire. Toutefois,vous souhaiterez peut-être continuer à gérer de façon statique des variables d'inventaire, indépendamment de la sortie du script d'inventaire dynamique ou en plus de celle-ci.

Une meilleure approche consiste à déplacer les définitions de variables du fichier d'inventaire vers des fichiers de variables distincts, un pour chaque groupe d'hôtes. Chaque fichier de variable est nommé d'après un groupe d'hôtes et contient des définitions de variables pour le groupe d'hôtes :

[user@demo project]$ ''tree -F group_vars''
group_vars/
├── db_servers.yml
├── lb_servers.yml
└── web_servers.yml

Grâce à cette structure, il est plus facile de localiser des variables de configuration pour l'un des groupes d'hôtes : db_servers', lb_servers ou web_servers.

À condition que chaque groupe d'hôtes contienne un petit nombre de définitions de variables, la structure d'organisation cidessus est suffisante.

Mais à mesure que les playbooks gagnent en complexité, la taille de ces fichiers augmentent et ils peuvent devenir difficiles à comprendre.

Une approche encore meilleure pour les environnements importants et diversifiés consiste à créer des sous-répertoires pour chaque groupe d'hôtes sous le répertoire group_vars.

Ansible analyse n'importe quel YAML dans ces sous-répertoires et associe les variables à un groupe d'hôtes basé sur le répertoire parent :

[user@demo project2]$ tree -F group_vars
group_vars/
├── db_servers/
│ ├── 3.yml
│ ├── a.yml
│ └── myvars.yml
├── lb_servers/
│ ├── 2.yml
│ ├── b.yml
│ └── something.yml
└── web_servers/
└── nothing.yml

Dans l'exemple précédent, les variables du fichier myvars.yml sont associées au groupe d'hôtes db_servers, car le fichier est contenu dans le sous-répertoire group_vars/db_servers.

Cependant, les noms de fichiers de cet exemple ne permettent pas de savoir facilement où trouver une variable particulière.

Si vous choisissez d'utiliser cette structure d'organisation pour les variables, regroupez celles-ci selon un thème commun dans le même fichier et utilisez un nom de fichier pour indiquer ce thème commun.

Lorsqu'un playbook utilise des rôles, une convention courante consiste à créer des fichiers de variables nommés selon chaque rôle du playbook.

Un projet respectant cette convention peut ressembler à ceci :

[user@demo project3]$ tree -F group_vars
group_vars/
├── all/
│ └── common.yml
├── db_servers/
│ ├── mysql.yml
│ └── firewall.yml
├── lb_servers/
│ ├── firewall.yml
│ ├── haproxy.yml
│ └── ssl.yml
└── web_servers/
├── firewall.yml
├── webapp.yml
└── apache.yml


Cette structure d'organisation pour un projet vous permet de voir rapidement les types de variables définis pour chaque groupe d'hôtes. Toutes les variables présentes dans des fichiers figurant dans des répertoires situés sous le répertoire group_vars sont fusionnées avec le reste des variables. La séparation de variables en fichiers regroupés par fonctionnalité rend l'ensemble du projet de playbook plus facile à comprendre et à gérer.

Variables d'inventaire spéciales

Il existe un certain nombre de variables que vous pouvez utiliser pour modifier la manière dont Ansible se connecte à un hôte listé dans l'inventaire. Certaines d'entre elles sont les plus utiles en tant que variables propres à l'hôte, mais d'autres peuvent s'avérer pertinentes pour tous les hôtes d'un groupe ou dans l'inventaire.


Principales variables d'inventaires Ansible
Variable Description
ansible_connection Plug-in de connexion utilisé pour accéder à l'hôte géré. Par défaut, ssh est utilisé pour tous les hôtes, à l'exception de localhost qui utilise local.
ansible_host Adresse IP réelle ou nom de domaine complet à utiliser lors de la connexion à l'hôte géré, à la place du nom du fichier d'inventaire (inventory_hostname). Par défaut, cette variable a la même valeur que le nom d'hôte d'inventaire.
ansible_port Port utilisé par Ansible pour se connecter à l'hôte géré. Pour le plug-in de connexion par SSH (par défaut), la valeur par défaut est 22.
ansible_user Utilisateur dont se sert Ansible pour se connecter à l'hôte géré. Le comportement par défaut d'Ansible est de se connecter à l'hôte géré à l'aide du même nom d'utilisateur que celui qui exécute le playbook Ansible sur le noeud de contrôle.
ansible_become_user Une fois qu'Ansible s'est connecté à l'hôte géré, il bascule vers cet utilisateur en utilisant absible_become_method (qui est sudo par défaut). Il se peut que vous deviez vous procurer des informations d'identification d'authentification de quelque façon que ce soit.
ansible_python_interpreter Chemin d'accès à l'exécutable Python qu'Ansible doit utiliser sur l'hôte géré. Sur Ansible 2.8 et versions ultérieures, cette valeur par défaut est auto, qui sélectionne automatiquement un interpréteur Python sur l'hôte exécutant le playbook en fonction du système d'exploitation qu'il exécute. Ainsi, il n'est plus autant nécessaire d'utiliser ce paramètre que dans les versions antérieures d'Ansible.


Variables utilisées lors d'exécution de playbooks

Lorsqu'un play est en cours d'exécution, un certain nombre de variables et de faits peuvent être utilisés pour identifier le nom de l'hôte géré actuel qui exécute une tâche :

Variables Ansible spécifiques à l'exécution
Variable Description
inventory_hostname Nom de l'hôte géré en cours de traitement, extrait de l'inventaire.
ansible_host Adresse IP ou nom d'hôte réel qui a été utilisé pour se connecter à l'hôte géré, comme indiqué

précédemment.

ansible_facts ['nom d'hôte'] Nom court (non qualifié) de l'hôte collecté comme un fait de l'hôte géré.
ansible_facts ['fqdn'] Nom de domaine complet de l'hôte collecté comme un fait de l'hôte géré.
ansible_play_hosts liste de tous les hôtes qui n'ont pas encore échoué au cours du play actuel (et qui, par conséquent, sera utilisée

pour les tâches restantes du play).|}

Penser ré-utilisabilité !

Les rôles permettent de créer des playbooks simples et de réutiliser du code commun à plusieurs projets. Un role doit porter sur un objectif ou une fonction spécifique. Idéalement, il est préférable de créer des rôles génériques configurables par le biais de variables. Ces variables sont le plus souvent définies par défaut dans le fichier YAML roles/[nom_role]/default/main.yml De cette façon, un rôle disposant de son propre paramétrage et ensemble de tâches peut facillement être intégré dans un autre playbook.

Si un playbook doit modifier le contenu d'une variable définie par un rôle, il suffit :

Exemple


- hosts: webservers
  vars:
    apache2_config: true
    apache2_default_port: 8000
  roles:
    ansible-apache2

Ce playbook utilise le rôle ansible-apache2 en modifiant 2 variables utilisées par ce rôle : apache2_config & apache2_default_port.

A l'éxécution de ce playbook, le service apache2 sera installé sur les serveurs webservers pour écouter sur le port 8000/tcp.

Exécution centralisée des playbooks

Pour contrôler l'accès aux systèmes et auditer l'activité d'Ansible, il est nécessaire d'envisagez l'utilsiation d'un serveur de contrôle dédié à partir duquel tous les playbooks Ansible sont exécutés. Les administrateurs système doivent toujours disposer de leurs propres comptes sur le système, ainsi que des informations d'identification permettant de se connecter aux hôtes gérés et d'augmenter les privilèges, si nécessaire. Lorsqu'un administrateur système cesse de travailler sur le projet, sa clé SSH peut être supprimée du fichier authorized_keys de l'hôte géré et ses privilèges de commande sudo peuvent être révoqués, sans répercussion sur les autres administrateurs.

Ce serveur central peut avantageusement héberger les services awx ou la version supportée par Red Hat Ansible Tower

Tester régulièrement

Il est bien évident qu'il faut tester les playbooks aussi bien au cours de la phase de développement que pendant l'exécution des playbooks eux-même. En effet, Ansible offre cette possibilité de s'auto-valider en définissant des tâches spécifiques permettant de vérifier une étape précédente d'un playbook.

Test des résultats des tâches

Si on a besoin de confirmer la réussite d'une tâche, vérifiez le résultat de la tâche au lieu de faire confiance au code de retour du module. Il existe plusieurs moyens de valider une tâche, en fonction du module concerné.


Exemple :

- Start web server
  service:
    name: httpd
    status: started
- name: Check web site from web server
  uri:
    url: http://{{ ansible_fqdn }}
    return_content: yes
  register: example_webpage
  failed_when: example_webpage.status != 200


Utilisation de block/rescue pour effectuer une récupération ou une restauration

La directive block est utile pour regrouper des tâches ; lorsqu'elle est associée à la directive rescue, elle est utile lorsqu'il s'agit d'effectuer une récupération après des erreurs ou des pannes.

Exemple :


- block:
  - name: Check web site from web server
    uri:
      url: http://{{ ansible_fqdn }}
      return_content: yes
    register: example_webpage
    failed_when: example_webpage.status != 200
  rescue:
    - name: Restart web server
      service:
        name: httpd
        status: restarted



Outils de test

  • ansible-playbook --syntax-check : pour vérifier la syntaxe d'un playbook (sans l'exécuter)
  • ansible-playbook --check : Exécute un playbook en mode "vérification"
NOTE
Cette vérification ne garantit pas une précision parfaite, étant donné que le playbook peut avoir besoin d'exécuter réellement certaines tâches avant que les tâches ultérieures du playbook ne fonctionnent correctement. Certaines tâches peuvent être marquées avec la directive check_mode: no. Ces tâches s'exécutent même en mode vérification.


NOTE
Il existe d'autres outils. Par exemple :

L'outil ansible-lint analyse un playbook et recherche les problèmes éventuels. Tous les problèmes signalés n'interrompront pas forcément le fonctionnement du playbook, mais les problèmes signalés peuvent indiquer la présence d'une erreur. L'outil yamllint analyse un fichier YAML et tente d'identifier les problèmes liés à la syntaxe YAML. Cet outil n'a pas une connaissance directe d'Ansible, mais il peut intercepter des problèmes potentiels de syntaxe YAML.