Franchement, mes débuts avec Ansible ont été déroutants. À l'époque, je gérais des dizaines de serveurs, et chaque déploiement ou mise à jour de configuration devait être effectué manuellement, un par un. C'était épuisant et source d'erreurs. Puis j'ai découvert Ansible, qui m'a littéralement libéré les mains.
Qu'est-ce qu'Ansible exactement ?
En termes simples, Ansible est un outil d'automatisation. Vous pouvez le considérer comme une "télécommande" capable de contrôler simultanément plusieurs serveurs. Par exemple, pour installer Nginx sur 100 serveurs, la méthode traditionnelle consisterait à se connecter à chacun d'eux individuellement. Avec Ansible, il suffit d'écrire un script et le tour est joué.
Je me souviens de ma première utilisation d'Ansible pour un déploiement en masse : voir les commandes s'exécuter en cascade dans le terminal était grisant. Un travail qui me prenait une journée entière a été réalisé en 10 minutes.
Relation entre nœud de contrôle et nœuds gérés
Ce concept est très simple : le nœud de contrôle est la machine sur laquelle Ansible est installé, tandis que les nœuds gérés sont les serveurs que vous administrez.
Personnellement, j'installe Ansible sur un serveur bastion pour faciliter la gestion. Le nœud de contrôle doit pouvoir se connecter via SSH à tous les nœuds gérés, c'est le prérequis de base.
# Installation d'Ansible sur le nœud de contrôle
yum install ansible -y
# Ou via pip
pip install ansible
Les nœuds gérés n'ont rien à installer, ils doivent simplement être accessibles via SSH. C'est l'un des avantages d'Ansible : contrairement à d'autres outils, aucun agent n'est nécessaire sur les machines cibles.
Inventaire (Inventory) : le registre des serveurs
Le fichier d'inventaire est comme votre carnet d'adresses des serveurs, contenant les informations de toutes les machines à gérer.
Un inventaire minimal ressemble à ceci :
[webservers]
192.168.1.10
192.168.1.11
192.168.1.12
[databases]
192.168.1.20
192.168.1.21
Mais en production, je le rédige de manière plus détaillée :
[webservers]
web01 ansible_host=192.168.1.10 ansible_user=root ansible_ssh_private_key_file=/root/.ssh/id_rsa
web02 ansible_host=192.168.1.11 ansible_user=root ansible_ssh_private_key_file=/root/.ssh/id_rsa
[databases]
db01 ansible_host=192.168.1.20 ansible_user=mysql ansible_become=yes
db02 ansible_host=192.168.1.21 ansible_user=mysql ansible_become=yes
[production:children]
webservers
databases
Cette approche permet de spécifier des paramètres de connexion différents pour chaque machine, comme l'utilisation de clés SSH, de mots de passe ou l'escalade de privilèges sudo.
Modules : la boîte à outils d'Ansible
Ansible propose des milliers de modules, chacun dédié à une fonction spécifique. Inutile de tous les connaître dès le départ ; maîtrisez d'abord les plus courants.
Modules de gestion de fichiers
Le module copy sert à copier des fichiers :
- name: Copier un fichier de configuration
copy:
src: /chemin/local/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
Le module file gère les fichiers et répertoires :
- name: Créer un répertoire
file:
path: /opt/monapp
state: directory
owner: www
group: www
mode: '0755'
Gestion des paquets
Le module yum pour CentOS/RHEL :
- name: Installer Nginx
yum:
name: nginx
state: present
Le module apt pour Ubuntu/Debian :
- name: Installer Nginx
apt:
name: nginx
state: present
update_cache: yes
Gestion des services
Le module systemd gère les services système :
- name: Démarrer le service Nginx
systemd:
name: nginx
state: started
enabled: yes
En pratique, ces quelques modules couvrent 80 % des tâches quotidiennes d'administration.
Tâches et Playbooks : le scénario d'automatisation
Une tâche est une opération spécifique (installer un logiciel, copier un fichier, etc.). Un playbook organise plusieurs tâches en un flux d'automatisation complet.
Voici un exemple concret pour déployer une application web :
---
- name: Déployer une application web
hosts: webservers
become: yes
vars:
app_name: monapp
app_version: 1.2.3
tasks:
- name: Installer les paquets requis
yum:
name:
- nginx
- python3
- git
state: present
- name: Créer le répertoire de l'application
file:
path: "/opt/{{ app_name }}"
state: directory
owner: nginx
group: nginx
mode: '0755'
- name: Télécharger le code source
git:
repo: https://github.com/entreprise/monapp.git
dest: "/opt/{{ app_name }}"
version: "{{ app_version }}"
notify: redemarrer nginx
- name: Copier la configuration Nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/conf.d/monapp.conf
notify: redemarrer nginx
- name: Démarrer le service Nginx
systemd:
name: nginx
state: started
enabled: yes
handlers:
- name: redemarrer nginx
systemd:
name: nginx
state: restarted
Ce playbook effectue plusieurs actions : installation des paquets, création des répertoires, téléchargement du code, configuration de Nginx et démarrage du service. Si un fichier de configuration change, Nginx est automatiquement redémarré.
Variables et templates : une configuration flexible
En environnement réel, les configurations diffèrent selon l'environnement (production, staging, etc.). C'est là que les variables et templates entrent en jeu.
Je crée généralement des fichiers de variables par environnement :
group_vars/production.yml :
db_host: prod-db.entreprise.com
db_port: 3306
app_env: production
log_level: warn
group_vars/staging.yml :
db_host: staging-db.entreprise.com
db_port: 3306
app_env: staging
log_level: debug
Et j'utilise ces variables dans un template :
templates/app.conf.j2 :
[database]
host = {{ db_host }}
port = {{ db_port }}
[app]
environment = {{ app_env }}
log_level = {{ log_level }}
Ainsi, le même playbook peut s'adapter à différents environnements.
Rôles : l'art de la modularité
Lorsque le projet devient complexe, tout écrire dans un seul playbook devient inapproprié. Les rôles permettent une gestion modulaire.
Structure d'un rôle :
roles/
nginx/
tasks/main.yml
handlers/main.yml
templates/
files/
vars/main.yml
defaults/main.yml
Exemple d'un rôle nginx :
roles/nginx/tasks/main.yml :
---
- name: Installer Nginx
yum:
name: nginx
state: present
- name: Copier la configuration principale
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: redemarrer nginx
- name: Copier les configurations des sites
template:
src: "{{ item }}"
dest: "/etc/nginx/conf.d/{{ item | basename | regex_replace('.j2$', '') }}"
with_fileglob:
- "../templates/sites/*.j2"
notify: redemarrer nginx
- name: Démarrer le service Nginx
systemd:
name: nginx
state: started
enabled: yes
roles/nginx/handlers/main.yml :
---
- name: redemarrer nginx
systemd:
name: nginx
state: restarted
Utilisation du rôle dans un playbook :
---
- name: Configurer les serveurs web
hosts: webservers
roles:
- nginx
- php
- mysql
Handlers : une atuomatisation réactive
Les handlers sont une fonctionnalité puissante d'Ansible. Ils ne s'exécutent que lorsqu'ils sont notifiés, et chaque handler ne s'exécute qu'une seule fois par exécution de playbook, même s'il est notifié plusieurs fois.
Par exemple, après avoir modifié plusieurs fichiers de configuration Nginx, vous ne voulez pas redémarrer le service à chaque modification, mais seulement une fois toutes les modifications effectuées. Les handlers répondent à ce besoin.
tasks:
- name: Modifier la configuration principale de Nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: redemarrer nginx
- name: Modifier la configuration d'un site
template:
src: site.conf.j2
dest: /etc/nginx/conf.d/site.conf
notify: redemarrer nginx
- name: Modifier la configuration SSL
template:
src: ssl.conf.j2
dest: /etc/nginx/conf.d/ssl.conf
notify: redemarrer nginx
handlers:
- name: redemarrer nginx
systemd:
name: nginx
state: restarted
Même si les trois tâches notifient le handler, Nginx ne sera redémarré qu'une seule fois.
Astuces pratiques et retours d'expérience
Gestion des clés SSH
Au début, j'ai eu des problèmes de connexion SSH. La meilleure approche est d'utiliser l'authentification par clé et de bien distribuer les clés.
# Génération de la paire de clés
ssh-keygen -t rsa -b 4096 -f ~/.ssh/ansible_rsa
# Distribution de la clé publique vers les nœuds gérés
ssh-copy-id -i ~/.ssh/ansible_rsa.pub user@target_host
Spécification de la clé privée dans l'inventaire :
[servers]
server1 ansible_host=192.168.1.10 ansible_ssh_private_key_file=~/.ssh/ansible_rsa
Importance de l'idempotence
Une caractéristique clé d'Ansible est l'idempotence : l'exécution répétée d'une même opération doit produire le même résultat.
Exemple non idempotent :
- name: Ajouter un utilisateur à sudoers
shell: echo "myuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
Ce code ajoute une ligne supplémentaire à chaque exécution. Il faut plutôt utiliser :
- name: Ajouter un utilisateur à sudoers
lineinfile:
path: /etc/sudoers
line: "myuser ALL=(ALL) NOPASSWD:ALL"
state: present
Gestion des erreurs et débogage
Voici quelques astuces de débogage :
- Augmenter la verbosité avec l'option
-v:
ansible-playbook -vvv playbook.yml
- Utiliser le module
debugpour afficher les variables :
- name: Afficher la variable
debug:
var: ansible_facts['os_family']
- Ignorer certaines erreurs avec
ignore_errors:
- name: Tâche pouvant échouer
command: some_commande_qui_peut_echouer
ignore_errors: yes
- Définir des conditions d'échec personnalisées avec
failed_when:
- name: Vérifier l'état du service
command: systemctl is-active nginx
register: nginx_status
failed_when: nginx_status.rc != 0 and nginx_status.rc != 3
Optimisation des performances
Quand le nombre de machines gérées augmente, les performances deviennent cruciales. Voici quelques optimisations :
- Ajuster le nombre de processus en parallèle :
# ansible.cfg
[defaults]
forks = 50
- Activer le SSH pipelining :
[ssh_connection]
pipelining = True
- Utiliser le plugin de stratégie
free:
- name: Playbook d'exécution rapide
hosts: all
strategy: free
tasks:
- name: Tâche simple
ping:
Gestion des fichiers de configuration
Le fichier de configuration d'Ansible, ansible.cfg, peut être placé à plusieurs endroits, avec la priorité suivante (de la plus haute à la plus basse) :
- Fichier spécifié par la variable d'environnement
ANSIBLE_CONFIG ansible.cfgdans le répertoire courant.ansible.cfgdans le répertoire personnel/etc/ansible/ansible.cfg
J'utilise généralement un fichier ansible.cfg dans le répertoire du projet :
[defaults]
inventory = inventory/hosts
host_key_checking = False
timeout = 30
forks = 20
remote_user = root
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
pipelining = True
Cas d'usage concrets
Ansible m'a aidé à résoudre de nombreux problèmes en entreprise. Voici quelques scénarios typiques :
Initialisation massive de serveurs
À la mise en service de nouvelles machines, de nombreuses tâches initiales sont nécessaires : création d'utilisateurs, configuration SSH, installation de logiciels de base, réglage du fuseau horaire, etc. Un playbook Ansible permet de tout initialiser en quelques minutes.
Déploiement d'applications
Auparavant, chaque déploiement nécessitait de se connecter à chaque serveur, d'arrêter le service, de sauvegarder, de mettre à jour le code et de redémarrer. Désormais, un seul playbook gère tout, y compris les déploiements sans interruption de service.
Gestion de configuration
Les modifications de configuration système sont monnaie courante. Ansible garantit la cohérence des configurations sur toutes les machines et permet de suivre l'historique des changements.
Maintenance régulière
Pour les tâches périodiques comme le nettoyage des logs, le renouvellement des certificats ou l'application de correctifs de sécurité, un playbook associé à cron simplifie grandement la vie.
Récemment, j'ai dû renouveler les certificats SSL de tous les serveurs de l'entreprise. Manuellement, cela aurait pris plusieurs jours pour des centaines de machines. Avec un playbook Ansible, tout a été fait en une demi-heure, sans aucune erreur.
Bien sûr, Ansible n'est pas une solution universelle. Pour des scénarios d'orchestration complexes, d'autres outils peuvent être nécessaires. Mais pour la majorité des tâches d'administration, Ansible est plus que suffisant.
La meilleure façon d'apprendre Ansible est de pratiquer. Commencez par des tâches simples (exécution de commandes en lot, copie de fichiers) puis explorez progressivement des fonctionnalités plus avancées. Rappelez-vous : tout outil doit résoudre un problème concret ; ne l'utilisez pas pour le plaisir.
J'espère que cet article vous aidera à mieux comprendre et utiliser Ansible. L'automatisation opérationnelle est un long chemin, mais avec Ansible comme allié, votre travail deviendra bien plus léger.