Aller au contenu principal

Exercices et projets


Objectifs

  • Consolider vos connaissances Ansible
  • Mettre en pratique tous les concepts
  • Développer des compétences opérationnelles

Exercice 1 : Installation et premiers pas

Objectif

Installer Ansible et valider la configuration.

Tâches

  1. Installez Ansible sur votre machine
  2. Créez la structure de projet
  3. Configurez l'inventaire avec localhost
  4. Exécutez un ping test

Structure à créer

ansible-labs/
├── ansible.cfg
├── inventory/
│ └── hosts.ini
└── playbooks/

Fichiers

# inventory/hosts.ini
[local]
localhost ansible_connection=local
# ansible.cfg
[defaults]
inventory = ./inventory/hosts.ini
host_key_checking = False

Validation

ansible all -m ping
# Attendu: localhost | SUCCESS

Exercice 2 : Commandes ad-hoc

Objectif

Maîtriser les opérations de base avec les commandes ad-hoc.

Tâches

  1. Affichez les informations système
  2. Créez un répertoire /tmp/ansible-test
  3. Créez un fichier avec du contenu
  4. Vérifiez l'espace disque

Commandes

# 1. Infos système
ansible localhost -m setup -a "filter=ansible_distribution*"

# 2. Créer un répertoire
ansible localhost -m file -a "path=/tmp/ansible-test state=directory"

# 3. Créer un fichier
ansible localhost -m copy -a "content='Hello Ansible' dest=/tmp/ansible-test/hello.txt"

# 4. Espace disque
ansible localhost -a "df -h"

Exercice 3 : Premier playbook

Objectif

Écrire un playbook simple.

Tâches

Créez un playbook qui :

  1. Affiche un message de bienvenue
  2. Crée un utilisateur "testuser"
  3. Crée un répertoire pour cet utilisateur

Solution

# playbooks/first-playbook.yml
---
- name: Mon premier playbook
hosts: localhost
become: yes

vars:
username: testuser
user_home: /home/testuser

tasks:
- name: Afficher un message
debug:
msg: "Bienvenue dans Ansible !"

- name: Créer l'utilisateur
user:
name: "{{ username }}"
state: present
shell: /bin/bash
create_home: yes

- name: Créer le répertoire projets
file:
path: "{{ user_home }}/projets"
state: directory
owner: "{{ username }}"
mode: '0755'

Exercice 4 : Inventaire avancé

Objectif

Créer un inventaire multi-environnements.

Structure

inventory/
├── production/
│ ├── hosts.ini
│ └── group_vars/
│ ├── all.yml
│ └── webservers.yml
├── staging/
│ ├── hosts.ini
│ └── group_vars/
│ └── all.yml
└── development/
└── hosts.ini

Fichiers à créer

# inventory/production/hosts.ini
[webservers]
web-01 ansible_host=192.168.1.10
web-02 ansible_host=192.168.1.11

[databases]
db-01 ansible_host=192.168.1.20

[production:children]
webservers
databases
# inventory/production/group_vars/all.yml
---
environment: production
debug_enabled: false
log_level: warn
# inventory/production/group_vars/webservers.yml
---
http_port: 80
nginx_worker_processes: 4

Exercice 5 : Playbook avec conditions et boucles

Objectif

Utiliser les structures de contrôle.

Playbook

# playbooks/packages.yml
---
- name: Gestion des packages
hosts: localhost
become: yes

vars:
common_packages:
- vim
- htop
- curl
- git

optional_packages:
- { name: docker.io, install: true }
- { name: nginx, install: false }

tasks:
- name: Mettre à jour le cache apt
apt:
update_cache: yes
cache_valid_time: 3600
when: ansible_os_family == "Debian"

- name: Installer les packages communs
apt:
name: "{{ common_packages }}"
state: present

- name: Installer les packages optionnels
apt:
name: "{{ item.name }}"
state: present
loop: "{{ optional_packages }}"
when: item.install | bool

- name: Afficher les packages installés
debug:
msg: "Package {{ item.name }} - Installé: {{ item.install }}"
loop: "{{ optional_packages }}"

Exercice 6 : Créer un rôle

Objectif

Créer un rôle pour installer et configurer nginx.

Structure

ansible-galaxy init --init-path roles/ nginx

Fichiers du rôle

# roles/nginx/defaults/main.yml
---
nginx_http_port: 80
nginx_server_name: localhost
nginx_document_root: /var/www/html
# roles/nginx/tasks/main.yml
---
- name: Install nginx
apt:
name: nginx
state: present
update_cache: yes

- name: Create document root
file:
path: "{{ nginx_document_root }}"
state: directory
mode: '0755'

- name: Configure nginx
template:
src: default.conf.j2
dest: /etc/nginx/sites-available/default
notify: Reload nginx

- name: Deploy index page
template:
src: index.html.j2
dest: "{{ nginx_document_root }}/index.html"

- name: Start and enable nginx
service:
name: nginx
state: started
enabled: yes
# roles/nginx/handlers/main.yml
---
- name: Reload nginx
service:
name: nginx
state: reloaded
{# roles/nginx/templates/default.conf.j2 #}
server {
listen {{ nginx_http_port }};
server_name {{ nginx_server_name }};
root {{ nginx_document_root }};

location / {
try_files $uri $uri/ =404;
}
}
{# roles/nginx/templates/index.html.j2 #}
<!DOCTYPE html>
<html>
<head>
<title>{{ nginx_server_name }}</title>
</head>
<body>
<h1>Bienvenue sur {{ nginx_server_name }}</h1>
<p>Déployé avec Ansible sur {{ ansible_hostname }}</p>
<p>Date: {{ ansible_date_time.iso8601 }}</p>
</body>
</html>

Utilisation

# playbooks/webservers.yml
---
- name: Configure web servers
hosts: webservers
become: yes

roles:
- role: nginx
nginx_server_name: example.com
nginx_http_port: 8080

Projet 1 : Stack LAMP

Objectif

Déployer une stack LAMP complète avec Ansible.

Architecture

Structure du projet

lamp-project/
├── ansible.cfg
├── inventory/
│ └── hosts.ini
├── group_vars/
│ └── all.yml
├── roles/
│ ├── common/
│ ├── apache/
│ ├── php/
│ └── mysql/
└── playbooks/
└── site.yml

Playbook principal

# playbooks/site.yml
---
- name: Deploy LAMP Stack
hosts: all
become: yes

roles:
- common
- mysql
- php
- apache

Variables

# group_vars/all.yml
---
# MySQL
mysql_root_password: "{{ vault_mysql_root_password }}"
mysql_databases:
- name: myapp
encoding: utf8mb4
mysql_users:
- name: appuser
password: "{{ vault_mysql_app_password }}"
priv: "myapp.*:ALL"

# PHP
php_version: "8.1"
php_extensions:
- php-mysql
- php-curl
- php-gd
- php-mbstring

# Apache
apache_vhosts:
- servername: myapp.local
documentroot: /var/www/myapp

Projet 2 : Déploiement d'application

Objectif

Automatiser le déploiement d'une application web.

Workflow

Playbook de déploiement

# playbooks/deploy.yml
---
- name: Deploy Application
hosts: webservers
become: yes

vars:
app_name: myapp
app_path: /var/www/{{ app_name }}
app_repo: https://github.com/myorg/myapp.git
app_branch: main

tasks:
- name: Pre-deployment tasks
block:
- name: Enable maintenance mode
copy:
content: "Maintenance in progress..."
dest: "{{ app_path }}/public/maintenance.html"

- name: Backup current version
archive:
path: "{{ app_path }}"
dest: "/backups/{{ app_name }}-{{ ansible_date_time.iso8601_basic_short }}.tar.gz"
ignore_errors: yes

- name: Deployment
block:
- name: Pull latest code
git:
repo: "{{ app_repo }}"
dest: "{{ app_path }}"
version: "{{ app_branch }}"
force: yes
register: git_result

- name: Install dependencies
command: composer install --no-dev --optimize-autoloader
args:
chdir: "{{ app_path }}"
when: git_result.changed

- name: Run database migrations
command: php artisan migrate --force
args:
chdir: "{{ app_path }}"

- name: Clear cache
command: php artisan cache:clear
args:
chdir: "{{ app_path }}"

- name: Set permissions
file:
path: "{{ app_path }}/storage"
owner: www-data
group: www-data
mode: '0775'
recurse: yes

- name: Post-deployment
block:
- name: Disable maintenance mode
file:
path: "{{ app_path }}/public/maintenance.html"
state: absent

- name: Reload PHP-FPM
service:
name: php8.1-fpm
state: reloaded

- name: Health check
uri:
url: "http://localhost/health"
status_code: 200
retries: 5
delay: 2

handlers:
- name: Restart apache
service:
name: apache2
state: restarted

Projet 3 : Infrastructure Docker

Objectif

Gérer une infrastructure Docker avec Ansible.

Playbook

# playbooks/docker-infra.yml
---
- name: Docker Infrastructure
hosts: docker_hosts
become: yes

collections:
- community.docker

vars:
docker_networks:
- name: frontend
driver: bridge
- name: backend
driver: bridge
internal: yes

docker_volumes:
- postgres_data
- redis_data

docker_containers:
- name: postgres
image: postgres:15
networks:
- backend
volumes:
- postgres_data:/var/lib/postgresql/data
env:
POSTGRES_PASSWORD: "{{ vault_postgres_password }}"

- name: redis
image: redis:7-alpine
networks:
- backend
volumes:
- redis_data:/data

- name: nginx
image: nginx:alpine
ports:
- "80:80"
networks:
- frontend
- backend

tasks:
- name: Create Docker networks
community.docker.docker_network:
name: "{{ item.name }}"
driver: "{{ item.driver | default('bridge') }}"
internal: "{{ item.internal | default(false) }}"
loop: "{{ docker_networks }}"

- name: Create Docker volumes
community.docker.docker_volume:
name: "{{ item }}"
loop: "{{ docker_volumes }}"

- name: Start containers
community.docker.docker_container:
name: "{{ item.name }}"
image: "{{ item.image }}"
networks: "{{ item.networks | default(omit) }}"
volumes: "{{ item.volumes | default(omit) }}"
ports: "{{ item.ports | default(omit) }}"
env: "{{ item.env | default(omit) }}"
state: started
restart_policy: unless-stopped
loop: "{{ docker_containers }}"

Quiz de validation

Questions

  1. Quelle commande vérifie la connectivité Ansible ?

    • a) ansible --ping
    • b) ansible all -m ping
    • c) ansible-ping
    • d) ping ansible
  2. Où définir les variables à priorité maximale ?

    • a) defaults/main.yml
    • b) group_vars/all.yml
    • c) extra-vars (-e)
    • d) vars/main.yml
  3. Quel module utiliser pour générer un fichier de configuration ?

    • a) copy
    • b) file
    • c) template
    • d) lineinfile
  4. Que signifie "idempotent" ?

    • a) Rapide à exécuter
    • b) Même résultat à chaque exécution
    • c) Compatible multi-OS
    • d) Exécution parallèle
  5. Comment organiser le code réutilisable ?

    • a) Playbooks imbriqués
    • b) Rôles
    • c) Scripts shell
    • d) Variables

Réponses

  1. b) ansible all -m ping
  2. c) extra-vars (-e) - Priorité la plus haute
  3. c) template - Pour les fichiers dynamiques Jinja2
  4. b) Même résultat à chaque exécution
  5. b) Rôles - Structure organisée et réutilisable

Ressources supplémentaires

Documentation officielle

Communauté

Rôles recommandés

  • geerlingguy.* - Rôles de qualité professionnelle
  • debops.* - Infrastructure Debian/Ubuntu
  • robertdebock.* - Rôles multi-plateforme

Conclusion

Félicitations ! Vous avez terminé le cours Ansible.

Vous maîtrisez maintenant :

  • L'installation et la configuration
  • L'inventaire et les commandes ad-hoc
  • Les playbooks et les variables
  • Les rôles et les templates
  • Ansible Galaxy et les collections

Continuez à pratiquer et explorez les projets réels !


← Ansible Galaxy | Table des matières