Aller au contenu principal

Les Inventaires Ansible

logo ansible

Au cœur d'Ansible réside un concept fondamental : les inventaires (inventories en anglais). Les inventaires Ansible sont essentiels pour cataloguer et gérer les serveurs, les ordinateurs et d'autres équipements informatiques ciblés par les scripts automatisations.

Les inventaires Ansible peuvent être statiques, où les détails des hôtes sont définis et stockés dans des fichiers YAML ou INI, ou dynamiques, s'adaptant automatiquement aux environnements changeants en interrogeant des sources de données externes. Cette dualité permet une gestion efficace tant dans des environnements stables que dans des contextes cloud dynamiques, où les instances peuvent être fréquemment créées et détruites.

Comprendre les inventaires

Les inventaires dans Ansible sont bien plus qu'une simple liste d'hôtes. Ils sont le fondement sur lequel Ansible construit ses opérations d'automatisation, permettant de spécifier quels serveurs (ou hôtes) doivent être gérés et comment. Un inventaire peut être aussi simple qu'une liste d'adresses IP ou de noms d'hôte, mais sa vraie puissance réside dans sa capacité à organiser ces hôtes en groupes et à leur attribuer des variables spécifiques.

Les inventaires ne servent pas uniquement à lister des hôtes ; ils permettent aussi d'appliquer de manière sélective des configurations spécifiques, de gérer des déploiements et d'exécuter des tâches d'automatisation avec précision. En utilisant des inventaires, je peux facilement cibler un sous-ensemble d'hôtes pour une tâche donnée, ou appliquer des variables globales à un groupe entier, rendant les scripts d'automatisation plus flexibles et plus faciles à maintenir.

Les Inventaires statiques

Les inventaires statiques sont ceux le plus souvent sur lequel reposent de nombreuses automatisations Ansible. Ils permettent de définir de manière explicite et immuable les hôtes et les groupes avec lesquels Ansible interagira. Ces inventaires peuvent être écrits dans deux formats principaux : INI et YAML, chacun ayant ses avantages et ses spécificités.

Un inventaire Ansible de base est un fichier en format INI ou YAML. Dans sa forme la plus simple, le fichier d'inventaire peut lister les hôtes sous un groupe défini :

# Format INI
[serveurs_web]
192.168.1.101
192.168.1.102

Cette structure permet déjà d'exécuter des tâches Ansible spécifiques sur le groupe serveurs_web. Cependant, Ansible permet également de définir des groupes enfants et d'attribuer des variables d'hôtes ou de groupes pour personnaliser davantage les configurations.

Ansible permet aussi de définir des variables au niveau des hôtes ou des groupes, ce qui offre une flexibilité incroyable pour personnaliser les comportements des modules Ansible sans avoir à écrire de multiples tâches pour chaque hôte. Les variables peuvent être définies directement dans le fichier d'inventaire ou dans des fichiers séparés pour organiser la configuration.

# Format INI
[serveurs_web]
web1 ansible_host=192.168.1.101 ansible_user=admin
web2 ansible_host=192.168.1.102 ansible_user=admin

[serveurs_web:vars]
nginx_version=1.18.0

Format INI

Le format INI est le plus simple et le plus direct pour créer un inventaire. Il est particulièrement apprécié pour sa lisibilité et sa facilité de rédaction. Voici un exemple d'inventaire statique au format INI :

[serveurs_web]
web1.example.com ansible_user=admin
web2.example.com ansible_user=admin

[base_de_donnees]
db1.example.com ansible_user=dbadmin
db2.example.com ansible_user=dbadmin

[serveurs_web:vars]
nginx_version=1.18.0

Dans cet exemple, serveurs_web et base_de_donnees sont des groupes d'hôtes. serveurs_web:vars définit des variables appliquées à tous les hôtes du groupe serveurs_web.

Format YAML

Le format YAML, d'autre part, offre une structure plus riche et est souvent préféré pour des inventaires plus complexes. YAML permet une représentation plus hiérarchique et est particulièrement utile pour définir des structures imbriquées et des variables de manière plus visuelle. Voici comment le même inventaire serait représenté en YAML :

all:
children:
serveurs_web:
hosts:
web1.example.com:
ansible_user: admin
web2.example.com:
ansible_user: admin
vars:
nginx_version: "1.18.0"
base_de_donnees:
hosts:
db1.example.com:
ansible_user: dbadmin
db2.example.com:
ansible_user: dbadmin

Ce format permet non seulement de définir des hôtes et des groupes, mais aussi d'organiser des sous-groupes et d'attribuer des variables à des niveaux spécifiques de la hiérarchie.

Choix du format

Le choix entre INI et YAML dépend de la complexité de l'environnement et des préférences personnelles. Le format INI, avec sa simplicité, est excellent pour des configurations rapides et des inventaires moins complexes. Le format YAML, en revanche, est plus adapté aux structures complexes et offre une meilleure visibilité pour les configurations plus élaborées.

Dans les deux cas, les inventaires statiques sont un outil puissant pour définir explicitement l'état désiré de l'infrastructure ciblée par les automatisations Ansible. Ils constituent la base sur laquelle les tâches sont exécutées, permettant une gestion précise et prévisible des configurations système.

Inventaires dynamiques

Contrairement aux inventaires statiques, les inventaires dynamiques ne sont pas écrits manuellement, mais sont générés automatiquement en interrogeant des sources de données externes.

Les inventaires dynamiques permettent à Ansible de s'adapter automatiquement à l'infrastructure en temps réel, ce qui est particulièrement utile dans les environnements cloud où les instances peuvent être créées ou supprimées à la volée. Ansible utilise des scripts ou des plugins pour interroger les services externes et construire l'inventaire en fonction des informations recueillies.

Plugins d'inventaire dynamique

Ansible prend en charge une large gamme de plugins d'inventaire dynamique pour différents environnements et plateformes. Ces plugins permettent d'interroger des services tels que AWS, Azure, Google Cloud, VMware, Docker et bien d'autres. Voici une liste non exhaustive des plugins d'inventaire dynamique disponibles dans Ansible :

  • AWS EC2 (aws_ec2): Pour interroger les instances EC2 d'Amazon Web Services.
  • Azure RM (azure_rm): Pour les ressources Microsoft Azure.
  • Google Cloud (gcp_compute): Pour les instances Compute Engine de Google Cloud Platform.
  • VMware (vmware_vm_inventory): Pour les machines virtuelles gérées par VMware vSphere.
  • Docker (docker_container): Pour les conteneurs Docker.
  • OpenStack (openstack): Pour les ressources dans un cloud OpenStack.
  • Digital Ocean (digital_ocean): Pour les droplets sur Digital Ocean.
  • Linode (linode): Pour les instances Linode.
  • Oracle Cloud Infrastructure (oci): Pour les ressources dans Oracle Cloud.
  • Kubernetes (k8s): Pour les pods et autres ressources dans un cluster Kubernetes.

Pour utiliser un inventaire dynamique, vous devez configurer Ansible avec le plugin correspondant à votre environnement. Chaque plugin a ses propres exigences de configuration, généralement sous forme de fichiers YAML qui spécifient les détails de l'API à interroger, les identifiants d'authentification et d'autres paramètres pertinents. Chaque plugin possède ces variables permettant de trier les machines en groupe.

# Exemple de configuration pour le plugin aws_ec2
plugin: aws_ec2
regions:
- us-east-1
keyed_groups:
# add hosts to tag_Name_value groups for each aws_ec2 host's tags.Name variable
- key: tags.Name
prefix: tag_Name_
separator: ""

Attention, le nom du fichier yaml est souvent contraint ! Il doit par exemple pour l'inventaire aws se terminer aws_ec2.{yml|yaml}

Pour connaître la liste des plugins d'inventaire, il suffit de lancer la commande suivante :

ansible-doc -t inventory -l

amazon.aws.aws_ec2 EC2 inventory source
amazon.aws.aws_rds RDS instance inventory source
ansible.builtin.advanced_host_list Parses a 'host list' with ranges
ansible.builtin.auto Loads and executes an inventory plugin specified in a YAML config
ansible.builtin.constructed Uses Jinja2 to construct vars and groups based on existing inventory
ansible.builtin.generator Uses Jinja2 to construct hosts and groups from patterns
ansible.builtin.host_list Parses a 'host list' string
ansible.builtin.ini Uses an Ansible INI file as inventory source
ansible.builtin.script Executes an inventory script that returns JSON
ansible.builtin.toml Uses a specific TOML file as an inventory source
ansible.builtin.yaml Uses a specific YAML file as an inventory source
awx.awx.controller Ansible dynamic inventory plugin for the Automation Platform Controller
azure.azcollection.azure_rm Azure Resource Manager inventory plugin
cloudscale_ch.cloud.inventory cloudscale.ch inventory source
community.aws.aws_mq MQ broker inventory source
community.digitalocean.digitalocean DigitalOcean Inventory Plugin
community.dns.hetzner_dns_records Create inventory from Hetzner DNS records
community.dns.hosttech_dns_records Create inventory from Hosttech DNS records
community.docker.docker_containers Ansible dynamic inventory plugin for Docker containers
community.docker.docker_machine Docker Machine inventory source
community.docker.docker_swarm Ansible dynamic inventory plugin for Docker swarm nodes
community.general.cobbler Cobbler inventory source
community.general.gitlab_runners Ansible dynamic inventory plugin for GitLab runners
community.general.icinga2 Icinga2 inventory source
community.general.linode Ansible dynamic inventory plugin for Linode
community.general.lxd Returns Ansible inventory from lxd host
community.general.nmap Uses nmap to find hosts to target
community.general.online Scaleway (previously Online SAS or Online.net) inventory source
community.general.opennebula OpenNebula inventory source
community.general.proxmox Proxmox inventory source
community.general.scaleway Scaleway inventory source
community.general.stackpath_compute StackPath Edge Computing inventory source
community.general.virtualbox virtualbox inventory source
community.general.xen_orchestra Xen Orchestra inventory source
community.hrobot.robot Hetzner Robot inventory source
community.libvirt.libvirt Libvirt inventory source
community.okd.openshift OpenShift inventory source
community.vmware.vmware_host_inventory VMware ESXi hostsystem inventory source
community.vmware.vmware_vm_inventory VMware Guest inventory source
community.zabbix.zabbix_inventory Zabbix Inventory Plugin
dellemc.openmanage.ome_inventory Group inventory plugin on OpenManage Enterprise
google.cloud.gcp_compute Google Cloud Compute Engine inventory source
hetzner.hcloud.hcloud Ansible dynamic inventory plugin for the Hetzner Cloud
infoblox.nios_modules.nios_inventory Infoblox inventory plugin
kubernetes.core.k8s Kubernetes (K8s) inventory source
microsoft.ad.ldap Inventory plugin for Active Directory
netbox.netbox.nb_inventory NetBox inventory source
ngine_io.cloudstack.instance Apache CloudStack instance inventory source
ngine_io.vultr.vultr Vultr inventory source
openstack.cloud.openstack OpenStack inventory source
ovirt.ovirt.ovirt oVirt inventory source
servicenow.servicenow.now ServiceNow Inventory Plugin
t_systems_mms.icinga_director.icinga_director_inventory Returns Ansible inventory from Icinga
telekom_mms.icinga_director.icinga_director_inventory Returns Ansible inventory from Icinga
theforeman.foreman.foreman Foreman inventory source
vultr.cloud.vultr Retrieves list of instances via Vultr v2 API

Vous remarquerez que certains sont désormais chargés avec les collections : community.general, community.docker. Pour obtenir leur documentation :

ansible-doc -t inventory <plugin-name>
Mise en oeuvre du plugin libvirt

Il suffit de créer un fichier se nommant livirt.yml et d'y mettre ceci :

plugin: community.libvirt.libvirt
uri: 'qemu:///system'

et dans le fichier de config ansible :

[defaults]
inventory=libvirt.yml
interpreter_python=auto_silent
[inventory]
enable_plugins = community.libvirt.libvirt, auto, host_list, yaml, ini, toml, script

Il faut donc installer la collection community.libvirt et le librairie python :

ansible-galaxy collection install community.libvirt
pip install libvirt-python

Maintenant listons les machines disponibles sur ma VM :

sudo virh list --all
Id Name State
-------------------------------------------
1 staticip running
- build-containers_builder shut off
- test-dyn_default shut off
- test-podman_db shut off

On retrouve la machine que j'ai provisionné avec Terraform. Que donne la commande ansible-inventory :

ansible-inventory --graph --vars
@all:
|--@144f4357-30fe-4bf8-9484-6f3e6ff2312b:
| |--test-podman_db
| | |--{ansible_connection = community.libvirt.libvirt_qemu}
| | |--{ansible_libvirt_uri = qemu:///system}
|--@b02ea6c4-8dfa-4fc6-8a38-735325ff9815:
| |--test-dyn_default
| | |--{ansible_connection = community.libvirt.libvirt_qemu}
| | |--{ansible_libvirt_uri = qemu:///system}
|--@f2c2438a-3371-41ab-8afe-b8bb59374527:
| |--build-containers_builder
| | |--{ansible_connection = community.libvirt.libvirt_qemu}
| | |--{ansible_libvirt_uri = qemu:///system}
|--@f845cd23-8848-4ce8-9666-d01d6abc0c41:
| |--staticip
| | |--{ansible_connection = community.libvirt.libvirt_qemu}
| | |--{ansible_libvirt_uri = qemu:///system}
|--@ungrouped:

Vous remarquez la chaîne de connexion, ce n'est pas du ssh !

Si on lançait un module sur la machine staticip :

ansible -m ping staticip

staticip | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3.6"
},
"changed": false,
"ping": "pong"
}

Ça marche !

Mise en oeuvre du plugin Amazon Web Services EC2

Le lien vers le billet dédié à terraform + ansible + AWS

Mise en oeuvre du plugin Google Cloud Platform Compute

Le lien vers le billet dédié à terraform + ansible + GCP

Mise en oeuvre du plugin zabbix_inventory

C'est pratiquement la même chose. Il suffit de créer un fichier se nommant zabbix_inventory.yml et d'y mettre ceci :

plugin: community.zabbix.zabbix_inventory
server_url: https://zabbix.robert.local
login_user: user
login_password: xxxxxxxxxxx
validate_certs: no
add_zabbix_groups: true

Il faut bien sur au préalable créer le user sur votre serveur zabbix et lui donner des droits suffisant pour récupérer les serveurs monitorés.

Dans le fichier de config ansible :

[defaults]
inventory=libvirt.yml
interpreter_python=auto_silent
[inventory]
enable_plugins = community.zabbix.zabbix_inventory, auto, host_list, yaml, ini, toml, script

Il faut installer la collection et le la librairie python :

ansible-galaxy collection install community.zabbix
pip install zabbix-api

Maintenant lançons la commande d'inventaire :

ansible-inventory  --graph --vars
...
| |--server1
| | |--{zbx_auto_compress = 1}
| | |--{zbx_available = 1}
| | |--{zbx_description : }
| | |--{zbx_disable_until = 0}
| | |--{zbx_error = }
| | |--{zbx_errors_from = 0}
| | |--{zbx_flags = 0}
| | |--{zbx_host = server1}
...

Les machines remontent bien.

Scripts d'inventaire dynamique

Les inventaires dynamiques dans Ansible ne se limitent pas à l'utilisation de plugins. Une autre approche consiste à utiliser des scripts personnalisés écrits, par exemple, en Pythonn en bash, ... Ces scripts permettent à Ansible d'interroger des sources de données externes ou des services pour générer un inventaire en temps réel, offrant une flexibilité maximale dans la gestion des hôtes et des groupes.

Les scripts Python offrent une personnalisation poussée dans la création d'inventaires dynamiques. Ils peuvent être particulièrement utiles dans les cas où :

  • Il n'existe pas de plugin d'inventaire spécifique pour une plateforme ou un service.
  • Des logiques complexes de filtrage, de regroupement ou de transformation des données sont nécessaires.
  • On souhaite intégrer des sources de données propriétaires ou peu communes dans l'inventaire.

Un script d'inventaire dynamique Python doit être capable de produire un JSON structuré sur la sortie standard. Ce JSON doit suivre un format spécifique reconnu par Ansible, définissant des groupes, des hôtes et éventuellement des variables.

Voici un exemple très basique d'un script Python qui génère un inventaire dynamique :

#!/usr/bin/env python

import json
import psycopg2

# Configuration de la connexion à la base de données
DB_HOST = "votre_host_db"
DB_NAME = "nom_de_votre_db"
DB_USER = "votre_user"
DB_PASSWORD = "votre_password"

def fetch_hosts():
"""Récupère les hôtes de la base de données PostgreSQL."""
conn = psycopg2.connect(host=DB_HOST, dbname=DB_NAME, user=DB_USER, password=DB_PASSWORD)
cursor = conn.cursor()
cursor.execute("SELECT hostname, ip, group_name, ansible_user FROM hosts")
hosts = cursor.fetchall()
cursor.close()
conn.close()
return hosts

def generate_inventory(hosts):
"""Génère l'inventaire à partir de la liste des hôtes."""
inventory = {"_meta": {"hostvars": {}}}
groups = {}

for hostname, ip, group_name, ansible_user in hosts:
if group_name not in inventory:
inventory[group_name] = {"hosts": []}
inventory[group_name]["hosts"].append(hostname)

if group_name not in groups:
groups[group_name] = []
groups[group_name].append(hostname)

inventory["_meta"]["hostvars"][hostname] = {
"ansible_host": ip,
"ansible_user": ansible_user
}

inventory["all"] = {"children": list(groups.keys())}
return inventory

if __name__ == "__main__":
hosts = fetch_hosts()
inventory = generate_inventory(hosts)
print(json.dumps(inventory, indent=4))

Pour utiliser un script d'inventaire dynamique avec Ansible, le script doit être marqué comme exécutable et spécifié comme source d'inventaire lors de l'exécution des commandes Ansible :

chmod +x script_inventaire.py
ansible-playbook -i script_inventaire.py playbook.yml

Lors de l'utilisation de scripts d'inventaire dynamique, il est important de tenir compte de la sécurité et des performances. Assurez-vous que le script ne divulgue pas d'informations sensibles, comme dans l'exemple ci-dessus et qu'il est optimisé pour éviter des requêtes inutiles ou coûteuses à vos services ou bases de données.

Les scripts d'inventaire dynamique en Python offrent une méthode puissante et flexible pour intégrer des sources de données dynamiques dans Ansible, permettant une automatisation plus intelligente et adaptée à des environnements IT complexes et en constante évolution.

Pou vous aider le repository ansible community regroupe un certains nombres de ces scripts. On retrouve par exemple celui de rudder.io, freeipa, scaleway, vagrant, ...

Utilisation des inventaires

L'utilisation des inventaires dans Ansible, qu'ils soient statiques ou dynamiques, nécessite de comprendre comment invoquer ces inventaires lors de l'exécution des commandes Ansible et comment activer les plugins d'inventaire dynamique.

Dans les paramètres des outils en lignes de commande

Pour exécuter des tâches, des playbooks ou toute autre commande Ansible sur un ensemble spécifique d'hôtes, vous devez indiquer à Ansible quel inventaire utiliser. Ceci peut être fait en utilisant l'option -i suivie du chemin vers le fichier d'inventaire.

Exemple avec un inventaire statique :

ansible-playbook -i /chemin/vers/inventaire.ini playbook.yml

Exemple avec un inventaire dynamique :

ansible-playbook -i /chemin/vers/script_inventaire_dynamique.py playbook.yml

Dans ces exemples, l'option -i permet à Ansible de savoir quel inventaire charger pour l'opération en cours.

Spécification de l'inventaire dans le fichier de configuration

Il est également possible de spécifier un inventaire par défaut dans le fichier de configuration d'Ansible (généralement ansible.cfg). En définissant l'inventaire dans ce fichier, vous n'avez pas besoin de spécifier l'option -i à chaque commande.

[defaults]
inventory = /chemin/vers/inventaire.ini

Cette méthode est particulièrement utile lorsque vous travaillez principalement avec un ensemble d'hôtes et que vous souhaitez éviter de spécifier l'inventaire à chaque commande.

Activation des plugins d'inventaire dynamique

Pour les inventaires dynamiques, l'utilisation de plugins nécessite une étape supplémentaire d'activation et de configuration. Chaque plugin d'inventaire dynamique a ses propres exigences de configuration, qui doivent être spécifiées dans le fichier de configuration ansible ansible.cfg. Pa exemple pour le plugin libvirt :

[defaults]
inventory=libvirt.yml
interpreter_python=auto_silent
[inventory]
enable_plugins = community.libvirt.libvirt, auto, host_list, yaml, ini, toml, script

Vous remarquez que ce plugin d'inventaire, n'est pas installé par défaut, il faut donc installer la collection community.libvirt et la librairie python :

ansible-galaxy collection install community.libvirt
pip install libvirt-python

Utilisation de la commande ansible-inventory

La commande ansible-inventory est un des outil de l'écosystème Ansible, permettant aux utilisateurs de travailler avec les inventaires d'Ansible de manière interactive. Elle offre la possibilité de visualiser, les inventaires Ansible. Trois de ses options les plus utiles sont --list, --graph et --vars, chacune fournissant une perspective différente sur la structure et les détails de l'inventaire.

L'option --list

L'option --list affiche l'inventaire entier sous forme de JSON. C'est particulièrement utile pour voir une représentation complète de l'inventaire, y compris les hôtes, les groupes et les variables associées.

ansible-inventory -i chemin/vers/inventaire.ini --list

{
"_meta": {
"hostvars": {
"bastion": {
"ansible_host": "192.168.1.102",
"domainname": "robert.local"
},
"proxmox1": {
"ansible_host": "192.168.1.71",
"domainname": "robert.local"
}
}
},
"all": {
"children": [
"ungrouped",
"bastions",
"proxmoxs"
]
},
"bastions": {
"hosts": [
"bastion"
]
},
"proxmoxs": {
"hosts": [
"proxmox1"
]
}
}

Cette commande transforme l'inventaire spécifié en un objet JSON structuré, permettant une vue d'ensemble des configurations et facilitant l'intégration avec d'autres outils qui peuvent traiter le format JSON.

Il est possible de demander la sortie au format YAML et non JSON avec l'option -y :

ansible-inventory --list -y

all:
children:
bastions:
hosts:
bastion:
ansible_host: 192.168.1.102
domainname: robert.local
proxmoxs:
hosts:
proxmox1:
ansible_host: 192.168.1.71
domainname: robert.local

L'option --graph

L'option --graph fournit une représentation visuelle de la hiérarchie des groupes dans l'inventaire, affichant la relation entre les groupes et les sous-groupes.

ansible-inventory --graph --vars
@all:
|--@144f4357-30fe-4bf8-9484-6f3e6ff2312b:
| |--test-podman_db
| | |--{ansible_connection = community.libvirt.libvirt_qemu}
| | |--{ansible_libvirt_uri = qemu:///system}
|--@b02ea6c4-8dfa-4fc6-8a38-735325ff9815:
| |--test-dyn_default
| | |--{ansible_connection = community.libvirt.libvirt_qemu}
| | |--{ansible_libvirt_uri = qemu:///system}
|--@f2c2438a-3371-41ab-8afe-b8bb59374527:
| |--build-containers_builder
| | |--{ansible_connection = community.libvirt.libvirt_qemu}
| | |--{ansible_libvirt_uri = qemu:///system}
|--@f845cd23-8848-4ce8-9666-d01d6abc0c41:
| |--staticip
| | |--{ansible_connection = community.libvirt.libvirt_qemu}
| | |--{ansible_libvirt_uri = qemu:///system}
|--@ungrouped:

Cette commande est particulièrement utile pour comprendre comment les groupes sont organisés et comment ils s'imbriquent les uns dans les autres, ce qui peut aider à à déboguer des stratégies d'automatisation.

L'option --vars

L'option --vars est utilisée pour afficher toutes les variables d'inventaire pour chaque hôte dans l'inventaire. Elle peut être combinée avec --graph ou --list pour inclure les variables dans l'affichages.

ansible-inventory --list -y --vars

all:
children:
bastions:
hosts:
bastion:
ansible_host: 192.168.1.102
domainname: robert.local
proxmoxs:
hosts:
proxmox1:
ansible_host: 192.168.1.71
domainname: robert.local

Cette option aussi extrêmement utile pour vérifier les valeurs des variables appliquées à vos hôtes ou groupes, ce qui est indispensble pour le débogage et la validation des configurations Ansible.

Gestion des variables d'inventaires

La gestion des variables dans Ansible est essentielle pour personnaliser et adapter les configurations aux spécificités de chaque hôte ou groupe d'hôtes. Ansible offre une flexibilité remarquable à travers l'utilisation des dossiers host_vars et group_vars. Ces dossiers permettent de définir des variables spécifiques à chaque hôte (host_vars) ou groupe d'hôtes (group_vars), rendant vos playbooks plus propres et votre gestion des variables plus organisée.

Structure des dossiers host_vars et group_vars

Les dossiers host_vars et group_vars doivent être placés à la racine à côté de votre fichier d'inventaire. Ansible recherche automatiquement ces dossiers pour charger des variables supplémentaires.

  • group_vars : Contient des fichiers nommés d'après chaque groupe défini dans votre inventaire. Les variables définies dans ces fichiers seront appliquées à tous les membres du groupe correspondant.
  • host_vars : Contient des fichiers nommés d'après chaque hôte défini dans votre inventaire. Les variables définies dans ces fichiers seront appliquées uniquement à l'hôte spécifique.

Exemple de structure

inventaire.ini
group_vars/
groupe1.yml
groupe2.yml
host_vars/
host1.example.com.yml
host2.example.com.yml

Définition de variables dans group_vars et host_vars

Chaque fichier dans group_vars ou host_vars doit être au format YAML et peut contenir n'importe quel nombre de variables Ansible que vous souhaitez appliquer.

  • Exemple de group_vars/groupe1.yml :
nginx_version: "1.18.0"
php_version: "7.4"
  • Exemple de host_vars/host1.example.com.yml :
ansible_user: "utilisateur_specifique"
ansible_ssh_private_key_file: "/chemin/vers/la/cle/privee"

La priorité de lecture des variables par Ansible

Avant de vous lancer dans la création de variables il est important de connaître la priorité de lecture qu'Ansible applique lors de l'éxécution d'une commande. Ansible priorise la source des variables, de la plus petite à la plus grande dans cet ordre :

  • command line values (par exemple, -u my_user qui n'est pas une variable)
  • role defaults (défini dans role/defaults/main.yml) 1
  • inventory file or script group vars 2
  • inventory group_vars/all 3
  • playbook group_vars/all 3
  • inventory group_vars/* 3
  • playbook group_vars/* 3
  • inventory file or script host vars 2
  • inventory host_vars/* 3
  • playbook host_vars/* 3
  • host facts / cached set_facts 4
  • play vars
  • play vars_prompt
  • play vars_files
  • role vars (défini dans role/vars/main.yml)
  • block vars (seulement pour les tasks dans un block)
  • task vars (seulement pour les tasks)
  • include_vars
  • set_facts / registered vars
  • role (et include_role) params
  • include params
  • extra vars ( par exemple, -e "user=my_user")

On voit que les variables passées dans les paramètres de la commande ansible-playbook (-e) sont les plus forts, il gagne sur tout le monde.

Imaginez une infrastructure gérée avec des dizaines de playbooks, des dizaines de fichiers de variables, des dizaines de groupes, ... Si on ne s'organise par correctement, le risque est de rapidement d'en perdre le contrôle !

Avantages de l'utilisation de host_vars et group_vars

  • Modularité : Sépare la logique des variables de celle des tâches, rendant vos playbooks plus lisibles et faciles à maintenir.
  • Organisation : Permet une organisation claire des variables en les associant directement aux hôtes ou groupes concernés.
  • Flexibilité : Facilite l'ajustement des configurations pour des hôtes ou des groupes spécifiques sans modifier les playbooks ou les rôles eux-mêmes.
  • Sécurité : Peut être utilisé pour stocker des variables sensibles spécifiques à l'hôte ou au groupe, surtout lorsqu'il est combiné avec Ansible Vault pour chiffrer des données sensibles.

Bonnes pratiques

  • Nommez clairement vos fichiers dans group_vars et host_vars pour correspondre exactement aux noms de vos groupes et hôtes dans l'inventaire, évitant toute confusion.
  • Utilisez Ansible Vault pour chiffrer les fichiers contenant des informations sensibles dans group_vars et host_vars pour améliorer la sécurité.
  • Limitez l'utilisation de variables spécifiques à l'hôte aux cas où c'est absolument nécessaire, privilégiant les variables de groupe pour une gestion plus simple et centralisée.

La gestion des variables via host_vars et group_vars est une méthode puissante pour personnaliser les environnements et les configurations dans Ansible, assurant que chaque hôte ou groupe d'hôtes reçoit les paramètres requis pour son rôle unique au sein de votre infrastructure.

Gestion dynamique des groupes

Ansible offre la possibilité de créer ou de modifier dynamiquement des groupes d'hôtes pendant l'exécution d'un playbook, grâce aux modules add_host et group_by. Cette fonctionnalité est particulièrement utile pour organiser les hôtes en groupes basés sur des conditions ou des données récupérées durant l'exécution des tâches.

Utilisation du module add_host

Le module add_host permet d'ajouter dynamiquement des hôtes à l'inventaire en cours d'exécution, avec la possibilité de les associer à des groupes spécifiques et de définir des variables pour ces hôtes.

- name: Ajouter un hôte dynamiquement à l'inventaire
ansible.builtin.add_host:
name: "{{ new_host }}"
groups: groupe_dynamique
ansible_host: "{{ ip_dynamique }}"
foo: valeur

Dans cet exemple, un nouvel hôte est ajouté à l'inventaire sous le nom {{ new_host }}, avec l'adresse IP définie par {{ ip_dynamique }}. L'hôte est associé au groupe groupe_dynamique et une variable mon_variable lui est attribuée.

Utilisation du module group_by

Le module group_by permet de créer de nouveaux groupes ou de modifier les membres des groupes existants en fonction des variables ou des faits d'un hôte. C'est une manière efficace de regrouper dynamiquement les hôtes selon des critères spécifiques découverts ou définis pendant l'exécution du playbook.

Exemple d'utilisation de group_by :

- name: Grouper les hôtes par système d'exploitation
ansible.builtin.group_by:
key: os_{{ ansible_facts['os_family'] }}

Cet exemple crée des groupes basés sur la famille du système d'exploitation des hôtes (par exemple, os_RedHat, os_Debian etc.), en utilisant les faits collectés par Ansible (ansible_facts['os_family']).

Scénario combiné : add_host et group_by

Vous pouvez combiner add_host et group_by dans un playbook pour créer des groupes hautement personnalisés basés sur des conditions dynamiques ou des données récupérées au cours de l'exécution.

- name: Ajouter des hôtes et les regrouper dynamiquement
hosts: localhost
tasks:
- name: Ajouter un hôte dynamiquement
add_host:
name: "host{{ item }}"
groups: "groupe_temporaire"
ansible_host: "192.168.1.{{ item }}"
loop: "{{ range(1, 5) | list }}"

- name: Grouper les hôtes par disponibilité
group_by:
key: "disponibilite_{{ item.status }}"
loop:
- { name: "host1", status: "haute" }
- { name: "host2", status: "moyenne" }
- { name: "host3", status: "basse" }
- { name: "host4", status: "haute" }

Dans ce scénario, des hôtes sont d'abord ajoutés dynamiquement à l'inventaire avec add_host et associés à un groupe temporaire. Ensuite, le module group_by est utilisé pour les réorganiser en groupes basés sur leur statut de disponibilité.

La capacité de créer et de manipuler dynamiquement des groupes d'hôtes offre une grande flexibilité dans la gestion de l'inventaire et l'application des configurations, permettant à Ansible de s'adapter efficacement à des situations complexes et changeantes lors de l'automatisation des tâches.

Conclusion

L'automatisation avec Ansible transforme la manière dont les administrateurs système et les ingénieurs DevOps gèrent les infrastructures informatiques. En utilisant des inventaires statiques et dynamiques, combinés à une gestion efficace des variables via host_vars et group_vars, Ansible offre une flexibilité et une puissance inégalées pour la configuration et le déploiement d'environnements. L'ajout dynamique d'hôtes et la création de groupes personnalisés avec les modules add_host et group_by ouvrent encore plus de possibilités pour adapter l'automatisation à des besoins spécifiques, rendant les processus plus efficaces et moins sujets aux erreurs.