diff --git a/content/blog/cours/ansible/ansible-les-variables.md b/content/blog/cours/ansible/ansible-les-variables.md index bf4f3fe6..5abfd39c 100644 --- a/content/blog/cours/ansible/ansible-les-variables.md +++ b/content/blog/cours/ansible/ansible-les-variables.md @@ -22,6 +22,42 @@ Il s'agit bien évidemment de supports à vocation pédagogique qui **ne sont pa Avoir suivi/lu les cours concernant les [inventaires](/blog/cours/ansible/ansible-les-inventaires-statiques) et les [playbooks](/blog/cours/ansible/ansible-les-playbooks) ! +Et donc disposer d'un inventaire s'approchant de celui-ci: + +```yaml +all: + hosts: + vm-web-prod-01: + ansible_host: XXX.XXX.XXX.XXX + ansible_user: debian + vm-db-prod-01: + ansible_host: XXX.XXX.XXX.XXX + ansible_user: debian + vm-web-staging-01: + ansible_host: XXX.XXX.XXX.XXX + ansible_user: debian + vm-db-staging-01: + ansible_host: XXX.XXX.XXX.XXX + ansible_user: debian + children: + webservers: + hosts: + vm-web-prod-01: ~ + vm-web-staging-01: ~ + dbservers: + hosts: + vm-db-prod-01: ~ + vm-db-staging-01: ~ + staging: + hosts: + vm-web-staging-01: ~ + vm-db-staging-01: ~ + production: + hosts: + vm-web-prod-01: ~ + vm-db-prod-01: ~ +``` + ## Introduction Nous avons vu précemment comment débuter avec Ansible avec les notions fondamentales d'inventaire et de playbooks. Dans l'idée d'apporter un peu plus d'outils à cet ensemble Ansible est également capable de gérer et interpréter des variables qui peuvent venir de différentes sources. @@ -31,15 +67,223 @@ Pour commencer attaquons nous aux variables qu'Ansible lui même manipule pour s ## Les variables +Ansible introduit énormément de souplesse en terme « d'endroit » ou peuvent être déclarées des variables ce qui laisse énormémement de liberté sur la façon dont on souhaite organiser notre projet mais qui a pour contrepartie de demander énormément de rigueur afin de respecter les standards établis pour le projet, sous peine que cela devienne très rapidement un vrai foutoir. + ### Les variables d'hôte -hostname: web-staging-01 +Pour commencer nous aborderons le principe des variables d'hôtes qui en toute logique, permettent de définir des variables au niveau d'une machine bien précise. Vous verrez avec le temps que sur des infrastructures d'exploitation conséquentes ces variables sont souvent peu utilisées car il est rare de n'avoir qu'une seule machine derrière un service. + +Commençons par créer un nouveau répertoire `host_vars` à la racine de notre répertoire de travail qui contiendra des fichiers reprenant les nom d'hôtes définis dans notre inventaire, nous commencerons par les membres du groupe `webservers` et crérons donc 2 fichiers `vm-web-prod-01.yml` et `vm-web-staging-01.yml`. + +Chaque fichier contiendra pour l'instant une définition de variable selon l'exemple suivant: + +```yaml +hostname: web-production-01 +``` +On fera bien évidemment de même avec le second fichier et les instances du groupe `dbservers` en ajoutant les fichiers `vm-db-prod-01.yml` et `vm-db-staging-01.yml` contenant respectivement: + +```yaml +hostname: db-production-01 +``` + +et + +```yaml +hostname: db-staging-01 +``` +Il est possible de faire afficher à Ansible les différentes variables définies `ansible-inventory --graph -i inventories --vars` qui devrait vous renvoyer pour l'instant: + +```yaml +@all: + |--@ungrouped: + |--@webservers: + | |--vm-web-prod-01 + | | |--{ansible_host = 162.19.93.111} + | | |--{ansible_user = debian} + | | |--{hostname = web-production-01} + | |--vm-web-staging-01 + | | |--{ansible_host = 162.19.93.190} + | | |--{ansible_user = debian} + | | |--{hostname = web-staging-01} + |--@dbservers: + | |--vm-db-prod-01 + | | |--{ansible_host = 162.19.92.208} + | | |--{ansible_user = debian} + | | |--{hostname = db-prod-01} + | |--vm-db-staging-01 + | | |--{ansible_host = 162.19.92.175} + | | |--{ansible_user = debian} + | | |--{hostname = db-staging-01} + |--@staging: + | |--vm-web-staging-01 + | | |--{ansible_host = 162.19.93.190} + | | |--{ansible_user = debian} + | | |--{hostname = web-staging-01} + | |--vm-db-staging-01 + | | |--{ansible_host = 162.19.92.175} + | | |--{ansible_user = debian} + | | |--{hostname = db-staging-01} + |--@production: + | |--vm-web-prod-01 + | | |--{ansible_host = 162.19.93.111} + | | |--{ansible_user = debian} + | | |--{hostname = web-production-01} + | |--vm-db-prod-01 + | | |--{ansible_host = 162.19.92.208} + | | |--{ansible_user = debian} + | | |--{hostname = db-prod-01} +``` + +Où l'on peut constater la présence de nos variables au niveau de chacun des hôtes ! ### Les variables de groupe -hostname: web-staging-01 +Passons à présent aux variables de groupes, vous l'aurez compris celles-ci s'appliqueront à un groupe de machine tel que nous l'aurons défini dans notre inventaire. +Leur fonctionnement repose sur le même principe que les variables d'hôtes, nous crérons donc cette fois un répertoire appelé `group_vars` contenant un fichier pour chacun des groupes que nous aurons défini. + +Nous allons donc créer les fichiers `production.yml` et `staging.yml` contenant respectivement pour l'instant: + +```yaml +stage: production +``` +et +```yaml +stage: staging +``` +En rejouant la commande ansible précédente vous pourrez constater qu'une nouvelle variables `stage` apparait bien comme définie lors de l'affichage de votre inventaire. + +!!! info "L'héritage des variables" + Il est bien évidemment possible d'appliquer une définition de variable aux groupes parent comme aux groupes enfant, dans ce cas on prendra bien soin de faire attention à l'héritage des variables ! + +On oubliera pas au passage que même s'il n'apparait pas de manière explicite dans notre inventaire, le groupe `all` est systématiquement définit par Ansible comme « super parent » et qu'il est donc de manière possible de déclarer des variables pour ce groupe en créant un fichier `all.yml` dans `group_vars` contenant par exemple: + +```yaml workshop: ansible -### Les « facts » +``` + +### Définir des variables dans un inventaire + +Il est possible (je vous l'ai dit Ansible est très souple) de définir des variables directement dans votre fichier d'inventaire, on l'a déjà plus ou moins vu d'ailleurs avec la définition de clés spécifiques à Ansible comme `ansible_host` ou `ansible_user` au niveau d'un hôte, l'ajout de variable sur un hôte fonctionne donc de la même façon en ajoutant des clés à la suite. + +Au niveau d'un groupe il faudra passer par la clé `vars` on pourrait imaginer par exemple indiquer un serveur de temps bien précis pour une zone géographique avec quelque chose comme: + +```yaml +france: + hosts: + host-01: + host-02: + vars: + ntp_server: ntp.univ-lyon1.fr +``` + +### Comment les variables sont elles fusionnées ? + +Ansible fusionne les variables pour les appliquer de manière spécifique à chacun de nos hôte, cela signifie que sortie de notre définition d'inventaire et de correspondance hôte/groupe la notion de groupe ne perdure pas, en effet Ansible va écraser les variables préalablement définies en suivant cet ordre (de poids le plus faible au plus important): + +- groupe `all` (n'oubliez pas c'est le parent « racine ») +- groupe parent +- groupe enfant +- hôte + +Pour résumer de la variable la moins précise (en terme de périmètre de définition) à la plus précise. + +**Quelques points d'attention toutefois:** + +Pour les groupes de même niveau hiérarchique les variables du dernier groupe considéré écraseront les autres, sauf si une pondération est appliqué au niveau du groupe en utilisant la variable `ansible_group_priority` comme suit: + +```yaml +france: + hosts: + host-01: + host-02: + vars: + ntp_server: ntp.sophia.mines-paristech.fr +lyon: + hosts: + host-01: + host-02: + vars: + ntp_server: ntp.univ-lyon1.fr + ansible_group_priority: 10 +``` + +!!! info "Prioriser un groupe" + `ansible_group_priority` peut uniquement être défini au niveau de l'inventaire, il n'est pas possible de l'utiliser dans `group_vars`. + +### Last but not least, les facts + +Les facts sont au coeur du fonctionnement des variables dans Ansible dans le sens où ce sont des variables spécifiques récupérées directement depuis l'hôte concerné par un déploiement. +Elles permettent de récupérer pas mal d'information parmi lesquelles notamment la ou les interfaces réseaux des machines, le type d'OS et sa version ou encore des informations concernant le matériel de la cible. + +On peut les consulter en utilisant par exemple le module `setup` directement en ligne de commande: `ansible -i inventories vm-web-prod-01 -m setup`. +Il est possible de filtrer la sortie affichée par Ansible en utilisant l'option `filter`: `ansible -i inventories vm-web-prod-01 -m setup -a "filter=ansible_default_ipv4"` + +Ces « facts » se reveleront fort utiles au fur et à mesure de votre prise en main d'Ansible. + +## Utiliser les variables dans nos playbooks + +Nous avons vu comment définir des variables, c'est bien beau mais comment les utilisées ? + +Reprenons par exemple nos fichiers d'hôte ou nous définissons la clé `hostname`, on peut constater que celle-ci dispose d'une partie qui reprend le contenu de la clé `stage` définie au niveau du groupe. +On peut donc modifier nos fichiers d'hôte de la manière suivante pour exploiter cette définition: + +``` +hostname: "web-{{ stage }}-01" +``` + +Et allons modifier notre playbook (`example.yml`) pour utiliser ces variables de la manière suivante: + +```yaml +--- +- hosts: webservers + + pre_tasks: + - name: Updating APT cache index + ansible.builtin.apt: + update_cache: yes + + tasks: + # NGINX + - name: Install Nginx web server + ansible.builtin.apt: + name: nginx + state: present + + - name: Nginx status configuration file + ansible.builtin.copy: + src: nginx/status.conf + dest: /etc/nginx/conf.d/status.conf + notify: + - restart_nginx + + # CONFIG + - name: Set a hostname + ansible.builtin.hostname: + name: "{{ hostname }}" + + handlers: + - name: restart_nginx + ansible.builtin.service: + name: nginx + state: restarted +``` + +## Les templates + +Sujet étroitement lié à l'utilisation des variables, les templates au sens d'Ansible sont des fichiers un peu particulier dont le contenu peut-être défini dynamiquement (par opposition notamment à l'utilisation de fichiers de configuration « statiques ») comme nous avons pu le voir dans la partie [playbook](http://localhost:8000/blog/cours/ansible/ansible-les-playbooks#les-handlers). + +Il faut également savoir qu'Ansible s'appuie sur le moteur de template [Jinja2](https://jinja.palletsprojects.com/en/3.1.x/) issu du monde Python qui pourrait être comparé à Twif pour PHP, Pebble pour Java, Liquid pour RoR ou encore DotLiquid pour .Net. + +Nous l'avons vu les variables peuvent être définies à divers endroits et peuvent ensuite être accessibles avec les doubles parenthèses `{{ ... }}`. + +Imaginons que nous souhaitions personnaliser nos [motd](https://fr.wikipedia.org/wiki/Message_of_the_Day) par exemple en fonction de l'environnement que nous allons accéder. + +### Définir et utiliser un nouveau template + + + +- https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html#assigning-a-variable-to-one-machine-host-variables +- https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html#assigning-a-variable-to-many-machines-group-variables \ No newline at end of file