đ SYNTHĂSE â Exercices 3 & 4
â Exercice 3 : Idempotence â RĂ©sultats
Question
What happens if you run the configuration playbook a second time? Observe and explain.
Exécution pratique
Nous avons relancé le playbook configure_sample_app_playbook.yml deux fois de suite et capturé les résultats.
Résultats observés
1Úre exécution :
PLAY RECAP
ec2-3-142-134-207.us-east-2.compute.amazonaws.com : ok=6 changed=1 unreachable=0 failed=0 skipped=1
2Úme exécution :
PLAY RECAP
ec2-3-142-134-207.us-east-2.compute.amazonaws.com : ok=6 changed=1 unreachable=0 failed=0 skipped=1
đ Analyse dĂ©taillĂ©e
| TĂąche | 1Ăšre | 2Ăšme | Explication |
|---|---|---|---|
| Gathering Facts | ok | ok | Collecte des variables â idempotent |
| Install Node.js setup repository | ok | ok | Le fichier de repo existe â skipped ou ok |
| Install Node.js | ok | ok | Package dĂ©jĂ installĂ© â yum module est idempotent |
| Copy sample app | ok | ok | Le fichier app.js nâa pas changĂ© â no change |
| Check if app running | failed (ignored) | failed (ignored) | Processus inexistant â pgrep retourne rc=1 |
| Stop any existing app | skipped | skipped | Condition when: rc==0 â false â skip |
| Start sample app | changed | changed | â PROBLĂME â elle sâexĂ©cute TOUJOURS |
â ïž ProblĂšme dâidempotence identifiĂ©
La tĂąche âStart sample appâ est Ă©crite ainsi :
- name: Start sample app
shell: nohup node /home/ec2-user/app.js > /tmp/app.log 2>&1 &
args:
chdir: /home/ec2-user/
become_user: ec2-userProblĂšmes :
- â Pas de condition
when:â sâexĂ©cute TOUJOURS - â Pas de
changed_when: falseâ marque TOUJOURS commechanged - â Pas de vĂ©rification dâĂ©tat â relance lâapp mĂȘme si elle tourne dĂ©jĂ
- â RĂ©sultat : Chaque exĂ©cution crĂ©e un nouveau processus Node â accumulation de processus sur le port 8080 â conflit potentiel
â Solutions proposĂ©es
Solution 1 : Idempotence minimale (ajouter condition + flag)
- name: Start sample app
shell: nohup node /home/ec2-user/app.js > /tmp/app.log 2>&1 &
when: app_running.rc != 0 # â
Ne lance que si pas déjà actif
changed_when: false # â
Supprime le "changed"RĂ©sultat : 2Ăšme exĂ©cution â skipped (condition fausse)
Solution 2 : Meilleure pratique (systemd) â RECOMMANDĂE
- name: Create systemd service for app
copy:
dest: /etc/systemd/system/sample-app.service
content: |
[Unit]
Description=Sample Node.js App
After=network.target
[Service]
Type=simple
User=ec2-user
ExecStart=/usr/bin/node /home/ec2-user/app.js
Restart=on-failure
[Install]
WantedBy=multi-user.target
- name: Enable and start service
systemd:
name: sample-app
state: started
enabled: yesRĂ©sultat : ComplĂštement idempotent â systemd gĂšre lâidempotence automatiquement
đ Leçons apprises
- Idempotence = PropriĂ©tĂ© clĂ© dâAnsible â les playbooks DOIVENT pouvoir ĂȘtre relancĂ©s sans effets indĂ©sirables
- Signes de non-idempotence :
shell:oucommand:sans conditions- TĂąches qui modifient lâĂ©tat sans vĂ©rifier lâĂ©tat existant
- Redémarrage/relancement sans détection de state
- Bonnes pratiques :
- Utiliser les modules de haut niveau (
yum:,copy:,systemd:) â idempotents par dĂ©faut - Ajouter
when:pour les tĂąches conditionnelles - Ajouter
changed_when:pour contrĂŽler le signalement de changements - PrĂ©fĂ©rer les services systemd pour la gestion dâapps
- Utiliser les modules de haut niveau (
đ Fichiers fournis
- Documentation détaillée :
td2/EXERCISE_3_IDEMPOTENCE_ANALYSIS.md - 3 variantes du rĂŽle :
roles/sample-app/tasks/main.yml(actuelle â non-idempotente)roles/sample-app/tasks/main_idempotent.yml(idempotente minimale)roles/sample-app/tasks/main_systemd.yml(meilleure pratique)
đ Exercice 4 : DĂ©ploiement multi-instance
Question
Modify the playbook to deploy and configure multiple EC2 instances. How would you adjust the playbook and inventory?
Architecture proposée
Approche 1 : Modifier le playbook de création
Fichier : create_ec2_instances_multi.yml
vars:
instance_count: 2 # Nombre d'instances à créer
tasks:
- name: Create multiple EC2 instances
amazon.aws.ec2_instance:
name: "sample-app-ansible-{{ item }}" # Noms uniques
...
tags:
Ansible: ch2_instances
Index: "{{ item }}"
loop: "{{ range(0, instance_count | int) | list }}" # Crée N instancesRésultat : Crée instance_count instances en boucle
Approche 2 : Inventaire découvre automatiquement
Fichier : inventory.aws_ec2.yml (inchangé)
plugin: amazon.aws.aws_ec2
filters:
tag:Ansible: ch2_instances # Découvre TOUTES les instances avec ce tag
instance-state-name: runningRĂ©sultat : Quelle que soit le nombre dâinstances créées, lâinventaire les dĂ©couvre toutes automatiquement dans le groupe _ch2_instances
Approche 3 : Configuration appliquée à tous les hÎtes
Fichier : configure_sample_app_playbook.yml (inchangé)
- name: Configure the EC2 instance to run a sample app
hosts: _ch2_instances # Cible TOUS les hÎtes du groupe dynamiqueRésultat : Ansible se connecte à TOUS les hÎtes du groupe en parallÚle et exécute la configuration
đŻ Workflow complet
# 1. Créer 3 instances
ANSIBLE_PYTHON_INTERPRETER="$(which python3)" \
AWS_PROFILE=labs-devops_diallo \
ansible-playbook -v create_ec2_instances_multi.yml \
-e instance_count=3 \
-e instance_type=t3.micro
# Attendre ~1-2 minutes que les instances se lancent
# 2. Découvrir les instances via inventaire dynamique
ansible-inventory -i inventory.aws_ec2.yml --list
# Affiche tous les hĂŽtes du groupe _ch2_instances
# 3. Configurer TOUTES les instances en parallĂšle
ANSIBLE_PYTHON_INTERPRETER="$(which python3)" \
AWS_PROFILE=labs-devops_diallo \
ansible-playbook -i inventory.aws_ec2.yml configure_sample_app_playbook.yml
# Ansible lance 3 connexions SSH en parallĂšle â configuration rapide
# 4. Tester les 3 apps
aws ec2 describe-instances \
--filters "Name=tag:Ansible,Values=ch2_instances" \
--query 'Reservations[].Instances[].[PublicIpAddress,InstanceId]' \
--output table \
--profile labs-devops_diallo --region us-east-2
# Puis curl chaque IP:8080
for IP in $(aws ec2 ... --output text); do
echo "Testing $IP:8080..."
curl -s "http://$IP:8080/" || echo "Failed"
doneâš Avantages du design
â
ScalabilitĂ© : Changer instance_count de 2 Ă 10 ne change rien dâautre
â
Inventaire auto-découvert : Le plugin aws_ec2 voit toutes les instances tagguées
â
Parallélisation : Ansible se connecte aux N instances en parallÚle (pas séquentiellement)
â
MĂȘme config : Tous les hĂŽtes reçoivent exactement la mĂȘme configuration
â
Pas de duplicate : Les instances ne se gĂȘnent pas (chacune sa clĂ©, son IP)
đ Comparaison : 1 vs N instances
| Aspect | 1 instance | N instances |
|---|---|---|
| Playbook création | loop: 1 ou pas de boucle | loop: range(0, N) |
| Inventaire | Découvre 1 hÎte | Découvre N hÎtes automatiquement |
| Configuration | Cible 1 hĂŽte | Cible N hĂŽtes en parallĂšle |
| Changement pour passer Ă 5 instances | Rewrite tout | Juste -e instance_count=5 |
đ Fichiers fournis
- Playbook multi-instance :
scripts/ansible/create_ec2_instances_multi.yml - Script dâexĂ©cution :
scripts/ansible/exercise_4_multi_instance.sh./exercise_4_multi_instance.sh 3 # Crée 3 instances, configure toutes - Documentation :
td2/EXERCISES_3_4_ANALYSIS.md
đ§č Nettoyage multi-instance
# Lister les instances
aws ec2 describe-instances \
--filters "Name=tag:Ansible,Values=ch2_instances" "Name=instance-state-name,Values=running" \
--query 'Reservations[].Instances[].[InstanceId,Tags[?Key==`Name`].Value|[0]]' \
--output table \
--profile labs-devops_diallo --region us-east-2
# Terminer toutes les instances d'un coup
aws ec2 terminate-instances \
--instance-ids i-xxx i-yyy i-zzz ... \
--profile labs-devops_diallo --region us-east-2
# Nettoyer SG et clé
aws ec2 delete-security-group --group-name sample-app-ansible \
--profile labs-devops_diallo --region us-east-2
aws ec2 delete-key-pair --key-name ansible-ch2 \
--profile labs-devops_diallo --region us-east-2đ Fichiers dâaccompagnement
| Fichier | Description |
|---|---|
td2/EXERCISE_3_IDEMPOTENCE_ANALYSIS.md | Analyse dĂ©taillĂ©e de lâidempotence avec solutions |
td2/EXERCISES_3_4_ANALYSIS.md | Explications concepts et approches pour les deux exercices |
td2/LABS_EXERCISES_3_4_SUMMARY.md | Ce document â rĂ©capitulatif complet |
scripts/ansible/create_ec2_instances_multi.yml | Playbook pour créer N instances |
scripts/ansible/roles/sample-app/tasks/main_idempotent.yml | Version idempotente minimale du rĂŽle |
scripts/ansible/roles/sample-app/tasks/main_systemd.yml | Version avec systemd (meilleure pratique) |
scripts/ansible/exercise_3_idempotency.sh | Script pour tester idempotence |
scripts/ansible/exercise_4_multi_instance.sh | Script pour déployer N instances |
đ Conclusions
Exercice 3 : Idempotence
Lâidempotence est une propriĂ©tĂ© critique des playbooks Ansible. Notre test a rĂ©vĂ©lĂ© que la tĂąche âStart sample appâ nâest pas idempotente â elle crĂ©e un nouveau processus Ă chaque relance.
Takeaway : Toujours relancer un playbook 2x de suite en dĂ©veloppement pour vĂ©rifier lâidempotence. Utiliser changed_when:, when:, ou des modules de haut niveau.
Exercice 4 : Scalabilité horizontale
GrĂące Ă la boucle Ansible et aux inventaires dynamiques, dĂ©ployer N instances est aussi simple que de changer une variable. Pas de code dupliquĂ©, pas de risque dâincohĂ©rence.
Takeaway : Concevoir les playbooks pour la scalabilité dÚs le départ. Utiliser les boucles, les tags, et les inventaires dynamiques pour éviter les scripts pour 1, 2, 5, 10 instances.
Tous les fichiers et scripts sont prĂȘts Ă lâemploi.
Pour plus de détails, consultez les fichiers .md fournis dans td2/.