May 30, 2023

Tech Articles

L'art de la technologie

Variables Ansible : choisir le bon emplacement

Variables Ansible : choisir le bon emplacement

Définir des variables pour vos playbooks et rôles Ansible peut devenir difficile à mesure que votre projet se développe.

Parcourir le Documentation ansiblela diversité de l’emplacement des variables Ansible est pour le moins déroutante :

  1. valeurs de ligne de commande (par exemple, -u my_userce ne sont pas des variables)
  2. valeurs par défaut des rôles (définies dans role/defaults/main.yml)
  3. fichier ou script d’inventaire group_vars
  4. inventaire group_vars/all
  5. livre de jeu group_vars/all
  6. inventaire group_vars/*
  7. livre de jeu group_vars/*
  8. fichier ou script d’inventaire host_vars
  9. inventaire host_vars/*
  10. livre de jeu host_vars/*
  11. héberger facts / mis en cache set_facts
  12. jouer à vars
  13. jouer vars_prompt
  14. jouer vars_files
  15. variables de rôle (définies dans role/vars/main.yml)
  16. block vars (uniquement pour les tâches en bloc)
  17. variables de tâche (uniquement pour la tâche)
  18. include_vars
  19. set_facts / variables enregistrées
  20. rôle (et include_role) paramètres
  21. inclure les paramètres
  22. variables supplémentaires (par exemple, -e "user=my_user")(toujours gagner la priorité)

Il y a 22 endroits différents où stocker vos variables ! Au fur et à mesure que votre code évolue et devient plus complexe, il peut devenir désordonné.

Définissez votre propre sous-ensemble d’emplacements de variables

La manière simple

Chaque fois que vous pensez à une variable, il devrait être évident où elle est définie. Si ce n’est pas le cas, vous diffusez peut-être vos variables dans trop d’endroits. Commencez par quelque chose de simple, par exemple n’avoir que 2 endroits où vos variables peuvent être définies :

  1. valeurs par défaut du rôle (définies dans role/defaults/main.yml)
  2. paramètres de rôle (et include_role)

roles/serviceA/default.yml: ce fichier définit tout variables requises par le rôle, avec quelques valeurs par défaut. Notez comment nous pouvons commenter les variables requises, mais pour lesquelles nous ne voulons pas fournir de valeur par défaut. Ce faisant, nous documentons chaque variable dont le rôle a besoin.

servicea_log_dir: /var/log/servicea

servicea_autorestart: yes

serviceA.yml: ce fichier est le playbook dans lequel le rôle est appelé. Nous mettons notre Douane configuration là-bas.

- hosts: groupa
  roles:
  - role: serviceA
    vars:
      servicea_user: gollum
      servicea_autorestart: no

Nous avons choisi 2 emplacements pour notre projet : role defaults, et role params. Il est facile de savoir où trouver notre variable. Cela devrait fonctionner dans la plupart des situations.

Une méthode plus générique

Prenons un autre sous-ensemble d’emplacements.

  1. valeurs par défaut du rôle (définies dans role/defaults/main.yml)
  2. inventaire group_vars/*

roles/serviceA/default.yml: rôles par défaut, définis de la même manière que dans l’exemple précédent.

servicea_log_dir: /var/log/servicea

servicea_autorestart: yes

inventory/group_vars/servicea.yml: ces variables vont être associées au groupe appelé servicea

servicea_user: gollum
servicea_autorestart: no

Il est ensuite nécessaire d’associer correctement le rôle aux hôtes dont vous avez défini les variables (rappel : à l’exécution, les variables sont finalement associées à un hôte : il n’y a pas de groupe ou de rôle par défaut, uniquement des variables d’hôte). Le livret de jeu :

- hosts: servicea
  roles:
  - role: serviceA

Supposons maintenant que nous voulions avoir plusieurs rôles, servicea et servicebpour s’exécuter sur un groupe appelé par exemple worker. Nous pourrait écrire la configuration personnalisée pour les deux services (servicea et serviceb) dans un seul fichier : inventory/group_vars/worker.yml; mais alors il n’est vraiment pas évident où trouver vos variables personnalisées.

Au lieu de cela, nous pouvons avoir 1 groupe par service, donc 1 fichier de configuration par service dans le group_vars dossier (servicea.yml et serviceb.yml). On associe alors le worker héberge au groupe de nos différents services. inventory/hosts:

[worker]
worker01.local
worker02.local
worker03.local
worker04.local

[servicea:children]
worker

[serviceb:children]
worker

Un mauvais chemin

Prenons simplement les 2 exemples précédents et mélangeons-les. Nous choisissons 3 emplacements :

  1. valeurs par défaut du rôle (définies dans role/defaults/main.yml)
  2. inventaire group_vars/*
  3. paramètres de rôle (et include_role)

Disons que nous voulons modifier servicea_log_dir variable. Nous ne pouvons pas modifier la variable par défaut du rôle, car nous voulons notre propre valeur personnalisée. Changeons-nous maintenant dans le group_vars ou dans les paramètres de rôle? Les deux fonctionnent, et il n’y a aucun moyen de déterminer quel emplacement vous choisiriez, à moins qu’il n’y ait une logique spécifique derrière cela. Ce n’est pas correct et nous voulons garder les choses simples.

Pensez aux gitops

Lorsque vous choisissez les quelques emplacements à utiliser, pensez à l’effet que cela aura sur votre version de code.

La méthodologie gitops peut vous aider. En bref, vous souhaitez diviser votre code en 2 référentiels : votre référentiel de code et votre référentiel ops.

En l’appliquant à Ansible, votre référentiel de code est l’endroit où vous versionnez vos rôles ou votre Collections Ansible. Votre référentiel ops est l’endroit où vous versionnez tout ce qui est spécifique à une instance de votre code ; à savoir votre inventaire et vos variables personnalisées.

Lorsque vous utilisez la méthode simple, vous devrez versionner vos playbooks dans votre référentiel ops, car ils contiennent vos variables personnalisées. Lorsque vous utilisez la deuxième méthode que nous avons décrite, où chaque variable personnalisée se trouve dans le groupe d’inventaire vars, vous ne pouvez versionner que l’inventaire dans votre référentiel ops.

L’important est qu’il soit possible de scinder le code générique et les propriétés propres à une instance. Par exemple, stocker des variables personnalisées dans le vars dossier d’un rôle (par ex. roles/servicea/vars/main.yml) n’est pas correcte.

Si vous pensez à une variable et savez avec certitude où elle a été définie, alors vous faites probablement les choses correctement.