PyInfra un gestionnaire de configuration
Je vous propose de découvrir un gestionnaire de configuration se nommant PyInfra. PyInfra n’est pourtant pas un projet tout jeune puisque la première version date de 2016. PyInfra mérite cependant qu’on s’y attarde, car il peut rendre bien des services et se veut simple à prendre en main surtout si on connait le langage Python.
Introduction à PyInfra
PyInfra se pose en alternative à Ansible dont il en reprend les grands principes. Plutôt que d’utiliser une syntaxe à base de YAML ou JSON, il décrit ses configurations en Python permettant ainsi d’utiliser toutes les librairies de ce langage sans difficultés.
On retrouve aussi :
- Des inventaires, appelé
inventory
, permettant de définir des groupes et de leur assigner des variables. - Des
operations
, l’équivalent des modules Ansible, permettant de configurer les machines cibles. - Des
facts
permettant de récupérer l’état actuel des serveurs cibles.
Premiers pas avec PyInfra
Comme d’habitude, je vais utiliser des machines provisionnées avec Vagrant
.
Voici un simple Vagrantfile :
On provisionne la machine :
Installation de Pyinfra
PyInfra étant écrit en python, vous pouvez utiliser pip
ou pipx
pour
l’installer.
Le mode adhoc
Pour lancer une simple action, nous allons utiliser le mode adhoc
:
L’inventaire peut être une simple machine ou un fichier d’inventaire. Une
machine est décrite sous la forme @connecteur/nom_serveur. Le connecteur par
défaut est bien sûr SSH
. Mais il est possible d’en utiliser d’autres comme
Local, Docker, Vagrant, Terraform, SSH… Une opération, l’équivalent des
modules ansible, permet de configurer les serveurs cibles.
Pour lancer la collecte des facts
sur la machine local :
Un premier inventaire PyInfra
Comme je l’ai dit plus haut, les personnes utilisant Ansible ne seront pas dépaysés. On retrouve les inventaires avec les mêmes notions de groupes et de variables.
Je vais utiliser le connecteur Vagrant. Pour accèder aux machines il faudra
lancer les commandes PyInfra dans le répertoire où se trouve le fichier
VagrantFile
.
Maintenant écrivons notre inventaire que nous nommons inventory.py
:
Dans cet inventaire, nous définissons le group nodes dans lequel nous ajoutons
notre machine vagrant. Pour lancer notre configuration sur une seule machine,
nous pouvons utiliser l’option --limit
.
On relance la commande en utilisant notre fichier d’inventaire en se limitant au
groupe nodes
:
Ecriture de notre première configuration
Comme dit plus haut, les configurations sont écrites en Python dont voici la structure minimale :
Dans cet exemple, nous allons utiliser l’opération apt.packages
puisque notre
machine est une Ubuntu. Contrairement à Ansible il n’y pas de modules package
gérant l’ensemble des services de packages rencontrés.
Pour définir les paramètres, il faut se rendre sur la documentation de l’opération apt ↗
Pour l’élévation de droits pour une opération, il suffit d’utiliser le paramètre
_sudo
. Pour retrouver la liste de tous paramètres globaux, c’est
ici. ↗
Nommer ce fichier deploy.py. Et lançons son exécution :
Super notre package est bien présent. Par contre, si je relance à nouveau la
commande, je vois toujours changed
1 dans le rapport final. Pour déboguer, il
suffit de lancer an ajoutant l’option -vvv
qui affiche toutes les opérations
effectuées par pyinfra
. Ah c’est le paramètre update
qui fait ce changement
d’état ce qui est vrai. Si on le retire et que l’on relance notre
configuration, nous obtenons bien changed:0
.
Utilisation des facts
Bon voilà cela fonctionne, mais comment faire si nous avons plusieurs variantes
de Linux pour différencier les opérations. L’équivalent du when
d’Ansible ?
Nous allons utiliser les facts.
Nous allons faire appel à l’opération host.get_fact
pour récupérer le type de
Linux. Ce fact se trouve dans les facts de type server
et se nomme LinuxName
.
Tous les facts sont documentés ici. ↗
Nous aurions pu utiliser aussi server.LinuxDistribution
.
Nous relançons notre configuration. Cela fonctionne comme attendu.
Une configuration plus avancée
Je vous propose de configurer notre machine vagrant pour qu’elle accepte les connexions ssh avec la clé ed25519 de mon compte personnel :
Pour cela, j’ai utilisé les opérations systemd.service
et files.line
. Pour
récupérer le contenu d’un fichier, on utilise le code python classique de lecture
de fichier.
Nous relançons, testons la connexion en ssh
:
Cela veut dire que nous pouvons désormais utiliser le connecteur ssh plutôt que Vagrant pour nos prochaines configurations.
Utilisation des variables dans les inventaires
Nous allons enrichir notre inventaire en ajoutant un groupe contenant notre machine à laquelle nous définissons une variable :
Voyons comment utiliser cette variable dans une nouvelle configuration :
Lançons notre configuration en limitant sur le groupe ssh_nodes :
Si on regarde les traces du mode verbose, nous pouvons remarquer que pyinfra fait une première analyse des packages présents pour identifier quels sont ceux à vraiment installer. Je me suis amusé à ajouter une seconde opération apt et le test est bien fait en amont. Clairement surpris et de la bonne manière. On définit bien un état à obtenir et non une suite d’opérations à effectuer. Une gestionnaire de configuration de type déclaratif. À vérifier sur d’autres types d’opérations
Toutes les opérations sont classées par catégorie :
- Basics : Files Operations, Server Operations, Git Operations, Systemd Operations
- System Packages : Apt Operations, Apk Operations, Brew Operations, Dnf Operations, Yum Operations
- Language Packages : Gem Operations, Npm Operations, Pip Operations
- Databases : Postgresql Operations, Mysql Operations
Leurs documentations sont documentées ici. ↗ Vous remarquerez que la liste est plutôt courte, mais on y retrouve le minimum vital.
Plus loin avec PyInfra
Maintenant que j’ai écrit ma première configuration PyInfra, voici les avantages que je vois :
- Comme Ansible, il est agentless.
- Il dispose de multiples connecteurs comme vagrant, docker, terraform, ansible, winrm … et ssh bien sur.
- Quelqu’un connaissant le langage python ne sera pas perdu. En effet, PyInfra n’utilise pas de syntaxe basée sur du JSON, ni du YAML mais écrit ses configurations en Python. Ce qui permet d’utiliser toutes les fonctionnalités de ce langage, comme les conditions, les tests, les décorateurs…
- Comme ses configurations sont écrites en Python le débogage est facile.
- Il possède de multiples opérateurs pour configurer ses cibles : server, files, user, apt, apk, dnf, git, mysql,…
- Il intégre un collecteur de facts
- Il peut être étendu par des développements maison pour ajouter des
operations
ou desconnectors
. - Il possède une API
- On a bien un gestionnaire de configuration déclaratif !
Au final, il faut poursuivre plus loin les tests, mais PyInfra me donne vraiment envie de l’utiliser. PyInfra a clairement un gros potentiel !!!!