DevOpsFacile
AccueilParcours de formationCertificationsModulesCheat SheetÀ Propos
DevOpsFacile

Une plateforme d'apprentissage complète pour maîtriser les pratiques DevOps modernes, du débutant à l'expert.

contact@devopsfacile.fr

Formation

  • Parcours de formation
  • Modules

Informations

  • À Propos
  • Conditions d'utilisation
  • Confidentialité
  • Mentions légales

© 2026 DevOps Facile. Tous droits réservés.

Fait avec pour la communauté DevOps

ModulesAWS - Avancé : ECS, IAM avancé et architecture multi-région09 - Infrastructure as Code avec CloudFormation

Détails

  • 50 minutes
  • Avancé

Objectifs

  • Créer une stack CloudFormation décrivant une infrastructure complète
  • Comprendre les ressources, paramètres, outputs et dépendances
  • Mettre à jour une stack existante et gérer les changesets
  • Détruire une stack proprement et comprendre les rollbacks
Module AWS - Avancé : ECS, IAM avancé et architecture multi-région

Exercice 09 : Infrastructure as Code avec CloudFormation

🎯 Objectifs

À la fin de cet exercice, vous serez capable de :

  • ✅ Écrire un template CloudFormation YAML décrivant une instance EC2 + Security Group
  • ✅ Déployer, mettre à jour et supprimer une stack
  • ✅ Utiliser les paramètres pour rendre le template réutilisable
  • ✅ Utiliser les outputs pour exposer les valeurs créées

Durée estimée : 50 minutes

Difficulté : ⭐⭐⭐⭐☆ (Avancé)

Prérequis : EC2 (Exercice 04), S3 (Exercice 05), notions YAML


📖 Contexte

Cliquer dans la console AWS est excellent pour apprendre, mais pour la production il faut de la reproductibilité : déployer la même infrastructure dans 10 régions, ou la recréer identique après une suppression accidentelle. CloudFormation est l'outil AWS natif d'Infrastructure as Code : vous décrivez ce que vous voulez (état cible), CloudFormation crée et orchestre les ressources dans le bon ordre.


📋 Énoncé

Créez un template CloudFormation qui déploie un serveur web EC2 complet, avec paramètres et outputs.


🧭 Déroulement de l'exercice

Tâche 1 : Créer le template CloudFormation

bash
cat > stack-web-server.yaml << 'EOF'
AWSTemplateFormatVersion: "2010-09-09"
Description: "Stack CloudFormation - Serveur web EC2 avec Security Group"

# ========================
# PARAMÈTRES (personnalisables au déploiement)
# ========================
Parameters:
  NomEnvironnement:
    Type: String
    Default: dev
    AllowedValues: [dev, staging, prod]
    Description: "Environnement de déploiement"

  TypeInstance:
    Type: String
    Default: t2.micro
    AllowedValues: [t2.micro, t2.small, t2.medium]
    Description: "Type d'instance EC2"

  NomCleSSH:
    Type: AWS::EC2::KeyPair::KeyName
    Description: "Nom de la paire de clés SSH pour l'accès à l'instance"

  MonIP:
    Type: String
    Default: "0.0.0.0/0"
    Description: "Votre IP pour restreindre l'accès SSH (ex: 203.0.113.0/32)"

# ========================
# MAPPINGS (valeurs par région)
# ========================
Mappings:
  RegionToAMI:
    eu-west-3:
      AMI: ami-0d3c032f5934e1b41  # Amazon Linux 2023 Paris
    eu-west-1:
      AMI: ami-0905a3c97561e0b69  # Amazon Linux 2023 Dublin
    us-east-1:
      AMI: ami-0c101f26f147fa7fd  # Amazon Linux 2023 N.Virginia

# ========================
# RESSOURCES
# ========================
Resources:

  # Security Group
  SecurityGroupWeb:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "sg-web-${NomEnvironnement}"
      GroupDescription: !Sub "Security Group pour le serveur web - ${NomEnvironnement}"
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
          Description: "Trafic HTTP public"
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
          Description: "Trafic HTTPS public"
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref MonIP
          Description: "SSH depuis mon IP seulement"
      Tags:
        - Key: Name
          Value: !Sub "sg-web-${NomEnvironnement}"
        - Key: Environnement
          Value: !Ref NomEnvironnement

  # Instance EC2
  InstanceEC2:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref TypeInstance
      ImageId: !FindInMap [RegionToAMI, !Ref "AWS::Region", AMI]
      KeyName: !Ref NomCleSSH
      SecurityGroups:
        - !Ref SecurityGroupWeb  # Référence à la ressource ci-dessus
      Tags:
        - Key: Name
          Value: !Sub "serveur-web-${NomEnvironnement}"
        - Key: Environnement
          Value: !Ref NomEnvironnement
      # UserData : script exécuté au premier démarrage
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          set -e
          dnf update -y
          dnf install -y nginx
          systemctl enable --now nginx
          cat > /usr/share/nginx/html/index.html << 'HTML'
          <!DOCTYPE html>
          <html>
          <head><title>CloudFormation Demo</title></head>
          <body>
            <h1>Déployé par CloudFormation</h1>
            <p>Environnement : ${NomEnvironnement}</p>
          </body>
          </html>
          HTML

# ========================
# OUTPUTS (valeurs exportées)
# ========================
Outputs:
  IPPubliqueInstance:
    Description: "Adresse IP publique de l'instance EC2"
    Value: !GetAtt InstanceEC2.PublicIp
    Export:
      Name: !Sub "${AWS::StackName}-PublicIP"

  URLServeurWeb:
    Description: "URL du serveur web"
    Value: !Sub "http://${InstanceEC2.PublicDnsName}"

  IDSecurityGroup:
    Description: "ID du Security Group créé"
    Value: !GetAtt SecurityGroupWeb.GroupId
    Export:
      Name: !Sub "${AWS::StackName}-SGID"
EOF

Tâche 2 : Déployer la stack

bash
STACK_NAME="serveur-web-dev"

# Valider le template avant le déploiement
aws cloudformation validate-template \
  --template-body file://stack-web-server.yaml

# Déployer la stack
aws cloudformation create-stack \
  --stack-name $STACK_NAME \
  --template-body file://stack-web-server.yaml \
  --parameters \
    ParameterKey=NomEnvironnement,ParameterValue=dev \
    ParameterKey=TypeInstance,ParameterValue=t2.micro \
    ParameterKey=NomCleSSH,ParameterValue=devops-key \
    ParameterKey=MonIP,ParameterValue=$(curl -s https://checkip.amazonaws.com)/32

# Suivre le déploiement
aws cloudformation wait stack-create-complete --stack-name $STACK_NAME
aws cloudformation describe-stacks \
  --stack-name $STACK_NAME \
  --query 'Stacks[0].StackStatus'
bash
# Voir les outputs (IP, URL...)
aws cloudformation describe-stacks \
  --stack-name $STACK_NAME \
  --query 'Stacks[0].Outputs' \
  --output table

# Tester le serveur web
IP=$(aws cloudformation describe-stacks \
  --stack-name $STACK_NAME \
  --query 'Stacks[0].Outputs[?OutputKey==`IPPubliqueInstance`].OutputValue' \
  --output text)
curl http://$IP

Tâche 3 : Mettre à jour la stack avec un Changeset

Un changeset vous montre exactement ce qui sera modifié avant d'appliquer la mise à jour.

bash
# Modifier le template : ajouter une règle ICMP (ping)
# Ajouter dans SecurityGroupIngress :
cat >> /tmp/patch-sg.txt << 'EOF'
        - IpProtocol: icmp
          FromPort: -1
          ToPort: -1
          CidrIp: 0.0.0.0/0
          Description: "ICMP (ping)"
EOF

# Créer un changeset (ne déploie PAS encore)
aws cloudformation create-change-set \
  --stack-name $STACK_NAME \
  --template-body file://stack-web-server.yaml \
  --change-set-name "ajout-icmp" \
  --parameters \
    ParameterKey=NomEnvironnement,UsePreviousValue=true \
    ParameterKey=TypeInstance,UsePreviousValue=true \
    ParameterKey=NomCleSSH,UsePreviousValue=true \
    ParameterKey=MonIP,UsePreviousValue=true

# Voir les changements proposés
aws cloudformation describe-change-set \
  --stack-name $STACK_NAME \
  --change-set-name "ajout-icmp" \
  --query 'Changes[*].[ResourceChange.Action,ResourceChange.ResourceType,ResourceChange.PhysicalResourceId]' \
  --output table

# Appliquer le changeset
aws cloudformation execute-change-set \
  --stack-name $STACK_NAME \
  --change-set-name "ajout-icmp"

Tâche 4 : Supprimer la stack

bash
# CloudFormation supprime toutes les ressources dans le bon ordre
aws cloudformation delete-stack --stack-name $STACK_NAME

# Attendre la suppression
aws cloudformation wait stack-delete-complete --stack-name $STACK_NAME
echo "Stack supprimée avec succès"

Indice : Si la suppression échoue (par exemple, un bucket S3 non vide), CloudFormation laisse la stack en état DELETE_FAILED et vous dit quelles ressources n'ont pas pu être supprimées. Vous devez les supprimer manuellement puis relancer la suppression.


✅ Vérification du résultat

  • aws cloudformation validate-template retourne sans erreur
  • La stack passe à l'état CREATE_COMPLETE
  • curl http://$IP affiche la page "Déployé par CloudFormation"
  • Le changeset montre bien la modification du Security Group avant application
  • La stack est supprimée et toutes les ressources sont effacées

💡 À retenir

Avantages CloudFormation vs console manuelle :

ConsoleCloudFormation
Reproductible❌✅
Versionnable (Git)❌✅
Rollback automatique❌✅
Dépendances gérées❌✅
Audit/traçabilitéPartiel✅

Références CloudFormation essentielles :

  • !Ref NomParametre : valeur d'un paramètre
  • !GetAtt Ressource.Attribut : attribut d'une ressource créée
  • !Sub "texte-${Variable}" : substitution de chaîne
  • !FindInMap [Mapping, Clé, SousClé] : lookup dans un mapping

✨ Solution Complète

bash
# Cycle de vie complet d'une stack
aws cloudformation validate-template --template-body file://stack.yaml
aws cloudformation deploy --template-file stack.yaml --stack-name ma-stack \
  --parameter-overrides Env=dev --capabilities CAPABILITY_IAM
aws cloudformation describe-stacks --stack-name ma-stack --query 'Stacks[0].Outputs'
aws cloudformation delete-stack --stack-name ma-stack
Retour au module

Sur cette page

  • 🎯 Objectifs
  • 📖 Contexte
  • 📋 Énoncé
  • 🧭 Déroulement de l'exercice
  • Tâche 1 : Créer le template CloudFormation
  • Tâche 2 : Déployer la stack
  • Tâche 3 : Mettre à jour la stack avec un Changeset
  • Tâche 4 : Supprimer la stack
  • ✅ Vérification du résultat
  • 💡 À retenir
  • ✨ Solution Complète