Ansible – inventaire dynamique avec PHP et MySQL

Ansible – inventaire dynamique avec PHP et MySQL

Ansible est un outil de gestion de configuration sous licence GNU GPL, très certainement disponible sur les dépôts de votre distribution Linux préférée. Il se démarque de ses concurrents par sa simplicité d’utilisation et de configuration et sa modularité. Pour les férus de sécurité, il est sans agents et utilise SSH pour contrôler les hôtes dont il a la charge.

Pour ceux qui ne connaissent pas, Ansible permet d’appliquer une configuration type à un système, de créer des comptes utilisateurs, d’installer des paquets… en parallèle et simultanément sur tous les hôtes d’une infrastructure.

Cet article n’est pas une introduction, il couvre un sujet bien précis : les inventaires dynamique. Et plus particulièrement, les inventaires dynamiques avec PHP et MySQL.

 

Note: les morceaux de codes présents dans cet article n’ont pas été testés. Vous devrez donc les corriger et les adapter pour pouvoir les utiliser.

Rappel sur les inventaires

Avant d’entrer dans le vif du sujet, voici un bref rappel de ce que sont les inventaires.

Un inventaire est une source de données qui permet à Ansible de connaître la liste des hôtes qu’il doit contrôler. C’est le minimum vital pour qu’Ansible puisse fonctionner.

Cette source de données peut être constituée d’un ou plusieurs fichiers respectant la syntaxe INI, on parle alors d’inventaire statique.

Voici un inventaire statique très simple regroupant trois hôtes dans deux groupes différents.

 

Pour un usage basique (i.e.: quelques hôtes à gérer et des playbook relativement simples), on peut très largement se contenter d’un inventaire statique.

Mais lorsque l’infrastructure devient conséquente, utiliser des fichiers devient très lourd à maintenir. Heureusement pour nous, Ansible est capable d’utiliser autre chose que des fichiers comme source de données.

Les inventaires dynamiques

De base, Ansible peut utiliser des sources de données dynamiques telles que AWS EC2 (le cloud Amazon), OpenStack, et bien d’autres.

Ansible est aussi capable d’utiliser un exécutable, on peut donc créer son propre inventaire dynamique. Peu importe le langage utilisé, du moment qu’il peut être exécuté et qu’il renvoi les données respectant la syntaxe JSON.

Si nous traduisons notre premier inventaire statique en JSON, et y ajoutons une « group_vars » domain, voici ce que ça donne :

Inventaire en PHP

Pour ma part, j’ai choisi d’utiliser PHP pour construire mon inventaire dynamique.

Si vous avez déjà joué avec PHP, vous ne serez pas perdus. Le but du jeu est de construire un tableau, qu’on traduira ensuite en JSON avant de l’afficher.

Le bout de code PHP qui suit reproduit l’inventaire précédent en JSON, group_vars comprise :

J’en conviens, c’est pas super dynamique tout ça…

Inventaire en PHP, avec MySQL

Imaginons maintenant que nous avons une base de données à disposition. MySQL pour l’exemple, mais on peut imaginer la même chose avec tout autre moteur.

Soit le SQL suivant, représentant un table « hosts_groups » et une table « hosts » :

On y retrouve nos groupes, nos hôtes et notre group_vars domain.

Le code PHP suivant vous donnera une idée de comment récupérer les données et les mettre en forme :

On s’approche de quelque chose d’exploitable par Ansible. Mais il manque encore un petit détail, les host_vars.

Les host_vars et _meta

Les host_vars sont des variables directement attribuées aux hôtes. Dans un inventaire statique, elles sont soit définies dans le fichier d’inventaire, soit dans un fichier yaml portant le nom de l’hôte et positionné dans /etc/ansible/host_vars/

Au lancement d’un playbook, Ansible va lire son inventaire, puis ira, pour chaque hôte concerné par le playbook et un par un, chercher les host_vars. Notre script doit donc pouvoir donner deux types d’informations différentes : la liste des groupes et hôtes, et les host_vars d’un hôte défini.

Pour pouvoir gérer ces deux scénarios, Ansible appelle notre script avec des arguments.

Pour construire son inventaire : --list

Pour récupérer les host_vars d’un hôte : --host <hostname>

Ce qui donnera au total quatre appels successifs puisque nous avons trois hôtes dans notre inventaire.

Un peu comme $_POST et $_GET, nous pouvons récupérer ces arguments grâce à PHP, et donc renvoyer des données différentes suivant leurs valeurs. Ces arguments sont mis dans un tableau nommé $argv  :

Note: Pour cet exemple j’ai utilisé deux champs qui ne sont pas définis dans mon SQL

Comme je l’ai dit plus haut, notre script sera appelé autant de fois qu’il y a d’hôtes concernés par le playbook. Pour diminuer le nombre d’appels, nous pouvons générer une variable « _meta » qui regroupe toutes ces host_vars et la renvoyer avec l’inventaire complet.

La structure finale doit être du genre :

Vous avez maintenant un script exploitable par Ansible !

Mais on peut encore aller un peu plus loin…

Des hôtes, des groupes, des variables,…

Le JSON retourné est un gros tableau. On peut penser, et à juste titre, qu’on peut peupler notre tableau comme on le souhaite.

Imaginons qu’on ait besoin de déployer des comptes unix sur un groupe d’hôtes, c’est possible.

Pour ce faire, on va créer une table regroupant toutes les informations nécessaires pour créer un compte (identifiant, hash du mot de passe, id du groupe d’hôtes concerné, clé ssh publique, …, etat[1]).

Pensez à utiliser des jointures pour récupérer le nom du groupe :

Pour utiliser cette variable « admins_enabled », je n’ai plus qu’à l’appeler dans une tâche :

Jusqu’où peut on aller

On peut faire exactement la même chose qu’avec un inventaire statique, mais sans la lourdeur de maintenir des fichiers à plat. Voici quelques idées :

  • les vhosts apache,
  • les dépôts git,
  • les clés ssh des développeurs,
  • les zones dns,

Si une interface web est créée, on peut même envisager de mettre en place un système de hooks pour qu’un playbook soit lancé dès qu’il y a modification des données.

Quelques conseils

Le shebang

Le Shebang est la première ligne du script : #!/usr/bin/php

Elle est importante car elle permet au système de connaître l’interpréteur à utiliser pour exécuter le script.

Un argument en plus : --debug

Intégrer la gestion de ce troisième argument permet d’afficher les données sous un autre format plus lisible que le JSON. Un var_dump par exemple.

Les groupes

Généralement, on utilise des groupes fonctionnels, des groupes géographiques, et des groupes par rôles (serveurs web, serveurs de bases de données, etc.).

L’inventaire dynamique peut donner beaucoup plus de souplesse sur la façon dont on peut cibler des hôtes spécifiques.

Rien n’empêche de mettre un hôte dans plusieurs groupes.

Pour ma part, j’ai opté pour un structure qui peut être représentée comme ça :

J’attribue mes group_vars en fonction des besoins.  Mes comptes admins sont dans les groupes fonctionnels. Mais les vhost, dans les groupes « par rôle dans un groupe fonctionnel ». Et enfin les paquets à installer dans les groupes par rôle…

[1] Le champ état : admins_enabled vs admins_disabled

Je l’ai mis en gras mais je n’ai pas insisté dessus, et pourtant il est important.

Ansible est un outil de gestion de configuration et d’automatisation. On peut faire des choses. Mais on peut aussi en défaire…

Le champ état sur ma table admins peut me permettre de différencier un compte unix à créer d’un compte unix à supprimer.

Conclusion

Pour finir sur le sujet, je dirais que la seule limite est votre imagination.

Si vous avez des questions (je sais que je suis passé trèèèès rapidement sur certains points), n’hésitez pas à laisser un commentaire.

2 réactions au sujet de « Ansible – inventaire dynamique avec PHP et MySQL »

  1. Bonjour, j’ai trouvé votre article intéressant pour plusieurs raisons : il est en français, il parle d’Ansible et fait le lien avec une approche dynamique du stockage des variables hosts, groups etc…

    Ansible est un formidable outil pour la centralisation et la gestion de la configuration mais également un support incontournable pour le suivi de l’inventaire. Associé à Git, on peut complètement tracer l’évolution de son infrastructure.

    Est-ce qu’on ne perd pas cette traçabilité en stockant dans mysql ? (pour ceux qui ne veulent pas commiter des mots de passe ou les stocker dans mysql, l’utilisation des vault est un vrai plus)

  2. Bonjour et merci pour votre commentaire.

    Un inventaire dynamique dans ce style est une application à part entière. On peut tout à fait la concevoir pour apporter une traçabilité de qui fait quoi, quand, comment, etc.

    Je n’ai pas encore eu l’occasion d’utiliser vault.
    Quoi qu’il en soit, il est possible de stocker les mots de passe chiffrés dans mysql et de les déchiffrer dans l’inventaire dynamique avec mcrypt ou phpseclib.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.