Fabric, le couteau suisse de l’automatisation

Magazine
Marque
Linux Pratique
Numéro
122
Mois de parution
novembre 2020
Spécialité(s)


Résumé

Fabric est une bibliothèque Python et une interface en ligne de commandes facilitant l’utilisation de SSH, que ce soit pour des applications ou dans le but d’automatiser certaines tâches répétitives d’administration système. La grande force de Fabric est d’être particulièrement simple à utiliser.


Body

1. Fabric, késako ?

Fabric, c’est tout le contraire des outils DevOps modernes tels que Salt ou Ansible pour ne citer que ceux qui opèrent au-dessus du protocole SSH. Ce n’est pas un langage de haut niveau avec de nombreux modules faisant abstraction des couches système inférieures. Point d’idempotence, de templates ou toutes les fonctionnalités qui font des outils de gestion de configuration le saint Graal de l’orchestration et pourtant je suis un fervent partisan de Puppet.

Pour autant, lorsqu’il s’agit d’interagir rapidement sur un grand nombre de serveurs, Puppet n’est pas la solution la plus efficace et un cluster SSH encore moins. L’adoption de Fabric dans mon entreprise lorsque le produit est devenu mature a radicalement changé notre façon d’administrer nos nombreux systèmes en parallèle de l’utilisation de Puppet. Il m’est ainsi arrivé fréquemment d’utiliser Fabric pour bootstraper des agents Puppet.

Lorsque l’on écrit du code Fabric, on travaille avec les primitives natives de SSH et le shell et on fait moins qu’effleurer du Python. C’est cette simplicité qui fait de Fabric un véritable couteau suisse, utilisable par n’importe qui.

Comme Ansible donc, il se base sur SSH. Il n’y a donc aucun agent particulier à installer. L’authentification est gérée par SSH, on peut donc se logger par login/mot de passe ou par clé SSH. Sudo est géré pour la délégation de droits ainsi que les primitives de transfert de fichiers.

2. On en est à quelle version déjà ?

Fabric première version est la version historique, disponible dans les dépôts Ubuntu 14.04 et 16.04 qui a comme grand défaut de n’être compatible que jusqu’à Python 2.7 qui n’est plus supporté par la fondation Python depuis un an, mais peut-être encore par votre distribution.

Fabric2 est une réécriture majeure qui supporte Python 3, dont le but avoué des développeurs est d’être plus facilement maintenable. Cependant, cette nouvelle version apporte une syntaxe largement modifiée et dont il manque encore de nombreuses fonctionnalités pour un sysadmin comme les groupes de machines. Mais pour un développeur qui cherche une surcouche à plus haut niveau que le shell pour déployer une application ou qui a besoin d’une intégration SSH avec Django au-dessus de ce que fourni le framework paramiko, le produit est tout à fait adapté.

Enfin, ma version de prédilection est Fabric3. C’est un fork amical de Fabric1 conçu pour fonctionner avec Python > 3.4. L’installation passe par le système de packages Python pip, tout ce qu’il y a de plus classique :

pip3 install Fabric3

3. Tout commence par un fabfile

Le lancement de fabric se fait par la commande fab qui cherche ses instructions dans un fichier fabfile.py dans le répertoire courant. Malgré l’extension du fichier, les connaissances requises en Python sont très faibles pour écrire un fabfile.

Voyons donc un premier fabfile avec une seule fonction :

from fabric.api import abort, cd, env, get, hide, hosts, local, prompt, \
    put, require, roles, run, runs_once, settings, show, sudo, warn, open_shell
 
def host_details():
    run('lsb_release -a')

Et allons exécuter notre fonction sur l’un de nos serveurs :

fab -H ldap1 host_details
 
[ldap1] Executing task 'host_details'
[ldap1] run: lsb_release -a
[ldap1] Login password for 'julien':
[ldap1] out: No LSB modules are available.
[ldap1] out: Distributor ID:   Ubuntu
[ldap1] out: Description:      Ubuntu 20.04 LTS
[ldap1] out: Release: 20.04
[ldap1] out: Codename: focal
[ldap1] out:
 

Quand il s’agit de simplement lancer une commande à usage unique, il est possible d’appeler directement fabric avec en paramètre notre commande sans avoir besoin de modifier le fabfile.

fab -H ldap2,ldap1 -- lsb_release -a
[ldap2] Executing task '<remainder>'
[ldap2] run: lsb_release -a
[ldap2] Login password for 'julien':
[ldap2] out: No LSB modules are available.
[ldap2] out: Distributor ID:    Ubuntu
[ldap2] out: Description:       Ubuntu 18.04.4 LTS
[ldap2] out: Release:   18.04
[ldap2] out: Codename: bionic
 
[ldap1] Executing task '<remainder>'
[ldap1] run: lsb_release -a
[ldap1] out: No LSB modules are available.
[ldap1] out: Distributor ID:   Ubuntu
[ldap1] out: Description:      Ubuntu 20.04 LTS
[ldap1] out: Release: 20.04
[ldap1] out: Codename: focal

4. On mutualise avec les rôles

Je parlais d’administration d’un parc de serveurs donc ma commande fabric elle est jolie, elle me permet de spécifier plusieurs serveurs en utilisant fab -H ldap1,ldap2, mais ce n’est pas très pratique à utiliser. Et puis surtout je n’ai pas besoin de connaître et saisir le nom de tous les serveurs lorsque je déploie une nouvelle configuration SNMP, en particulier lorsque le parc est mouvant.

Pour cela, Fabric expose une variable d’environnements env.roledefs, en pratique un dictionnaire permettant d’organiser nos serveurs par rôles. Bien entendu, un serveur peut se retrouver dans plusieurs rôles, mais il n’est pas possible d’utiliser nos définitions de rôles sous la forme imbriquée, d’union ou d’intersection.

env.roledefs = {
    'dns': ['ns1', 'ns2'],
    'ldap': ['ldap1', 'ldap2'],
    'world': ['ldap1', 'ldap2', 'ns1', 'ns2'],
}

Comme pour les hôtes, on peut au besoin lancer une commande sur plusieurs rôles en les séparant par une virgule. Et quand le nombre de machines devient trop grand, il est même possible de paralléliser l’exécution avec -P.

fab -R ldap host_details
 
[ldap1] Executing task 'host_details'
[ldap1] run: lsb_release -a
[ldap1] Login password for 'julien':
[ldap1] out: No LSB modules are available.
[ldap1] out: Distributor ID:   Ubuntu
[ldap1] out: Description:      Ubuntu 20.04 LTS
[ldap1] out: Release: 20.04
[ldap1] out: Codename: focal
[ldap1] out:
[ldap2] Executing task 'host_details'
[ldap2] run: lsb_release -a
[ldap2] out: No LSB modules are available.
[ldap2] out: Distributor ID:    Ubuntu
[ldap2] out: Description:       Ubuntu 18.04.4 LTS
[ldap2] out: Release:   18.04
[ldap2] out: Codename: bionic

Personnellement, j’ai tendance à découper mes rôles par profil de serveur (DB, LDAP, SMTP, etc.), par environnement (recette, production…) et créer un rôle qui contient l’ensemble des serveurs.

5. Tout SSH dans un fabfile

Pour le premier exemple nous avons simplement utilisé la primitive run, mais fabric en dispose d’une multitude d’autres pour couvrir l’essentiel des cas d’usages d’un sysadmin :

  • sudo : forcément lorsqu’on parle d’administration système se pose la question des droits. Pas question de tout faire en root, d’ailleurs le compte est probablement désactivé à la connexion SSH. L’utilisation se fait de la même façon que la commande run :
  • sudo('systemctl restart snmpd.service')
  • Et il est aussi possible de préciser l’utilisateur sous lequel exécuter la commande en sudo :
  • sudo('/opt/zimbra/bin/zmlocalconfig ldap_host',user="zimbra")
  • Transférer des fichiers avec get et put :
  • put('snmpd.conf','/etc/snmp/snmpd.conf',use_sudo=True,mirror_local_mode=True)
  • ou à l’inverse :
  • get('/etc/resolv.conf','resolv.conf')
  • mirror_local_mode, optionnel, est bien pratique pour répliquer les permissions locales sur la machine distante. Il est tout autant possible de spécifier les permissions avec mode=’0640’ ou ne rien indiquer.
  • Redémarrer un serveur : reboot(), par défaut avec un timer de 120 secondes.
  • Interaction avec le sysadmin avec prompt :
  • def installpkg():
  •     pkg = prompt('Lequel monseigneur?')
  •     sudo('apt -y install '+pkg)
  • Les contextes : ils permettent de redéfinir une partie de l’environnement pour fournir un contexte d’exécution aux commandes qui seront lancées.
  • def run_commande():
  •     with shell_env(PATH='/opt/zimbra/bin:$PATH'):
  •                 run("commande")
  • lcd modifie le chemin de la machine sur laquelle le fabfile est exécuté et cd la machine sur laquelle on se connecte.   
  • def update_git() :
  •         with cd("/srv/project"):
  •             run("git pull")

6. Environnement

Fabric propose également certaines dispositions pour interagir avec les variables d’environnement. De manière absolument pas sécurisée, les variables env.user et env.password permettent d’indiquer les identifiants de connexion de manière globale dans le fabfile, la dernière chose à montrer à son RSSI donc.

Néanmoins, d’autres aspects de l’environnement ont toute leur place sur un grand parc. Notamment, si je veux collecter tous les fichiers /etc/resolv.conf de mes serveurs pour les auditer, je peux facilement les récupérer localement nommés de manière appropriée :

def get_resolvconf():
  get('/etc/resolv.conf','/tmp/resolv.conf-+env.host)

7. Un exemple dans le monde réel

Pour ne pas finir sur une bête liste de commandes, voici ce que nous donnerait un script fabric pour déployer un service SNMP avec un fichier de configuration local. Il y a de fortes chances que du SNMP soit standardisé sur un parc de machines et l’utilisation d’un outil d’automatisation tel que Fabric a toute sa place.

from fabric.api import abort, cd, env, get, hide, hosts, local, prompt, \
    put, require, roles, run, runs_once, settings, show, sudo, warn, open_shell
 
 
env.roledefs = {
    'dns': ['ns1', 'ns2'],
    'ldap': ['master', 'slave'],
    'world': ['ldap1', 'ldap2', 'ns1', 'ns2'],
}
 
def yumcleanup():
    sudo('yum clean all')
 
def inst_snmp():
    sudo('yum install net-snmp')
    sudo('systemctl enable snmpd.service')
 
def conf_snmp():
    put('snmpd.conf','/etc/snmp/snmpd.conf',use_sudo=True,mode=’0600’)
    sudo('systemctl restart snmpd.service')
 
def deploy_snmp():
    yumcleanup()
    inst_snmp()
    conf_snmp()

Il suffit ensuite d’appeler la commande deploy_snmp pour déclencher la configuration du SNMP sur les serveurs désirés. Et en quelques lignes de Python de plus, il est possible de rendre les commandes neutres sur le système de packages utilisé par la distribution.

Conclusion

Fabric n’est plus tout jeune dans le monde Linux et open source désormais. Bien qu'il soit largement dépassé par d’autres solutions autour de SSH comme Salt ou Ansible sur le terrain des fonctionnalités, ces logiciels ne doivent pas être opposés.

Je considère qu’un outil simple garde son intérêt pour sa souplesse et sa facilité d’utilisation. Il est en effet bien plus simple d’écrire une fonction de quelques lignes à exécuter sur plusieurs machines que l’équivalent Ansible, surtout quand c’est du code jetable.



Article rédigé par

Par le(s) même(s) auteur(s)

Déployer des environnements de développement avec Vagrant

Magazine
Marque
Linux Pratique
Numéro
127
Mois de parution
septembre 2021
Spécialité(s)
Résumé

Vagrant est un logiciel libre permettant de déployer rapidement des machines virtuelles. C'est un logiciel développé par la société Hashicorp, déjà connue pour d'autres logiciels comme Terraform, Packer ou Vault. Historiquement lié à VirtualBox, Vagrant s'est désormais largement ouvert à d'autres solutions de virtualisation comme Libvirt ou de conteneurisation comme Docker.

Utilisez Terraform pour vos projets Docker

Magazine
Marque
GNU/Linux Magazine
Numéro
240
Mois de parution
septembre 2020
Spécialité(s)
Résumé

Terraform est un outil populaire pour déployer de l’infrastructure en particulier à destination des Clouds publics. Cependant, il possède de nombreux providers pour dialoguer avec différents hyperviseurs, bases de données ou solutions d’infrastructures en Software Defined. Voyons dans cet article son utilisation avec Docker.

Tirez le meilleur parti de votre gestionnaire de configuration Puppet

Magazine
Marque
Linux Pratique
Numéro
119
Mois de parution
mai 2020
Spécialité(s)
Résumé

Puppet [1], outil de gestion de configuration et d’automatisation, a été présenté précédemment dans les colonnes de Linux Pratique [2]. Je vous propose de découvrir certaines fonctionnalités du logiciel qui ont évolué ou qui méritent de s’y attarder pour exploiter au mieux cet outil.

Les derniers articles Premiums

Les derniers articles Premium

Donnez une autre dimension à vos logs avec Vector

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Avoir des informations précises et détaillées sur ce qu’il se passe dans une infrastructure, et sur les applications qu'elle héberge est un enjeu critique pour votre business. Cependant, ça demande du temps, temps qu'on préfère parfois se réserver pour d'autres tâches jugées plus prioritaires. Mais qu'un système plante, qu'une application perde les pédales ou qu'une faille de sécurité soit découverte et c'est la panique à bord ! Alors je vous le demande, qui voudrait rester aveugle quand l'observabilité a tout à vous offrir ?

Du graphisme dans un terminal ? Oui, avec sixel

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

On le voit de plus en plus, les outils en ligne de commandes s'étoffent peu à peu d'éléments graphiques sous la forme d'émojis UTF8. Plus qu'une simple décoration, cette pointe de « graphisme » dans un monde de texte apporte réellement un plus en termes d'expérience utilisateur et véhicule, de façon condensée, des informations utiles. Pour autant, cette façon de sortir du cadre purement textuel d'un terminal n'est en rien une nouveauté. Pour preuve, fin des années 80 DEC introduisait le VT340 supportant des graphismes en couleurs, et cette compatibilité existe toujours...

Game & Watch : utilisons judicieusement la mémoire

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Au terme de l'article précédent [1] concernant la transformation de la console Nintendo Game & Watch en plateforme de développement, nous nous sommes heurtés à un problème : les 128 Ko de flash intégrés au microcontrôleur STM32 sont une ressource précieuse, car en quantité réduite. Mais heureusement pour nous, le STM32H7B0 dispose d'une mémoire vive de taille conséquente (~ 1,2 Mo) et se trouve être connecté à une flash externe QSPI offrant autant d'espace. Pour pouvoir développer des codes plus étoffés, nous devons apprendre à utiliser ces deux ressources.

Les listes de lecture

8 article(s) - ajoutée le 01/07/2020
Découvrez notre sélection d'articles pour faire vos premiers pas avec les conteneurs, apprendre à les configurer et les utiliser au quotidien.
11 article(s) - ajoutée le 02/07/2020
Si vous recherchez quels sont les outils du DevOps et comment les utiliser, cette liste est faite pour vous.
8 article(s) - ajoutée le 02/07/2020
Il est essentiel d'effectuer des sauvegardes régulières de son travail pour éviter de perdre toutes ses données bêtement. De nombreux outils sont disponibles pour nous assister dans cette tâche.
Voir les 49 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous