CloudFormation : premier stack YAML
À la fin de ce tutoriel, vous rédigerez un template YAML CloudFormation, créerez un stack qui provisionne un bucket S3 privé (Block Public Access), validerez, mettrez à jour (tags), repérerez le drift, puis supprimerez le stack — en
ca-central-1, sans EC2 coûteuse.Niveau : Intermédiaire · Temps estimé : 55–70 min · Versions testées : CloudFormation 2026, AWS CLI v2, YAML · Dernière vérification : 2026-09-10 · Region :
ca-central-1← Précédent : Lambda + API Gateway · → Suivant : Elastic Beanstalk · Hub : Démarrer avec AWS
Prérequis
- Profil AWS CLI
labavec droitscloudformation:*ets3:*(ou politiques plus fines) - AWS CLI v2 installée et configurée
- Éditeur de texte (VS Code, nano…) pour le YAML
- Budget d’alerte activé — lab quasi gratuit (S3 vide), mais supprimez toujours le stack en fin de session
- Notions S3 (S3 bucket & sécurité) et un premier contact IaC (Lambda + API Gateway)
export AWS_PROFILE=lab
export AWS_DEFAULT_REGION=ca-central-1
aws sts get-caller-identity
Vérifiez que l’identité renvoyée est celle du compte lab — jamais la production.
Ce que nous allons construire
lab-cf-s3-stack (CloudFormation)
│
▼
Template YAML
├── Parameters (BucketNamePrefix)
├── Resources
│ └── AWS::S3::Bucket (privé + BPA + tags)
└── Outputs (BucketName, BucketArn)
│
▼
Bucket S3 ca-central-1 (lab, vide, privé)
(Schéma — alt : « Stack CloudFormation YAML créant un bucket S3 privé avec Block Public Access ».)
Une ressource unique, peu chère, pour le cycle complet (validate → create → update → drift → delete) sans EC2 ni base. En prod vous empilerez VPC, IAM, ALB… ici on maîtrise d’abord le gabarit YAML et la CLI.
Étape 1 — Pourquoi l’IaC / CloudFormation vs la console
La console suffit pour un POC. Pour reproduire (lab, staging, prod), documenter les changements et éviter les « snowflake », il faut de l’Infrastructure as Code.
| Approche | Forces | Limites |
|---|---|---|
| Console clics | Rapide pour découvrir | Non reproductible, drift humain |
| Scripts CLI bash | Automatisable | Ordre, rollback et dépendances fragiles |
| CloudFormation | Stack versionné, rollback, Drift | Syntaxe verbose ; JSON/YAML natif |
| Terraform / CDK / SAM | DX souvent plus riche | Abstraction au-dessus (ou hors) CFN |
CloudFormation est le service natif AWS : un template décrit l’état désiré ; un stack est l’instance déployée. Les mises à jour sont transactionnelles (rollback si échec, selon options). Examen Solutions Architect : savoir quand choisir CFN, ce qu’est un change set, et que Drift Detection compare template vs réalité.
Étape 2 — Anatomie d’un template YAML
| Section | Rôle |
|---|---|
AWSTemplateFormatVersion |
Format (2010-09-09 — stable) |
Description |
Texte libre pour humains / reviewers |
Parameters |
Valeurs injectées à la création / update |
Resources |
Obligatoire — ressources AWS (AWS::S3::Bucket, etc.) |
Outputs |
Valeurs exportées (nom, ARN) pour CLI / autres stacks |
Mappings / Conditions |
Tables / booléens (hors lab minimal) |
Chaque ressource a un logical ID (ex. LabBucket) et un physical ID une fois créée. Références croisées : !Ref et !GetAtt.
Étape 3 — Écrire le template du lab
Créez lab-s3-stack.yaml (placeholders seulement — pas de secrets) :
AWSTemplateFormatVersion: "2010-09-09"
Description: >
Lab CloudFormation — bucket S3 privé (Block Public Access)
Region cible : ca-central-1. À supprimer après le lab.
Parameters:
BucketNamePrefix:
Type: String
Default: lab-cf
Description: Préfixe du nom de bucket (suffixe aléatoire ajouté)
MinLength: 3
MaxLength: 40
AllowedPattern: "^[a-z0-9][a-z0-9-]*$"
ConstraintDescription: minuscules, chiffres, tirets
Resources:
LabBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
Properties:
BucketName: !Sub "${BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}"
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
Tags:
- Key: Project
Value: devopselastichayway-lab
- Key: Environment
Value: lab
- Key: ManagedBy
Value: cloudformation
Outputs:
BucketName:
Description: Nom physique du bucket
Value: !Ref LabBucket
BucketArn:
Description: ARN du bucket
Value: !GetAtt LabBucket.Arn
Points clés :
!Subcompose un nom unique (AccountId + Region) — évite les collisions S3 globales.- Block Public Access (4 drapeaux) = bucket privé par défaut (bonnes pratiques S3 2026).
DeletionPolicy: Delete: à la suppression du stack, le bucket part s’il est vide. En prod, parfoisRetain.- Aucun secret dans le YAML — paramètres et tags de lab uniquement.
Étape 4 — Valider le template
aws cloudformation validate-template
--template-body file://lab-s3-stack.yaml
La commande renvoie Description, Parameters et Capabilities. Elle n’garantit pas le succès du déploiement (noms pris, quotas, IAM), mais attrape YAML cassé et types invalides. En CI, branchez-la avant merge. Optionnel : cfn-lint lab-s3-stack.yaml.
Étape 5 — Créer le stack
STACK_NAME=lab-cf-s3-stack
aws cloudformation create-stack
--stack-name "$STACK_NAME"
--template-body file://lab-s3-stack.yaml
--parameters ParameterKey=BucketNamePrefix,ParameterValue=lab-cf
--tags Key=Owner,Value=lab Key=Tutorial,Value=cloudformation-25
--region ca-central-1
aws cloudformation wait stack-create-complete
--stack-name "$STACK_NAME"
aws cloudformation describe-stacks
--stack-name "$STACK_NAME"
--query 'Stacks[0].{Status:StackStatus,Outputs:Outputs}'
--output table
wait bloque jusqu’à CREATE_COMPLETE (ou échoue sur ROLLBACK_COMPLETE). Les Outputs BucketName et BucketArn sont vos preuves de succès.
BUCKET=$(aws cloudformation describe-stacks
--stack-name "$STACK_NAME"
--query "Stacks[0].Outputs[?OutputKey=='BucketName'].OutputValue"
--output text)
echo "Bucket créé : $BUCKET"
aws s3api get-public-access-block --bucket "$BUCKET"
Les quatre blocs BPA doivent être à true. Bucket vide → coût S3 négligeable.
Étape 6 — Mettre à jour le stack (tags)
Ajoutez un tag CostCenter dans le template :
Tags:
- Key: Project
Value: devopselastichayway-lab
- Key: Environment
Value: lab
- Key: ManagedBy
Value: cloudformation
- Key: CostCenter
Value: training-2026
Puis :
aws cloudformation update-stack
--stack-name "$STACK_NAME"
--template-body file://lab-s3-stack.yaml
--parameters ParameterKey=BucketNamePrefix,ParameterValue=lab-cf
aws cloudformation wait stack-update-complete
--stack-name "$STACK_NAME"
Change sets (concept)
En équipe, préférez un change set : CFN calcule le diff (créer / modifier / remplacer / supprimer) sans appliquer. Revue du plan, puis execute-change-set. Évite les Replacement surprises (renommer un bucket force un remplacement — S3 ne renomme pas in-place).
aws cloudformation create-change-set
--stack-name "$STACK_NAME"
--change-set-name lab-tags-review
--template-body file://lab-s3-stack.yaml
--parameters ParameterKey=BucketNamePrefix,ParameterValue=lab-cf
--change-set-type UPDATE
aws cloudformation describe-change-set
--stack-name "$STACK_NAME"
--change-set-name lab-tags-review
# Ensuite : execute-change-set OU delete-change-set
Examen : change set = aperçu des impacts avant update.
Étape 7 — Drift detection
Le drift apparaît quand une ressource est modifiée hors CloudFormation (console, CLI). CFN peut détecter l’écart.
aws cloudformation detect-stack-drift --stack-name "$STACK_NAME"
# Attendez quelques secondes puis :
aws cloudformation describe-stack-resource-drifts
--stack-name "$STACK_NAME"
--query 'StackResourceDrifts[].{LogicalId:LogicalResourceId,Status:StackResourceDriftStatus}'
Pour provoquer un drift (optionnel) : ajoutez un tag via aws s3api put-bucket-tagging, relancez detect-stack-drift, observez MODIFIED, puis réconciliez via update-stack depuis le template (source de vérité). En prod : Drift + alarmes = gouvernance IaC.
Étape 8 — Vérification
aws cloudformation describe-stacks --stack-name "$STACK_NAME"
--query 'Stacks[0].StackStatus'
aws cloudformation list-stack-resources --stack-name "$STACK_NAME"
--query 'StackResourceSummaries[].{Logical:LogicalResourceId,Type:ResourceType,Status:ResourceStatus}'
aws s3api head-bucket --bucket "$BUCKET"
aws s3api get-bucket-tagging --bucket "$BUCKET"
Checklist :
- StackStatus =
CREATE_COMPLETEouUPDATE_COMPLETE LabBucket=AWS::S3::BucketenCREATE_COMPLETE/UPDATE_COMPLETE- Block Public Access actif (4× true)
- Tags
ManagedBy=cloudformation(+CostCenteraprès update) - Outputs
BucketName/BucketArnnon vides - Plan de delete-stack noté avant de quitter
Nettoyage (obligatoire)
Le bucket doit être vide pour que CFN le supprime (DeletionPolicy: Delete). Si un objet de test existe, videz-le d’abord.
# Si besoin : vider le bucket (lab uniquement)
# aws s3 rm "s3://${BUCKET}" --recursive
aws cloudformation delete-stack --stack-name "$STACK_NAME"
aws cloudformation wait stack-delete-complete
--stack-name "$STACK_NAME"
aws cloudformation describe-stacks --stack-name "$STACK_NAME" 2>&1 || echo "Stack supprimé OK"
Si DELETE_FAILED : souvent un objet restant (ou Object Lock hors lab). Corrigez, puis delete-stack à nouveau. Un bucket vide ≈ gratuit ; un stack oublié avec EC2/NAT/ALB facture — d’où le choix S3-only.
Suite — SAM et CDK (aperçu)
- AWS SAM : templates CFN enrichis (
AWS::Serverless::Function) pour Lambda / API — suite naturelle du lab Lambda + API Gateway. - AWS CDK (TypeScript/Python) : génère du CloudFormation (
cdk synth→cdk deploy).
Les deux aboutissent à des stacks CFN : comprendre YAML natif reste un atout debug / examen. Prochain tuto de la série : Elastic Beanstalk (PaaS), pas encore CDK.
Coûts du lab
| Élément | Ordre de grandeur lab |
|---|---|
| CloudFormation | Gratuit (API standard) |
| Bucket S3 vide | ≈ 0 $ |
Requêtes validate / describe |
Négligeables |
| Oubli (objets + autres services) | Peut coûter — delete-stack systématique |
Activez une alarme de budget (voir CloudWatch / Billing) même pour les labs « gratuits ».
Erreurs fréquentes
| Symptôme | Cause | Correction |
|---|---|---|
AlreadyExists / bucket name |
Nom S3 globalement pris | Changer BucketNamePrefix ou garder !Sub AccountId |
ValidationError YAML |
Indentation / type faux | validate-template + relecture YAML |
DELETE_FAILED |
Bucket non vide | aws s3 rm --recursive puis re-delete |
UPDATE_ROLLBACK |
Propriété invalide | Events du stack (describe-stack-events) |
Drift MODIFIED |
Changement hors template | Revenir au template ou importer le changement |
| AccessDenied create-stack | IAM lab insuffisant | Droits CloudFormation + S3 |
Astuce : aws cloudformation describe-stack-events --stack-name "$STACK_NAME" --max-items 20 — la première ligne en échec indique souvent la ressource et le message AWS exact.
Bonnes pratiques (examen + prod)
- Repo Git pour les templates ; jamais de secrets en clair (Secrets Manager / SSM + références dynamiques).
- Paramètres pour ce qui change entre env ; Mappings pour AMI / régions.
- Stack policies pour protéger des ressources critiques.
- Nested stacks / modules si le template grossit.
- Change sets en CI/CD avant
execute. - Taguer systématiquement (
Environment,ManagedBy,Owner) pour FinOps et Drift.
Quiz (3 questions)
1. La section obligatoire d’un template CloudFormation est :
– A. Mappings uniquement
– B. Resources
– C. Metadata seule
2. Pour un bucket S3 de lab géré par CloudFormation, la bonne hygiène est :
– A. Laisser le bucket public « pour tester »
– B. Block Public Access + delete-stack en fin de lab
– C. Créer une EC2 devant le bucket
3. Un change set sert surtout à :
– A. Facturer Spot
– B. Prévisualiser les impacts d’un update avant exécution
– C. Remplacer IAM Identity Center
Réponses : 1‑B · 2‑B · 3‑B
Pour aller plus loin
- AWS CloudFormation User Guide
- Resource type AWS::S3::Bucket
- Detecting unmanaged configuration changes (drift)
- AWS SAM
Maillage série AWS (P1)
| ← Précédent | Lambda + API Gateway |
| → Suivant | Elastic Beanstalk |
| Aussi | S3 sécurité · Démarrer avec AWS |
Retour parcours AWS — hub de la série et leçons sœurs.



