Chapitre 2 - Déployer une Infrastructure Docker avec Ansible - Pratique 02
Dans ce chapitre, nous allons explorer l'utilisation d'Ansible pour automatiser des tâches sur une infrastructure Docker de manière efficace et structurée. Cette infrastructure sera composée de plusieurs conteneurs utilisant différentes distributions Linux (Ubuntu, Debian, AlmaLinux) qui nous permettront de :
- Configurer et gérer plusieurs conteneurs Docker de manière centralisée
- Automatiser des tâches complexes sur différentes distributions Linux avec des conditions adaptées (Ubuntu, Debian, AlmaLinux)
- Organiser et structurer nos conteneurs de manière logique et maintenable
- Mettre en place des bonnes pratiques d'automatisation avec Ansible
- Créer des playbooks réutilisables et modulaires
📋 Table des Matières
- Introduction
- Étape 1 : Installer Docker et Docker Compose
- Étape 2 : Créer et Démarrer les Conteneurs
- Étape 3 : Configurer l'Accès SSH pour Ansible
- Étape 4 : Créer l'Inventaire Ansible avec Groupes
- Étape 5 : Lister les Hôtes par Groupe
- Étape 6 : Tester la Connectivité et Exécuter des Commandes
- Étape 7 : Exécuter des Actions Spécifiques sur des Groupes
- Étape 8 : Écrire et Exécuter un Playbook Ansible
- Étape 9 : Vérifier le Déploiement
- Conclusion
📝 Introduction
Nous allons déployer une infrastructure Docker avec plusieurs conteneurs de différentes distributions Linux, configurer l'accès SSH pour Ansible, organiser les conteneurs en groupes dans un inventaire Ansible, et automatiser des tâches sur ces conteneurs en tenant compte des spécificités de chaque distribution.
🌍 Étape 1 : Installer Docker et Docker Compose
Sur votre machine de contrôle (Ubuntu Desktop 22.04 ou Ubuntu Server 22.04), exécutez les commandes suivantes pour installer Docker et Docker Compose :
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release git
git clone https://github.com/SkillFlowCoach/install-docker-ubuntu2204.git
cd install-docker-ubuntu2204/
chmod +x install-docker.sh
sudo ./install-docker.sh
apt install docker-compose
docker-compose version
🗄️ Étape 2 : Créer et Démarrer les Conteneurs
2.1. Créer un Répertoire de Travail
Créez un nouveau répertoire pour votre projet et accédez-y :
mkdir ansible_project
cd ansible_project
2.2. Créer le Fichier docker-compose.yml
Architecture de l'infrastructure à créer avec docker-compose :
+----------------------+
| Ansible Controller |
| Ubuntu 22.04 |
| IP: 172.20.0.X |
+----------------------+
|
|
--------------------------------------------------------------------------
| | | | | | |
+---------+ +---------+ +---------+ +---------+ +---------+ +---------+ +---------+
| Node1 | | Node2 | | Node3 | | Node4 | | Node5 | | Node6 | | NodeX |
| Ubuntu | | Debian | | AlmaLin | | AlmaLin | | Ubuntu | | Ubuntu | | (opt) |
| 172.20.0.2| 172.20.0.3| 172.20.0.4| 172.20.0.5| 172.20.0.6| 172.20.0.7| ... |
+---------+ +---------+ +---------+ +---------+ +---------+ +---------+ +---------+
Légende :
- Ansible Controller : Machine principale de contrôle sous Ubuntu 22.04.
- Nodes (Node1 à Node6) :
- Node1 : Ubuntu
- Node2 : Debian
- Node3, Node4 : AlmaLinux
- Node5, Node6 : Ubuntu
- Toutes les machines sont sur le réseau
ansible_network
avec des adresses IP statiques dans le sous-réseau172.20.0.0/24
.
Créez le fichier docker-compose.yml
:
nano docker-compose.yml
2.3. Contenu du Fichier docker-compose.yml
Copiez et collez le contenu suivant dans le fichier, en veillant à ce que la configuration pour les conteneurs AlmaLinux soit correcte :
version: '3'
services:
node1:
image: ubuntu:latest
container_name: node1
networks:
ansible_network:
ipv4_address: 172.20.0.2
command: /bin/bash -c "apt update && apt install -y openssh-server python3 && service ssh start && tail -f /dev/null"
expose:
- "22"
- "80"
node2:
image: debian:latest
container_name: node2
networks:
ansible_network:
ipv4_address: 172.20.0.3
command: /bin/bash -c "apt update && apt install -y openssh-server python3 && service ssh start && tail -f /dev/null"
expose:
- "22"
- "80"
node3:
image: almalinux:latest
container_name: node3
networks:
ansible_network:
ipv4_address: 172.20.0.4
command: /bin/bash -c "yum update -y && yum install -y openssh-server passwd python3 && echo 'root:root' | chpasswd && ssh-keygen -A && /usr/sbin/sshd -D"
expose:
- "22"
- "80"
node4:
image: almalinux:latest
container_name: node4
networks:
ansible_network:
ipv4_address: 172.20.0.5
command: /bin/bash -c "yum update -y && yum install -y openssh-server passwd python3 && echo 'root:root' | chpasswd && ssh-keygen -A && /usr/sbin/sshd -D"
expose:
- "22"
- "80"
node5:
image: ubuntu:latest
container_name: node5
networks:
ansible_network:
ipv4_address: 172.20.0.6
command: /bin/bash -c "apt update && apt install -y openssh-server python3 && service ssh start && tail -f /dev/null"
expose:
- "22"
- "80"
node6:
image: ubuntu:latest
container_name: node6
networks:
ansible_network:
ipv4_address: 172.20.0.7
command: /bin/bash -c "apt update && apt install -y openssh-server python3 && service ssh start && tail -f /dev/null"
expose:
- "22"
- "80"
networks:
ansible_network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
Remarques Importantes :
- Python3 est installé sur tous les conteneurs pour assurer la compatibilité avec Ansible.
- Les conteneurs AlmaLinux exécutent
sshd -D
pour garder le conteneur actif. - Les ports
22
et80
sont exposés pour SSH et HTTP.
Voici un tableau récapitulatif des informations pour chaque nœud avec le détail de la distribution utilisée, l'adresse IP, et les actions effectuées :
Nœud | Image (OS) | Adresse IP | Commandes exécutées | Ports exposés | But principal |
---|---|---|---|---|---|
node1 | Ubuntu (latest) | 172.20.0.2 | apt update , installation openssh-server , python3 , démarrage SSH | 22, 80 | Nœud de test pour Ansible (Ubuntu) |
node2 | Debian (latest) | 172.20.0.3 | apt update , installation openssh-server , python3 , démarrage SSH | 22, 80 | Nœud de test pour Ansible (Debian) |
node3 | AlmaLinux (latest) | 172.20.0.4 | yum update , installation openssh-server , passwd , python3 , génération clé SSH | 22, 80 | Nœud de test pour Ansible (AlmaLinux) |
node4 | AlmaLinux (latest) | 172.20.0.5 | yum update , installation openssh-server , passwd , python3 , génération clé SSH | 22, 80 | Nœud de test pour Ansible (AlmaLinux) |
node5 | Ubuntu (latest) | 172.20.0.6 | apt update , installation openssh-server , python3 , démarrage SSH | 22, 80 | Nœud de test pour Ansible (Ubuntu) |
node6 | Ubuntu (latest) | 172.20.0.7 | apt update , installation openssh-server , python3 , démarrage SSH | 22, 80 | Nœud de test pour Ansible (Ubuntu) |
Explication des colonnes :
- Nœud : Nom du conteneur.
- Image (OS) : Système d'exploitation utilisé pour le conteneur.
- Adresse IP : Adresse IP fixe dans le réseau
ansible_network
. - Commandes exécutées : Commandes exécutées pour préparer l'environnement (mise à jour du système, installation de packages nécessaires).
- Ports exposés : Ports ouverts pour accéder au conteneur (SSH et HTTP).
- But principal : Utilisation prévue du conteneur (test des playbooks Ansible sur différentes distributions).
2.4. Démarrer les Conteneurs
Exécutez la commande suivante pour démarrer tous les conteneurs en arrière-plan :
docker-compose up -d
Vérifiez que les conteneurs sont en cours d'exécution :
docker ps
N'exécutez pas la commande ci-dessous maintenant. Elle doit être exécutée à la fin car elle permet d'arrêter et de supprimer tous les conteneurs + réseau , volumes etc...:
docker-compose down
🔑 Étape 3 : Configurer l'Accès SSH pour Ansible
3.1. Générer une Clé SSH (si elle n'existe pas)
Générez une clé SSH sans phrase de passe :
ssh-keygen -t rsa -b 2048 -N "" -f ~/.ssh/id_rsa
3.2. Copier la Clé Publique vers Chaque Conteneur
Pour tous les conteneurs (node1
à node6
) :
for i in {1..6}; do
docker exec -it node$i mkdir -p /root/.ssh
docker cp ~/.ssh/id_rsa.pub node$i:/root/.ssh/authorized_keys
docker exec -it node$i chmod 600 /root/.ssh/authorized_keys
done
Scénario de connexion SSH avec Ansible:
- Le master (machine Ansible) envoie une requête de connexion SSH aux nœuds (conteneurs).
- Chaque nœud (esclave) envoie un challenge chiffré avec la clé publique.
- Le master utilise sa clé privée pour déchiffrer le challenge et prouver son identité.
- Si la réponse est correcte, la connexion SSH est établie, permettant à Ansible d'exécuter des commandes sur le nœud sans mot de passe.
Résumé :
Le master prouve son identité aux nœuds pour établir une connexion sécurisée et automatiser la gestion via Ansible.
3.3. Vérifier la Connexion SSH pour Chaque Conteneur
Supprimez les anciennes entrées d'hôtes connus pour éviter les conflits :
rm -f ~/.ssh/known_hosts
ssh-keygen -R 172.20.0.2
ssh-keygen -R 172.20.0.3
ssh-keygen -R 172.20.0.4
ssh-keygen -R 172.20.0.5
ssh-keygen -R 172.20.0.6
ssh-keygen -R 172.20.0.7
Lorsqu'une clé publique de serveur a été modifiée, le client SSH détecte une incohérence avec l'empreinte stockée et bloque la connexion pour des raisons de sécurité ; il faut donc supprimer l'ancienne empreinte dans known_hosts pour établir une nouvelle connexion sans erreur.
Ensuite, vérifiez la connexion SSH :
for i in {1..6}; do
IP=172.20.0.$((i+1))
ssh -o StrictHostKeyChecking=no root@$IP exit
done
- Cette boucle SSH désactive la vérification stricte des clés d'hôtes (
StrictHostKeyChecking=no
) pour éviter toute demande de confirmation lors de la connexion aux adresses IP des conteneurs. - Pour chaque IP de
172.20.0.2
à172.20.0.7
, une connexion SSH est testée (avecexit
pour quitter immédiatement), permettant de préenregistrer automatiquement l'empreinte dans le fichierknown_hosts
.
📜 Étape 4 : Créer l'Inventaire Ansible avec Groupes
Créez un fichier inventory.ini
dans votre répertoire de travail :
nano inventory.ini
Ajoutez le contenu suivant :
[node_containers]
node1 ansible_host=172.20.0.2 ansible_user=root
node2 ansible_host=172.20.0.3 ansible_user=root
node3 ansible_host=172.20.0.4 ansible_user=root
node4 ansible_host=172.20.0.5 ansible_user=root
node5 ansible_host=172.20.0.6 ansible_user=root
node6 ansible_host=172.20.0.7 ansible_user=root
[web]
node1
node5
[database]
node2
node3
[mail]
node4
node6
Un inventaire Ansible définit la liste des machines cibles avec leurs adresses IP, noms d'hôte et paramètres de connexion. Il permet de regrouper les machines par rôles ou services afin d'exécuter des tâches spécifiques sur un ensemble d'hôtes de manière organisée.
Ce fichier est un exemple d' inventaire Ansible qui liste les hôtes et les regroupe en catégories :
-
[node_containers] :
- Groupe principal contenant tous les conteneurs avec leurs adresses IP (
ansible_host
) et l'utilisateur SSH utilisé (ansible_user=root
).
- Groupe principal contenant tous les conteneurs avec leurs adresses IP (
-
[web] :
- Groupe des nœuds affectés aux services web (
node1
etnode5
).
- Groupe des nœuds affectés aux services web (
-
[database] :
- Groupe des nœuds pour les services de base de données (
node2
etnode3
).
- Groupe des nœuds pour les services de base de données (
-
[mail] :
- Groupe des nœuds pour le service de messagerie (
node4
etnode6
).
- Groupe des nœuds pour le service de messagerie (
Résumé :
Cet inventaire organise les conteneurs par rôles spécifiques pour exécuter des playbooks Ansible ciblés sur certains groupes (web, base de données, messagerie).
📝 Étape 5 : Lister les Hôtes par Groupe
5.1. Lister les Hôtes du Groupe web
ansible web -i inventory.ini --list-hosts
5.2. Lister les Hôtes du Groupe mail
ansible mail -i inventory.ini --list-hosts
5.3. Lister Tous les Hôtes Définis
ansible all -i inventory.ini --list-hosts
5.4. Lister les Détails d'un Hôte Spécifique (node1
)
ansible node1 -i inventory.ini --list-hosts
📝 Étape 6 : Tester la Connectivité et Exécuter des Commandes
6.1. Tester la Connectivité avec ping
pour Tous les Conteneurs
ansible all -m ping -i inventory.ini
6.2. Afficher la Date Actuelle sur node1
ansible node1 -m command -a "date" -i inventory.ini
C'est un exemple de commande ad hoc Ansible qui exécute le module command
sur l'hôte node1
pour afficher la date actuelle via la commande date
. L'option -i inventory.ini
précise le fichier d'inventaire contenant les informations sur les hôtes cibles.
6.3. Afficher la Date Actuelle sur Tous les Conteneurs
ansible all -m command -a "date" -i inventory.ini
📝 Étape 7 : Exécuter des Actions Spécifiques sur des Groupes
7.1. Redémarrer le Service Apache sur le Groupe web
Nous devons tenir compte des différences entre les distributions :
- Sur Ubuntu/Debian, le service Apache s'appelle
apache2
. - Sur AlmaLinux, le service s'appelle
httpd
.
Cependant, dans le groupe web
, nous avons node1
et node5
, qui sont tous deux des conteneurs Ubuntu. Nous utiliserons donc apache2
.
Installer Apache sur le Groupe web
:
ansible web -m apt -a "name=apache2 state=present" -i inventory.ini
Démarrer et Activer le Service Apache :
ansible web -m service -a "name=apache2 state=started enabled=yes" -i inventory.ini
Redémarrer le Service Apache sur le Groupe web
ansible web -m service -a "name=apache2 state=restarted" -i inventory.ini
Note : Si vous aviez des conteneurs AlmaLinux dans le groupe web
, vous devriez utiliser des conditions ou séparer les tâches.
7.2. Vérifier l'Uptime sur le Groupe mail
Le conteneur node4
(AlmaLinux) semble ne pas avoir la commande uptime
installée par défaut. Nous allons installer procps
qui fournit uptime
.
7.2.1. Installer procps
sur les Conteneurs AlmaLinux
ansible mail -m yum -a "name=procps-ng state=present" -i inventory.ini
7.2.2. Vérifier l'Uptime
ansible mail -m command -a "uptime" -i inventory.ini
ansible node4 -m command -a "uptime" -i inventory.ini
ansible node6 -m command -a "uptime" -i inventory.ini
7.3. Vérifier l'Utilisation du Disque sur le Groupe database
La commande df
devrait être disponible sur toutes les distributions.
ansible database -m command -a "df -h" -i inventory.ini
- La commande df -h permet de vérifier l’état de l’espace disque sur les serveurs du groupe database afin de diagnostiquer les éventuels problèmes liés à l'espace disponible.
7.4. Installer vim
sur le Groupe database
Nous avons des conteneurs Ubuntu/Debian et AlmaLinux dans le groupe database
. Nous devons utiliser le gestionnaire de paquets approprié pour chaque distribution.
7.4.1. Créer un Playbook pour Gérer les Différentes Distributions
Créez un fichier install_vim.yml
:
nano install_vim.yml
Contenu :
- name: Install vim on database servers
hosts: database
become: yes
tasks:
- name: Install vim on Debian-based systems
apt:
name: vim
state: present
when: ansible_facts['os_family'] == 'Debian'
- name: Install vim on RedHat-based systems
yum:
name: vim-enhanced
state: present
when: ansible_facts['os_family'] == 'RedHat'
Explication de become: yes
:
become: yes
est une directive Ansible utilisée pour élever les privilèges lors de l'exécution des tâches.- Cela signifie que les commandes seront exécutées avec les droits de superutilisateur (souvent équivalent à
sudo
sur les systèmes Linux).
Détail du fonctionnement :
- Lorsqu'une tâche nécessite des permissions administratives (comme l'installation de logiciels), Ansible utilise
become: yes
pour basculer vers l'utilisateur privilégié (root
ou un autre si spécifié). - Par défaut,
become: yes
utilisesudo
, mais cela peut être personnalisé (become_method
peut être défini sursudo
,su
,pbrun
, etc.).
Exemple du playbook :
- Hôtes ciblés : Le groupe
database
, qui inclut les machinesnode2
etnode3
selon ton inventaire. - Tâches exécutées :
- Si le système est basé sur Debian (par exemple Ubuntu, Debian), Ansible utilise le module
apt
pour installervim
. - Si le système est basé sur RedHat (par exemple RedHat, AlmaLinux, CentOS), Ansible utilise le module
yum
pour installervim-enhanced
.
- Si le système est basé sur Debian (par exemple Ubuntu, Debian), Ansible utilise le module
Sans become: yes
:
- Sans cette directive, Ansible exécuterait les commandes avec des permissions limitées (l'utilisateur SSH, souvent
root
, est requis par défaut). - Si l'utilisateur est non privilégié, certaines tâches (comme l'installation de logiciels) échoueraient sans
become: yes
.
Pour résumer la description du playbook du point 7.4.1, become: yes
permet à Ansible d'exécuter les tâches avec des privilèges administratifs (similaire à sudo
). Dans ce playbook, il est nécessaire pour installer vim
sur les machines cibles (database
) sans erreurs liées aux permissions.
7.4.2. Exécuter le Playbook
ansible-playbook -i inventory.ini install_vim.yml
📝 Étape 8 : Écrire et Exécuter un autre Playbook Ansible
8.1. Créer un Playbook pour Configurer Apache sur Tous les Serveurs Web
Créez un fichier configure_apache.yml
:
nano configure_apache.yml
Contenu :
- name: Configure Apache on Web Servers
hosts: web
become: yes
tasks:
- name: Install Apache on Debian-based systems
apt:
name: apache2
state: present
when: ansible_facts['os_family'] == 'Debian'
- name: Start Apache on Debian-based systems
service:
name: apache2
state: started
enabled: true
when: ansible_facts['os_family'] == 'Debian'
- name: Install Apache on RedHat-based systems
yum:
name: httpd
state: present
when: ansible_facts['os_family'] == 'RedHat'
- name: Start Apache on RedHat-based systems
service:
name: httpd
state: started
enabled: true
when: ansible_facts['os_family'] == 'RedHat'
- name: Create index.html
copy:
content: "<h1>Bienvenue sur votre serveur web!</h1>"
dest: /var/www/html/index.html
Ce playbook Ansible installe et démarre le service Apache sur les serveurs web en fonction de leur système d'exploitation (apache2
pour Debian/Ubuntu, httpd
pour RedHat/CentOS). Il s'assure que le service Apache est activé au démarrage. Enfin, il crée un fichier index.html
avec un message de bienvenue dans le dossier racine du serveur web.
8.2. Exécuter le Playbook
ansible-playbook -i inventory.ini configure_apache.yml
🔎 Étape 9 : Vérifier le Déploiement
9.1. Obtenir les Adresses IP des Conteneurs
for i in {1..6}; do
IP=172.20.0.$((i+1))
echo "node$i IP: $IP"
done
9.2. Vérifier l'Accès aux Serveurs Web
Utilisez curl
pour tester les serveurs web :
for i in 1 5; do
IP=172.20.0.$((i+1))
echo "Testing node$i at $IP:"
curl http://$IP
echo -e "\n------------------------\n"
done
Vous devriez voir le message :
<h1>Bienvenue sur votre serveur web!</h1>
🎯 Conclusion
Nous avons réussi à :
- Installer Docker et Docker Compose.
- Créer et démarrer plusieurs conteneurs Docker de différentes distributions.
- Configurer l'accès SSH pour Ansible.
- Créer un inventaire Ansible avec des groupes.
- Exécuter des commandes spécifiques en tenant compte des différences entre les distributions.
- Écrire et exécuter des playbooks Ansible pour automatiser des tâches.
🛠️ Conseils Supplémentaires
- Modules Ansible Appropriés : Utilisez le module
apt
pour Debian/Ubuntu etyum
pour RedHat/AlmaLinux. - Conditions dans les Playbooks : Utilisez les conditions
when
pour exécuter des tâches spécifiques à une distribution. - Installer les Paquets Nécessaires : Assurez-vous que les commandes que vous voulez utiliser sont disponibles (par exemple, installer
procps
pour la commandeuptime
sur AlmaLinux). - Gestion des Services : Le nom du service Apache diffère selon la distribution (
apache2
vshttpd
).