Automatiser l’administration SSH avec Fabric
Mise à jour :
Python Fabric simplifie l’administration distante grâce à l’automatisation des tâches via SSH. Avec son approche basée sur les fabfiles, Fabric permet d’exécuter facilement des commandes sur plusieurs serveurs, de déployer rapidement des applications et de gérer les infrastructures avec quelques lignes de code Python. Pourquoi continuer à exécuter manuellement des scripts répétitifs quand Fabric peut le faire pour vous ? Découvrez dans ce guide comment gagner du temps et automatiser efficacement vos déploiements.
Installation de Fabric
Pour commencer à utiliser Python Fabric, vous avez besoin d’un environnement Python configuré et d’un accès SSH fonctionnel à vos serveurs distants.
Prérequis SSH : Configuration des clés
Fabric communique avec vos serveurs via SSH, il est donc recommandé d’utiliser une authentification par clés SSH pour éviter les connexions par mot de passe répétées.
Si vous n’avez pas encore configuré de clés SSH, générez-en une sur votre machine locale avec la commande :
ssh-keygen -t rsa -b 4096 -C "email@example.com"
Envoyez ensuite votre clé publique vers votre serveur distant :
ssh-copy-id utilisateur@votre-serveur
Vérifiez que votre connexion SSH sans mot de passe est fonctionnelle :
ssh utilisateur@votre-serveur
Si vous êtes connecté directement sans demande de mot de passe, vous êtes prêt à utiliser Fabric.
Installation de Fabric avec pipx
L’installation de Fabric est très simple grâce au gestionnaire de paquets pipx qui crée un environnement isolé pour chaque application Python. Voici les étapes à suivre :
pipx install fabric
Pour vérifier que Fabric est correctement installé, exécutez la commande suivante :
fab --version
Vous devriez obtenir une sortie semblable à celle-ci :
Fabric 3.2.2Paramiko 3.4.0Invoke 2.2.0
Premier fabfile
Fabric repose sur l’utilisation d’un fichier nommé fabfile.py
, où vous
définissez vos tâches (tasks). Ce fichier est le cœur de vos scripts
d’automatisation.
Structure basique d’un fabfile
Un fabfile se compose de fonctions Python décorées avec l’annotation
@task
, indiquant à Fabric que ces fonctions peuvent être exécutées à
distance :
from fabric import task
@taskdef mise_a_jour(c): c.run('sudo apt update && sudo apt upgrade -y')
Dans cet exemple :
mise_a_jour
est une tâche simple qui exécute une commande sur le serveur distant pour mettre à jour les paquets.
Exécution d’une task via Fabric
Pour vérifier que votre fabfile
fonctionne, vous pouvez exécuter la commande
suivante :
fab --list
Available tasks:
mise-a-jour
Vous remarquez que le nom de la tâche est automatiquement converti en
snake_case. Pour exécuter la tâche mise_a_jour
, utilisez la commande suivante
en remplaçant <user>
et <host>
par vos informations de connexion SSH :
fab -H <user>@<host> mise-a-jour
Fabric établit une connexion SSH automatique et exécute la commande définie. Vous verrez une sortie détaillée affichée directement dans votre terminal, comme ceci :
Passer des arguments à une task
Vous pouvez facilement passer des arguments à vos tasks pour les rendre réutilisables. Exemple avec une tâche qui redémarre un service spécifique :
from fabric import task
@taskdef redemarrer_service(c, nom_service): c.run(f'sudo systemctl restart {nom_service}')
L’exécution se fait alors en spécifiant l’argument :
fab -H utilisateur@serveur-distant redemarrer_service --nom-service=nginx
Exécution locale avec local
Fabric permet d’exécuter une commande sur votre machine locale à partir de
votre fabfile.py
grâce à la fonction local
.
from fabric import task
@taskdef sauvegarde_locale(c): c.local('tar -czf sauvegarde.tar.gz /chemin/dossier')
L’exécution se fait simplement via :
fab sauvegarde-locale
Commandes avec privilèges (sudo
)
Pour exécuter une commande nécessitant les privilèges root sur le serveur
distant, Fabric fournit la méthode sudo
:
from fabric import task
@taskdef redemarrer_nginx(c): c.sudo('systemctl restart nginx')
Cette commande vous demandera un mot de passe si votre utilisateur n’est pas configuré en sudo sans mot de passe :
fab -H utilisateur@serveur-distant redemarrer_nginx
Gestion du contexte : cd
, prefix
, path
Fabric offre aussi des outils pratiques pour gérer le contexte d’exécution :
- Changer de répertoire (
cd
) :
from fabric import task
@taskdef deploy(c): with c.cd('/var/www/monapp'): c.run('git pull')
- Ajouter un préfixe (
prefix
) (par exemple, pour activer un virtualenv) :
from fabric import task
@taskdef deploy_app(c): with c.prefix('source /env/bin/activate'): c.run('pip install -r requirements.txt')
- Modifier temporairement la variable d’environnement PATH (
path
) :
from fabric import task
@taskdef execute_script(c): with c.path('/opt/scripts', behavior='prepend'): c.run('script_personnalise.sh')
Grâce à ces fonctions, Fabric simplifie considérablement l’exécution cohérente et structurée de vos commandes locales et distantes.
Transfert de fichiers avec put
et get
Fabric facilite également le transfert de fichiers entre votre machine locale et le serveur distant.
put
: pour envoyer des fichiers vers le serveur distant.get
: pour récupérer des fichiers depuis le serveur distant.
Exemple d’utilisation :
from fabric import task
@taskdef envoyer_fichier(c): c.put('mon_fichier.txt', '/tmp/mon_fichier.txt')
@taskdef recuperer_fichier(c): c.get('/tmp/mon_fichier.txt', 'mon_fichier.txt')
Déploiement simplifié avec Fabric
Python Fabric excelle particulièrement dans l’automatisation des déploiements d’applications. Voici comment automatiser simplement votre déploiement grâce à quelques lignes de Python.
Exemple simple : Déployer une application web
Imaginons une application hébergée sur GitHub que vous souhaitez déployer rapidement sur votre serveur distant :
from fabric import task
@taskdef deploy(c): with c.cd('/var/www/mon_app'): c.run('git pull origin main') c.sudo('systemctl restart mon_app.service')
Ce script réalise en une seule tâche :
- Le téléchargement des dernières modifications depuis GitHub.
- Le redémarrage automatique du service lié à votre application.
Exécutez simplement :
fab -H utilisateur@serveur-distant deploy
Déploiement en parallèle sur plusieurs serveurs
Fabric permet également d’effectuer des déploiements en parallèle sur plusieurs serveurs à la fois. Cela accélère considérablement les mises à jour en environnement de production :
fab -H web1,web2,web3 --parallel deploy
Chaque serveur exécute indépendamment le déploiement en simultané, réduisant drastiquement le temps nécessaire à la mise à jour globale.
Gestion d’erreurs en cours de déploiement
Fabric s’arrête par défaut si une erreur se produit. Vous pouvez contrôler
ce comportement grâce au paramètre warn=True
:
@taskdef deploy(c): with c.cd('/var/www/mon_app'): result = c.run('git pull origin main', warn=True) if result.failed: print("Erreur lors de la mise à jour du dépôt Git") else: c.sudo('systemctl restart mon_app.service')
Déploiement conditionnel selon la branche Git
Fabric peut également déployer différentes branches selon vos besoins (production, test…) :
@taskdef deploy(c, branche='main'): with c.cd('/var/www/mon_app'): c.run(f'git checkout {branche}') c.run('git pull') c.sudo('systemctl restart mon_app.service')
Utilisation :
fab -H serveur-prod deploy --branche=prodfab -H serveur-test deploy --branche=develop
Grâce à ces techniques, Fabric facilite et accélère vos déploiements tout en limitant les erreurs humaines.
Utiliser Group pour exécuter sur plusieurs hôtes
Fabric propose un outil puissant pour exécuter des tâches sur plusieurs
serveurs à la fois : l’objet Group
. Il permet de gérer un groupe de
connexions distantes de manière simple et cohérente, notamment pour les
déploiements multi-hôtes.
Déclarer un Group de connexions
Un Group
représente une liste de connexions SSH. Voici comment l’utiliser :
from fabric import task, Group
@taskdef uptime_group(c): group = Group("web1", "web2", "web3") for connection in group: connection.run("uptime")
Chaque hôte défini dans le groupe exécutera la commande uptime
indépendamment.
Authentification centralisée
Vous pouvez spécifier le nom d’utilisateur, la clé SSH ou d’autres options globales au moment de la création du groupe :
group = Group( "web1", "web2", "web3", user="admin", connect_kwargs={"key_filename": "~/.ssh/id_rsa"})
Exécution parallèle avec ThreadingGroup
Pour aller plus loin, utilisez ThreadingGroup
(fourni par le module
fabric.connection
) pour exécuter les commandes en parallèle, ce qui est
idéal lors de déploiements sur plusieurs machines :
from fabric import taskfrom fabric.connection import ThreadingGroup
@taskdef deploy_parallel(c): hosts = ["web1", "web2", "web3"] group = ThreadingGroup.from_connections([ c.clone(host=host) for host in hosts ]) group.run("git -C /var/www/app pull origin main") group.sudo("systemctl restart mon_app.service")
Filtrage et gestion des erreurs
Vous pouvez facilement capturer les erreurs et afficher les résultats pour chaque hôte :
for connection in group: result = connection.run("uptime", warn=True) if result.failed: print(f"{connection.host} : commande échouée")
Organisation des tâches
Pour une meilleure organisation de vos tâches, vous pouvez structurer votre
fabfile.py
en plusieurs fichiers. Par exemple, créez un dossier fabfile/
et
placez-y vos scripts :
fabfile/│├── __init__.py├── deploy.py # Tâches de déploiement├── system.py # Mises à jour système, gestion des services└── db.py # Sauvegardes, migrations, nettoyages
Dans le fichier __init__.py
, importez les tâches pour les rendre accessibles :
from .deploy import deployfrom .system import mise_a_jour, redemarrer_servicefrom .db import sauvegarde, migration
Dans le fichier deploy.py
, définissez vos tâches de déploiement :
from fabric import task
@taskdef deploy(c): c.run('git pull origin main') c.sudo('systemctl restart mon_app.service')
Dans les autres fichiers, ajoutez les tâches correspondantes.
Bonnes pratiques de fabfiles
Un fabfile bien structuré rend vos automatisations plus lisibles, maintenables et évolutives. Voici les meilleures pratiques à adopter pour tirer le meilleur parti de Fabric.
Nommer clairement les tasks
Choisissez des noms explicites et en français ou anglais selon votre convention d’équipe :
@taskdef redemarrer_nginx(c): ...
Cela facilite l’appel via la CLI :
fab redemarrer_nginx
Ajouter une docstring à chaque task
Fabric extrait la première ligne de docstring pour l’afficher dans fab --list
.
Exemple :
@taskdef deploy(c): """Déploie la dernière version de l'application""" ...
Résultat :
Available tasks:
deploy Déploie la dernière version de l'application
Gérer les erreurs proprement
Utilisez warn=True
pour éviter qu’un échec ne stoppe tout le processus, et
traitez les erreurs manuellement si nécessaire :
result = c.run('git pull', warn=True)if result.failed: print("Échec du pull Git")
Utiliser des paramètres
Les arguments de tâches rendent vos scripts adaptables :
@taskdef restart_service(c, name): """Redémarre un service donné""" c.sudo(f'systemctl restart {name}')
Appel :
fab restart_service --name=nginx
Documenter l’usage global
Ajoutez un fichier README.md
dans votre répertoire fabfile/
expliquant
comment installer, configurer et utiliser vos tâches.
Une alternative à Ansible ?
Si votre priorité est d’avoir un outil d’automatisation rapide à mettre en place, lisible et intégrable facilement à des scripts Python existants, Fabric constitue une excellente alternative à Ansible. Mais attention, Fabric n’est pas conçu pour gérer des configurations complexes ou des infrastructures massives. Il est plus adapté pour des tâches simples et des déploiements rapides.
Conclusion
Fabric est un outil puissant pour automatiser vos tâches d’administration système et de déploiement d’applications. Grâce à sa simplicité d’utilisation, vous pouvez rapidement mettre en place des scripts pour gérer vos serveurs distants, déployer vos applications et automatiser les tâches répétitives.