Aller au contenu

Automatiser l’administration SSH avec Fabric

Mise à jour :

logo python

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 :

Terminal window
ssh-keygen -t rsa -b 4096 -C "email@example.com"

Envoyez ensuite votre clé publique vers votre serveur distant :

Terminal window
ssh-copy-id utilisateur@votre-serveur

Vérifiez que votre connexion SSH sans mot de passe est fonctionnelle :

Terminal window
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 :

Terminal window
pipx install fabric

Pour vérifier que Fabric est correctement installé, exécutez la commande suivante :

Terminal window
fab --version

Vous devriez obtenir une sortie semblable à celle-ci :

Terminal window
Fabric 3.2.2
Paramiko 3.4.0
Invoke 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
@task
def 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 :

Terminal window
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 :

Terminal window
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 :

Terminal window

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
@task
def redemarrer_service(c, nom_service):
c.run(f'sudo systemctl restart {nom_service}')

L’exécution se fait alors en spécifiant l’argument :

Terminal window
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
@task
def sauvegarde_locale(c):
c.local('tar -czf sauvegarde.tar.gz /chemin/dossier')

L’exécution se fait simplement via :

Terminal window
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
@task
def 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 :

Terminal window
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
@task
def 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
@task
def 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
@task
def 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
@task
def envoyer_fichier(c):
c.put('mon_fichier.txt', '/tmp/mon_fichier.txt')
@task
def 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
@task
def 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 :

  1. Le téléchargement des dernières modifications depuis GitHub.
  2. Le redémarrage automatique du service lié à votre application.

Exécutez simplement :

Terminal window
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 :

Terminal window
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 :

@task
def 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…) :

@task
def 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 :

Terminal window
fab -H serveur-prod deploy --branche=prod
fab -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
@task
def 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 task
from fabric.connection import ThreadingGroup
@task
def 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 :

Terminal window
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 deploy
from .system import mise_a_jour, redemarrer_service
from .db import sauvegarde, migration

Dans le fichier deploy.py, définissez vos tâches de déploiement :

from fabric import task
@task
def 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 :

@task
def redemarrer_nginx(c): ...

Cela facilite l’appel via la CLI :

Terminal window
fab redemarrer_nginx

Ajouter une docstring à chaque task

Fabric extrait la première ligne de docstring pour l’afficher dans fab --list. Exemple :

@task
def deploy(c):
"""Déploie la dernière version de l'application"""
...

Résultat :

Terminal window
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 :

@task
def restart_service(c, name):
"""Redémarre un service donné"""
c.sudo(f'systemctl restart {name}')

Appel :

Terminal window
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.