Fabric ou l'art d'envoyer une commande sur plusieurs serveurs

Billet posté le 29 août 2015

Bon bon on va présenter l’outil fabric. Cet outil permet de pouvoir envoyer une commande sur plusieurs serveurs à la fois. Le principe de fabric c’est donc de pouvoir exécuter une commande et de l’envoyer sur beaucoup de serveurs et en faire le moins possible.

Fabric est écrit en Python. Cela veut dire que quand vous allez écrire le fichier de configuration de fabric vous faîtes un petit peu de python ;-)

Pour l’installation il existe de nombreux packages pour une grande variété de distributions Linux et BSD Libres. Sous Debian et Ubuntu nous procédons de la manière suivante :

apt-get install fabric

Sous RHEL et distributions à base de RPM :

yum install fabric

Ou bien procéder via pip :

pip install fabric

Avant de pouvoir jouer avec fabric il convient de créer un fichier de configuration, par défaut celui-ci doit se nommer fabfile.py. Vous pouvez le créer dans votre home directory.

Voici le début du fichier.

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 = {
    'webservers': ['srv01','srv02','srv03'],
    'mailservers': ['srv04','srv05','srv06','srv07'],
    }

env.user = "mon_user"
env.password = "mon_password"

Plusieurs choses intéressantes dans cet extrait de fichier de configuration fabfile.py.

Tout d’abord les pré-requis / bibliothèques à importer. Ensuite, nous définissons des rôles : webservers et mailservers. Les rôles permettent de définir des groupes de serveurs et via un paramètre à la commande fabric on pourra alors exécuter des commandes sur des serveurs bien spécifiques en utilisant simplement le nom du rôle. Sympa hein ? Ensuite, nous définissons le nom d’utilisateur et le mot de passe. Alors là prudence. En effet, le mot de passe est écrit en clair dans le fichier de configuration et celui-ci n’est pas protégé par un chiffrement éventuel. Deux solutions : soit on protège le fichier via un chmod 600 ou bien et c’est plutôt même la méthode préférée on utilise une clé ssh publique qu’on aura pris le soin d’envoyer sur chacun des serveurs avant.

Ensuite, nous allons apprendre à exécuter une commande sur un ensemble de serveur. Afin de faire un exemple simple nous allons nous débrouiller pour exécuter la commande date sur un ensemble de serveur. Voici comment procéder, ajouter ces deux lignes dans le fichier fabfile.py. Attention il faut bien respecter la tabulation :

def mydate():
    run('date')

Vous pouvez alors enregistrer ce fichier et exécuter la commande suivante :

fab -H mon.seveur mydate

La commande shell s’appelle fab, l’option -H permet de préciser le nom du serveur que l’on souhaite requêter et mydate correspond à la commande que vous avez défini dans votre fichier fabfile.py.

Et sans surprise nous obtenons alors la date sur le serveur :

root@puppet:/srv/fabric# fab -H mon.serveur mydate
[mon.serveur] Executing task 'mydate'
[mon.serveur] run: date
[mon.serveur] out: Sun Aug 23 22:13:42 CEST 2015


Done.
Disconnecting from mon.serveur... done.
root@puppet:/srv/fabric#

Dans le début de l’article on évoquait le fait de pouvoir exécuter la commande sur plein de serveurs voici comment procéder :

fab -R webservers mydate

Et donc cela va exécuter la commande mydate sur tous les serveurs qui sont définis dans le rôle webservers. Par défaut cette commande fabric va exécuter mydate sur chaque serveur en séquentiel.

Nous allons maintenant effectuer la même commande fabric à l’exception que nous souhaitons avoir une exécution non plus séquentielle mais parallèle.

fab -P -R webservers mydate

Nous avons ajouté le paramètre “-P” qui indique une exécution en parallèle.

Il est aussi possible de faire une exécution en parallèle mais en définissant un nombre d’exécution max.

Par exemple : je veux exécuter la commande mydate en parallèle mais par lot de 3 :

fab -P -z 3 -R webservers mydate

Nous avons vu comment exécuter des commandes utilisateurs mais qu’en est-il pour des commandes ayant besoin d’avoir des droits root ?

Nous allons éditer à nouveau le fichier fabfile.py et y ajouter les lignes suivantes :

def get_size():
	sudo('df -h')

Il est aussi possible de lancer des commandes sudo en précisant un autre utilisateur :

def get_crontab():
    sudo("crontab -l | grep toto",user="titi")

Nous affichons la sortie de la commande crontab -l en utilisant sudo sous l’utilisateur titi.

Je vous laisse vous rapprocher de la documentation pour des choses plus avancées : http://docs.fabfile.org/en/1.10/