Introduction au Lab 2

Ce TP a pour objectif de nous familiariser avec le déploiement d’infrastructure cloud sur AWS en utilisant différents outils d’automatisation : des scripts Bash, Ansible, Packer et OpenTofu. Nous allons progressivement passer d’une approche manuelle avec des scripts à une approche déclarative et modulaire.


Section 2 : Deploying an EC2 Instance Using a Bash Script

1. Set Up the Directory Structure

On crée le dossier bash dans le dossier script.

2. Create the User Data Script

On copie le script user data dans le fichier user-data.sh.

3. Create the Bash Script

On crée le fichier deploy-ec2-instance.sh et on copie le script provenant du sujet.

5. Run the Script

On lance l’instance EC2.

instance

6. Test the Deployment

Le déploiement est testé avec succès.

deploiement

Exercices

Exercice 1 :

What happens if you run the script a second time? Try it and observe the output. Explain why this happens. Hint: Consider resource names and uniqueness in AWS.

Quand on essaye de relancer la commande, on obtient cette erreur :

bash git:(main)  ./deploy-ec2-instance.sh
An error occurred (InvalidGroup.Duplicate) when calling the CreateSecurityGroup operation: 
The security group 'sample-app' already exists for VPC 'vpc-030743539e69419e7'

Cette erreur signifie que notre requête échoue car notre script va simplement créer une ressource AWS sans vérifier si une ressource n’existe pas déjà avec ce nom. Or, dans AWS, les noms des security groups doivent être uniques. AWS refuse donc de créer une ressource dont le nom existe déjà et renvoie une erreur.

Exercice 2 :

Modify the script to deploy multiple EC2 instances. How would you adjust the script to handle this?

Pour que le script fonctionne quand même, il faudrait changer le nom de l’instance en mettant un nom unique.


Section 3: Deploying an EC2 Instance Using Ansible

2. Create the Ansible Playbook for EC2 Deployment

On crée le fichier create_ec2_instance_playbook.yml et on copie le code donné dans le sujet.

3 - Exécution du Playbook

On lance le Playbook.

playbook

On voit avec failed=0 et changed=1 que l’instance a bien été déployée.

4. Set Up the Ansible Inventory

On crée l’inventaire inventory.aws_ec2.yml.

5. Create Group Variables

On crée le dossier group_vars puis le fichier ch2_instances.yml.

6. Create the Ansible Playbook for Configuration

On crée le fichier configure_sample_app_playbook.yml.

7. Create the Ansible Role

On crée la structure de dossiers demandée puis on copie app.js.

8. Run the Configuration Playbook

Le playbook de configuration est exécuté avec succès.

configuration

9. Test the Deployment

Ici nous avons essayé de tester le déploiement de l’application en allant sur l’URL http://18.224.32.181:8080. Cependant, nous ne sommes pas parvenues à ouvrir la page, elle ne faisait que charger en continu sans me donner de résultat. Nous avons donc recherché la cause probable.

test

En cherchant, nous avons trouvé que nous pouvions voir le contenu de ma page avec ces deux commandes :

# Connecte-toi à l'instance
ssh -i ansible-ch2.key ec2-user@18.224.32.181
 
# Une fois dedans, teste si l'app répond localement
curl http://localhost:8080

Et nous sommes parvenues à avoir le résultat Hello World ! :

  ansible git:(main)  ssh -i ansible-ch2.key ec2-user@18.224.32.181
The authenticity of host '18.224.32.181 (18.224.32.181)' can't be established.
ED25519 key fingerprint is SHA256:3bodBEl5o4XI0lES3SI3RSR5ubXp4l8dCDBjQZCxNe0.
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:3: ec2-18-224-32-181.us-east-2.compute.amazonaws.com
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '18.224.32.181' (ED25519) to the list of known hosts.
   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'
Last login: Fri Feb  6 14:55:18 2026 from 79.174.206.181
[ec2-user@ip-172-31-12-249 ~]$ curl http://localhost:8080
Hello, World!
[ec2-user@ip-172-31-12-249 ~]$

Ainsi, selon nos recherches, le problème est sûrement dû au Security Group d’AWS qui bloque les connexions venant de notre navigateur vers le port 8080.

Pour réussir tout de même à ouvrir l’URL dans notre navigateur, nous avons essayé de faire cette commande :

  ansible git:(main)  aws ec2 authorize-security-group-ingress \
    --group-name sample-app-ansible \
    --protocol tcp \
    --port 8080 \
    --cidr 0.0.0.0/0
 
An error occurred (InvalidPermission.Duplicate) when calling the AuthorizeSecurityGroupIngress operation: 
the specified rule "peer: 0.0.0.0/0, TCP, from port: 8080, to port: 8080, ALLOW" already exists

Nous avons eu une erreur à la suite de cette requête, mais en essayant à nouveau d’ouvrir l’URL, la page s’est bien affichée. Nous ne savons pas si c’est grâce à la commande ou parce que nous avons changé de wifi, mais finalement ça marche !

test

Exercices

Exercice 3 :

What happens if you run the configuration playbook a second time? Observe and explain. Hint: Consider idempotency in Ansible tasks.

Si nous essayions de relancer la commande ansible-playbook -i inventory.aws_ec2.yml configure_sample_app_playbook.yml, nous ne voyons pas de changement. Le résultat que nous obtenons ne nous semble pas différent de la première fois que nous avons lancé la commande.

test

Hint — Idempotence dans Ansible : Ansible est conçu pour être idempotent, ce qui signifie que rejouer le même playbook ne modifie rien si l’état souhaité est déjà atteint. Les tâches vérifient l’état actuel avant d’agir.

Exercice 4 :

Modify the playbook to deploy and configure multiple EC2 instances. How would you adjust the playbook and inventory?

Afin de pouvoir créer plusieurs instances en même temps, nous avons ajouté des lignes de code dans le fichier create_ec2_instance_playbook.yml.

test

Nous n’avons pas changé l’inventaire ni le Playbook car nous avons vu que cela n’avait pas besoin d’être changé et que cela se faisait automatiquement.

Ensuite j’ai nettoyé le tout pour passer à la section 4.

test


Section 4 : Creating a VM Image Using Packer

1. Set Up the Directory Structure

On crée la structure de répertoires.

2. Copy the Node.js Sample App

On copie l’application Node.js Sample App.

3. Create the Packer Template

On crée le fichier sample-app.pkr.hcl et on copie le code donné dans le sujet. On a eu besoin d’installer Packer préalablement.

test

4. Initialize Packer

On initialise et on construit notre AMI avec Packer.

test

5. Build the AMI

On construit notre AMI.

test

test

On peut voir que notre AMI a bien été créée :

test

Exercices

Exercice 5 :

What happens if you run packer build a second time? Explain why. Hint: Consider the uniqueness of the ami name .

Normalement, si on relance exactement la même commande sans rien modifier, on va obtenir une erreur car AWS interdit d’avoir deux AMIs avec le même identifiant. Sauf que dans notre fichier, nous avons nommé notre AMI comme suit :

ami_name = "sample-app-packer-${uuidv4()}"

Ainsi, grâce à la fonction uuidv4(), Packer va générer un identifiant unique à chaque fois que l’on construit une nouvelle AMI. Donc, si on relance la commande, build va créer une nouvelle AMI avec un nom différent et un nouvel ID, et ne va pas générer d’erreur.

Exercice 6 :

Modify the Packer template to create images for another cloud provider or for local use (e.g., VirtualBox).

Nous avons compris que Packer est multi-provider, ce qui signifie que l’on peut utiliser plusieurs services cloud en même temps. Pour changer de service, il faut modifier deux sections dans le fichier sample-app.pkr.hcl :

  • Dans un premier temps, il faut modifier le bloc packer {} (les plugins) et ajouter le plugin du nouveau service cloud.
  • Ensuite, il faut modifier le bloc source {} en remplaçant amazon-ebs par le type correspondant au nouveau service.

Avant de passer à la section 5, j’ai bien désenregistré l’AMI.

lab2


Section 5 : Deploying, Updating, and Destroying an EC2 Instance Using OpenTofu

1. Set Up the Directory Structure

On crée la structure du dossier.

2. Create the Main Configuration File

On crée le fichier main.

test

3. Create the Variables File

On crée le fichier variables.

lab2

4. Create the User Data Script

On crée le fichier User Data script.

lab2

5. Create the Outputs File

On crée le fichier output.

lab2

6. Initialize OpenTofu

Avant d’initialiser tofu, j’installe OpenTofu.

lab2

Ensuite, je lance l’initialisation de tofu.

lab2

7. Apply the Configuration

Ensuite, je lance tofu apply et j’entre l’identifiant de mon AMI créée avec Packer.

tofu

tofu

tofu

Après avoir validé, la configuration est appliquée avec succès.

succes

8. Test the Deployment

Ensuite, nous pouvons tester le déploiement en allant à l’URL http://3.143.143.144:8080.

test

9. Update the Configuration

Nous avons bien appliqué la modification :

configuration

Nous avons relancé tofu apply :

apply

Ensuite, je détruis les ressources.

apply

apply

apply

Les ressources ont bien été détruites.

Exercices

Exercice 7 :

What happens if you run tofu apply after the resources have been destroyed? Explain the behavior.

Si l’on relance tofu apply après la destruction, aucun changement n’apparaît au sens d’erreur, en effet, les ressources sont bien recréées.

apply

apply

En effet, même si nous avons tout détruit, tofu compare notre code et le State file. Comme le State file est vide, tofu va recréer toutes les ressources.

Exercice 8 :

How would you modify the OpenTofu code to deploy multiple EC2 instances? Implement this change using a loop or by defining multiple resources.

Pour déployer plusieurs instances EC2, il suffit d’ajouter une ligne count dans le bloc resource du fichier main :

resource "aws_instance" "sample_app" {
  count = 2
  # ...
}

lab2


Section 6 : Deploying an EC2 Instance Using an OpenTofu Module

1. Set Up the Modules Directory

On crée la structure de répertoires.

2. Create the Root Module

On crée le module.

3. Create the Main Configuration File

On crée le fichier main et on copie le code donné.

main

4. Modify the Module to Use Variables

On modifie le fichier variables.

variables

5. Update main.tf in the Module to Use var.name

On actualise le fichier main en ajoutant var.name pour donner le nom à travers une variable.

module

6. Initialize OpenTofu

On lance l’initialisation d’OpenTofu.

initialisation

7. Apply the Configuration

L’initialisation fonctionnait parfaitement, mais lorsque nous avons voulu lancer tofu apply -var ami_id=ami-08473fbb358a1464d, nous avons obtenu plusieurs erreurs.

configuration

Nous avons donc modifié nos codes pour résoudre ces erreurs :

  • Dans le fichier main, nous avons modifié le contenu de ami_id.

contenu

  • Dans le fichier variables, nous avons ajouté la variable "ami_id".

variables

  • Nous avons complété le code dans le main du module.

main

  • Nous avons ajouté un fichier variable.tf dans live pour déclarer la variable "ami_id".

variables

Ensuite on a relancé la commande pour la configuration et cette fois-ci, on n’avait plus aucune erreur et tout a fonctionné.

succes

succes

succes

succes

8. Test the Deployment

Maintenant, nous pouvons récupérer les deux adresses IP publiques de nos instances.

deployment

Pour la première instance, on saisit cette URL dans notre navigateur : http://3.133.105.77:8080

instance

Puis on teste la deuxième instance avec cette URL : http://3.138.182.226:8080

url{width=80%}

Exercices

Exercice 9 :

Modify the module to accept additional parameters like port . Update the root module to pass these parameters.

On a modifié le code de variables.tf de ec2-instance pour que le module accepte plusieurs paramètres.

ec2

On a également modifié le main de ec2-instance.

ec2

Ensuite on a relancé l’initialisation avec tofu init puis tofu apply -var ami_id=ami-08473fbb358a1464d.

ami_id

On a également ajouté instance_type = "t3.micro" dans le main de sample-app, sinon nous avions une erreur lors de tofu apply -var ami_id=ami-08473fbb358a1464d.

t3micro

t3

Exercice 10 :

Use OpenTofu’s count or for each to deploy multiple instances without duplicating code in the root module.

Pour faire cela, on a ajouté la boucle for_each dans le main de sample-app :

app

Ensuite on a modifié les outputs de sample-app car sinon nous avions une erreur.

sample

Ensuite j’ai relancé l’initialisation avec tofu init puis tofu apply -var ami_id=ami-08473fbb358a1464d. Nous avons dû faire au préalable tofu destroy -var ami_id=ami-08473fbb358a1464d car nous avions une erreur avec l’unicité des noms des variables des groupes de sécurité.

destroy

destroy

On peut saisir l’URL avec les adresses IP et retrouver notre application sur le navigateur :

  • Pour la première instance : http://3.142.51.82:8080

ip

  • Pour la deuxième instance : http://3.150.117.170:8080

lab2


Section 7: Using OpenTofu Modules from GitHub

Après avoir essayé avec le code déjà donné dans le main.tf de sample-app-github, nous avons obtenu de nombreuses erreurs. Alors, on a modifié outputs et créé un fichier variable, mais cela ne fonctionnait toujours pas. Nous avons finalement modifié le main.tf et les outputs et nous avons enfin réussi à lancer sans erreur tofu apply -var ami_id=ami-08473fbb358a1464d.

Fichier main :

main

Fichier outputs :

main

Fichier variables :

main

2. Initialize OpenTofu

On lance l’initialisation d’OpenTofu.

3. Apply the Configuration

On applique la configuration avec tofu apply.

apply

4. Test the Deployment

Si l’on saisit l’URL, on retrouve bien notre application sur le navigateur web : http://18.218.248.209:8080

deployment

Exercices

Exercice 11 :

Explore the use of versioning with modules by specifying a specific Git tag or commit in the module source.

Pour cette question, nous avons ajouté ?ref=v0.0.1 à la fin de l’URL de la source GitHub dans le fichier main.tf de sample-app-github. Grâce à cet ajout, même si l’auteur du répertoire GitHub modifie quelque chose sur celui-ci, notre commande tofu apply parviendra toujours à fonctionner. Cela nous permet de choisir la version que nous utilisons.

lab2

Exercice 12 :

Find an OpenTofu module in the Terraform Registry or another public repository and use it in your configuration.

On a regardé le catalogue public Terraform Registry regroupant énormément de modules écrits par des experts et les services cloud. Contrairement à GitHub où l’on utilise une URL complète, le Registry permet d’utiliser un nom court et un argument version dédié, ce qui nous permet de garantir la stabilité de notre code. On a donc modifié le main de sample-app-github en ajoutant le module "vpc" :

Il a fallu aussi changer la référence mise lors de la question 10 car cela ne fonctionnait pas sinon.

lab2

Nous avond commenté tous les outputs aussi, sinon cela ne fonctionnait pas.

outputs

J’ai lancé la commande tofu init -upgrade. L’argument -upgrade est important pour forcer OpenTofu à oublier l’erreur du tag v0.0.1 et à prendre la branche main, sinon cela ne fonctionne pas.

img

Puis nous avons lancé : tofu apply -var ami_id=ami-08473fbb358a1464d Et cela a bien fonctionné !

succes

Conclusion

Ce TP nous a permis de découvrir et de comparer plusieurs outils essentiels au déploiement d’infrastructure cloud sur AWS. Nous avons commencé par des scripts Bash simples pour des déploiements rapides puis nous avons continué avec Ansible pour la configuration idempotente des serveurs, Packer pour la création d’images reproductibles mais également des modules comme OpenTofu réutilisables.

Au final, ce TP pose les bases concrètes de l’Infrastructure as Code (IaC) que nous avons ensuite pu approfondir avec la mise en place d’un pipeline CI/CD complet dans le Lab 5.