AWS DevOps Infrastructure Code : les 9 étapes clés pour passer de zéro à opérationnel
AWS DevOps Infrastructure Code : l'essentiel en un article — vrai code, schémas et étapes concrètes, extraits d'un cours de 39 leçons.
Tout le monde peut apprendre AWS DevOps Infrastructure Code — à condition de suivre les étapes dans le bon ordre. On a condensé un cours complet de 39 leçons en un parcours clair, avec les extraits de code les plus utiles.
- Introduction et Configuration AWS
- DevOps et Infrastructure as Code
- AWS CloudFormation
- AWS CDK Cloud Development Kit
- CICD avec AWS CodePipeline
Introduction à AWS CDK — Cloud Development Kit
Chapitre 03 — Leçon 01 · AWS DevOps : Infrastructure as Code
1. Qu'est-ce que l'AWS CDK ?
CloudFormation, c'est comme remplir un formulaire administratif CERFA à la main, case par case, en respectant des règles de syntaxe strictes. C'est fastidieux mais ça fonctionne. Le CDK, c'est avoir un programme informatique qui remplit ce formulaire à votre place : vous lui dites en Python "je veux un serveur de taille moyenne avec une base de données", et il génère automatiquement le formulaire CERFA complet, correctement rempli, avec toutes les cases obligatoires. Vous écrivez beaucoup moins, vous faites beaucoup plus, et vous bénéficiez de toute la puissance d'un vrai langage de programmation comme les boucles, les fonctions et la réutilisation de code.
L'AWS Cloud Development Kit (CDK) est un framework open-source qui permet de définir votre infrastructure AWS avec un vrai langage de programmation : Python, TypeScript, Java, C# ou Go. Le CDK génère ensuite automatiquement des templates CloudFormation à partir de votre code.
CDK vs CloudFormation — comparaison
| Critère | CloudFormation (YAML) | AWS CDK (Python) |
|---|---|---|
| Langage | YAML / JSON déclaratif | Python, TypeScript, Java, C#, Go |
| Réutilisabilité | Copier-coller, Nested Stacks | Classes, modules, héritage |
| Autocomplétion IDE | Limitée (YAML) | Complète avec types et documentation |
| Logique | Conditions et mappings limités | if/else, boucles for, fonctions complètes |
| Tests | Difficile | Tests unitaires avec pytest, jest |
| Courbe d'apprentissage | Faible pour YAML, mais verbose | Nécessite connaissance d'un langage de prog. |
| Sous le capot | Exécuté directement par CloudFormation | Génère du CloudFormation puis le déploie |
Les quatre concepts fondamentaux du CDK
App (Application CDK)
Le point d'entrée de tout projet CDK. Une App contient une ou plusieurs Stacks. C'est le conteneur racine de votre infrastructure.
Stack (Pile CDK)
Correspond à une stack CloudFormation. Contient des Constructs (ressources AWS). Une App peut avoir plusieurs Stacks pour différents environnements.
Construct
Le bloc de construction de base du CDK. Représente une ressource AWS (ou un groupe de ressources). Existe à trois niveaux : L1, L2, L3.
Environment (Env)
La combinaison compte AWS + région cible pour le déploiement. Permet de déployer la même stack dans plusieurs environnements.
2. Installation — Node.js, CDK CLI et Python
Le CDK CLI est un outil Node.js. Même si vous codez en Python, vous devez avoir Node.js installé.
Prérequis
# 1. Vérifier Node.js (version 18+ recommandée) node --version
# Bootstrap dans la région courante cdk bootstrap # Bootstrap dans une région spécifique cdk bootstrap aws://123456789012/eu-west-1
Les Constructs sont les briques de base du CDK. Ils existent à trois niveaux d'abstraction, chacun offrant un compromis différent entre contrôle et simplicité.
L1 — Constructs bas niveau (CfnXxx)
Les constructs L1 (préfixés Cfn) sont des wrappers directs autour des ressources CloudFormation. Ils donnent accès à toutes les propriétés mais sans aucune valeur par défaut — vous devez tout configurer explicitement.
from aws_cdk import aws_s3 as s3
import aws_cdk as cdk
class MaStack(cdk.Stack):
def __init__(self, scope, id, **kwargs):
super().__init__(scope, id, **kwargs)
# L1 : CfnBucket = wrapper direct CloudFormation AWS::S3::Bucket
bucket_l1 = s3.CfnBucket(self, "BucketL1",
bucket_name="mon-bucket-l1",
versioning_configuration=s3.CfnBucket.VersioningConfigurationProperty(
status="Enabled"
),
lifecycle_configuration=s3.CfnBucket.LifecycleConfigurationProperty(
rules=[s3.CfnBucket.RuleProperty(
id="expiration-anciens-objets",
status="Enabled",
expiration_in_days=90
)]
)
)L2 — Constructs haut niveau (recommandés)
Nested Stacks, StackSets, Change Sets et Bonnes Pratiques
Chapitre 02 — Leçon 03 · AWS DevOps : Infrastructure as Code
1. Nested Stacks — décomposer les grandes infrastructures
Imaginez la construction d'un immeuble de bureaux. Plutôt qu'un seul entrepreneur qui ferait tout de A à Z et serait vite dépassé, on fait appel à des spécialistes indépendants : un électricien pour tout le réseau électrique, un plombier pour la plomberie, un menuisier pour les cloisons, un technicien réseau pour l'informatique. Chacun travaille dans son domaine, produit son rapport de travail, et un chef de chantier coordonne l'ensemble. Les Nested Stacks fonctionnent de la même façon : chaque module (réseau, sécurité, base de données, application) est un template indépendant géré par une équipe différente, et une stack parente coordonne tout le monde.
Quand une infrastructure devient complexe (VPC, bases de données, applications, sécurité...), regrouper tout dans un seul template devient ingérable. Les Nested Stacks (stacks imbriquées) permettent de découper l'infrastructure en modules réutilisables, chacun dans son propre template.
Architecture en couches avec les Nested Stacks
infrastructure/ ├── stack-parent.yaml # Stack racine — orchestre tout ├── modules/ │ ├── reseau.yaml # VPC, subnets, Internet Gateway │ ├── securite.yaml # Security Groups, IAM Roles │ ├── base-de-donnees.yaml # RDS, cache ElastiCache │ └── application.yaml # EC2, Load Balancer, Auto Scaling
La stack parent qui référence les modules
AWSTemplateFormatVersion: "2010-09-09"
Description: "Stack parent — orchestre toute l'infrastructure"
Parameters:
Environnement:
Type: String
AllowedValues: [dev, prod]
URLTemplates:
Type: String
Description: "URL S3 de base où sont stockés les templates"
Default: "https://s3.amazonaws.com/mon-bucket-templates/v1"
Resources:
# Module réseau
StackReseau:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub "${URLTemplates}/reseau.yaml"
Parameters:
Environnement: !Ref Environnement
CIDRVpc: "10.0.0.0/16"
TimeoutInMinutes: 15
# Module sécurité — dépend du réseau
StackSecurite:
Type: AWS::CloudFormation::Stack
DependsOn: StackReseau
Properties:
TemplateURL: !Sub "${URLTemplates}/securite.yaml"
Parameters:
Environnement: !Ref Environnement
VpcId: !GetAtt StackReseau.Outputs.VpcId
# Module base de données
StackBDD:
Type: AWS::CloudFormation::Stack
DependsOn: StackSecurite
Properties:
TemplateURL: !Sub "${URLTemplates}/base-de-donnees.yaml"
Parameters:
Environnement: !Ref Environnement
VpcId: !GetAtt StackReseau.Outputs.VpcId
SubnetIds: !GetAtt StackReseau.Outputs.SubnetsPrives
SGBaseDeDonnees: !GetAtt StackSecurite.Outputs.SGBaseDeDonnees
TimeoutInMinutes: 30
# Module application
StackApplication:
Type: AWS::CloudFormation::Stack
DependsOn: StackBDD
Properties:
TemplateURL: !Sub "${URLTemplates}/application.yaml"
Parameters:
Environnement: !Ref Environnement
VpcId: !GetAtt StackReseau.Outputs.VpcId
SubnetPublics: !GetAtt StackReseau.Outputs.SubnetsPublics
URLBDD: !GetAtt StackBDD.Outputs.EndpointBDD
SGApplication: !GetAtt StackSecurite.Outputs.SGApplication
Outputs:
URLApplication:
Description: "URL du Load Balancer de l'application"
Value: !GetAtt StackApplication.Outputs.URLLoadBalancerExemple du template module reseau.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "Module réseau — VPC, subnets publics et privés"
Parameters:
Environnement:
Type: String
CIDRVpc:
Type: String
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref CIDRVpc
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub "vpc-${Environnement}"
SubnetPublic1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.1.0/24"
AvailabilityZone: !Select [0, !GetAZs ""]
MapPublicIpOnLaunch: true
SubnetPrive1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.10.0/24"
AvailabilityZone: !Select [0, !GetAZs ""]
Outputs:
VpcId:
Value: !Ref VPC
Export:
Name: !Sub "${AWS::StackName}-VpcId"
SubnetsPublics:
Value: !Join [",", [!Ref SubnetPublic1]]
Export:
Name: !Sub "${AWS::StackName}-SubnetsPublics"
SubnetsPrives:
Value: !Join [",", [!Ref SubnetPrive1]]
Export:
Name: !Sub "${AWS::StackName}-SubnetsPrives"Déployer avec les templates stockés dans S3
# Uploader les templates dans S3 d'abord
aws s3 sync ./modules/ s3://mon-bucket-templates/v1/ --exclude "*.md"
# Déployer la stack parent
aws cloudformation deploy \
--stack-name infra-prod \
--template-file stack-parent.yaml \
--parameter-overrides \
Environnement=prod \
URLTemplates=https://s3.amazonaws.com/mon-bucket-templates/v1 \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM2. StackSets — déployer sur plusieurs comptes et régions
Imaginez une chaîne de restaurants qui ouvre des succursales dans le monde entier. Le directeur général crée une recette de menu standard, une charte graphique, et des procédures de fonctionnement qui s'appliquent dans tous les restaurants, qu'ils soient à Paris, New York ou Tokyo. Quand une nouvelle règle est ajoutée (nouvelle allergie à afficher, nouveau règlement sanitaire), elle est appliquée simultanément dans tous les restaurants de la chaîne en une seule décision centrale. Les StackSets fonctionnent pareil : vous définissez votre infrastructure une seule fois et vous la déployez dans tous vos comptes AWS et toutes vos régions en une seule opération.
Les StackSets permettent de déployer le même template CloudFormation dans plusieurs comptes AWS et/ou plusieurs régions en une seule opération. C'est l'outil idéal pour les organisations multi-comptes (Landing Zone, Control Tower).
Cas d'usage typiques
Gouvernance centralisée
Déployer des règles AWS Config, CloudTrail, GuardDuty dans tous les comptes de l'organisation automatiquement.
Conformité uniforme
Appliquer les mêmes politiques IAM, groupes de sécurité de base et notifications d'alerte dans chaque compte.
Multi-région
Déployer une infrastructure identique dans us-east-1, eu-west-1 et ap-southeast-1 pour la redondance globale.
Prérequis : configurer les permissions
# Deux modes de fonctionnement : # Mode 1 : Self-Managed (rôles IAM manuels dans chaque compte) # Créer AWSCloudFormationStackSetAdministrationRole dans le compte admin # Créer AWSCloudFormationStackSetExecutionRole dans chaque compte cible # Mode 2 : Service-Managed (via AWS Organizations — recommandé) # Activer la confiance avec Organizations dans CloudFormation aws organizations enable-aws-service-access \ --service-principal cloudformation.amazonaws.com
Créer et déployer un StackSet
Déployer et gérer des applications sur EKS
Chapitre 08 — Kubernetes sur AWS EKS | AWS DevOps Infrastructure as Code
1. Déployer une application — Deployment YAML
Un Deployment Kubernetes, c'est comme une chaîne de fast food. Vous définissez combien de "comptoirs" (replicas) vous voulez ouverts en même temps. Si l'un tombe en panne, Kubernetes en ouvre un nouveau automatiquement sans que les clients s'en aperçoivent. Quand vous voulez changer le menu (nouvelle version de l'image), Kubernetes met à jour les comptoirs un par un (rolling update) pour ne jamais fermer tous les comptoirs en même temps. Si le nouveau menu ne plaît pas, on peut revenir à l'ancien menu immédiatement (rollback).
Un Deployment Kubernetes déclare l'état désiré de votre application : quelle image utiliser, combien de réplicas, comment effectuer les mises à jour. Kubernetes maintient cet état en permanence.
Deployment complet avec toutes les bonnes pratiques
apiVersion: apps/v1
kind: Deployment
metadata:
name: mon-api-fastapi
namespace: mon-application
labels:
app: mon-api-fastapi
version: "1.0.0"
equipe: backend
spec:
replicas: 3
selector:
matchLabels:
app: mon-api-fastapi
# Stratégie de déploiement rolling update
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # Au plus 1 Pod indisponible pendant la mise à jour
maxSurge: 1 # Au plus 1 Pod en surplus pendant la mise à jour
template:
metadata:
labels:
app: mon-api-fastapi
version: "1.0.0"
spec:
serviceAccountName: sa-mon-api # IRSA — IAM Role for Service Account
terminationGracePeriodSeconds: 30
# Sécurité au niveau du Pod
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- name: mon-api-fastapi
image: 123456789012.dkr.ecr.ca-central-1.amazonaws.com/mon-api-fastapi:1.0.0
ports:
- containerPort: 8080
protocol: TCP
# Limites de ressources obligatoires en production
resources:
requests:
cpu: "250m" # 0.25 vCPU garanti
memory: "256Mi" # 256 Mo garantis
limits:
cpu: "500m" # Maximum 0.5 vCPU
memory: "512Mi" # Maximum 512 Mo
# Variables d'environnement depuis ConfigMap et Secret
env:
- name: ENVIRONNEMENT
value: production
- name: PORT
value: "8080"
envFrom:
- configMapRef:
name: config-mon-api
- secretRef:
name: secrets-mon-api
# Sondes de santé
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
startupProbe:
httpGet:
path: /health
port: 8080
failureThreshold: 30
periodSeconds: 5
# Sécurité du conteneur
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
# Distribution entre les zones de disponibilité
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: mon-api-fastapiCommandes de déploiement essentielles
# Appliquer le manifeste kubectl apply -f deployment.yaml -n mon-application # Suivre le déploiement en temps réel kubectl rollout status deployment/mon-api-fastapi -n mon-application # Voir l'historique des déploiements kubectl rollout history deployment/mon-api-fastapi -n mon-application # Mettre à jour l'image (déclenche un rolling update) kubectl set image deployment/mon-api-fastapi \ mon-api-fastapi=123456789012.dkr.ecr.ca-central-1.amazonaws.com/mon-api-fastapi:1.1.0 \ -n mon-application # Revenir à la version précédente (rollback) kubectl rollout undo deployment/mon-api-fastapi -n mon-application # Revenir à une révision spécifique kubectl rollout undo deployment/mon-api-fastapi --to-revision=2 -n mon-application
2. Services Kubernetes : ClusterIP, NodePort, LoadBalancer
Dans Kubernetes, les Services sont comme des adresses postales stables dans un immeuble dont les locataires changent souvent. ClusterIP, c'est un bureau interne dans l'immeuble : personne de l'extérieur ne peut y accéder, c'est pour la communication entre employés. LoadBalancer, c'est la porte d'entrée principale de l'immeuble avec un agent de sécurité (le Load Balancer AWS) qui dirige les visiteurs extérieurs vers le bon bureau disponible. Même si les locataires changent (les Pods redémarrent), l'adresse de l'immeuble reste la même.
Un Service expose un ensemble de Pods via une IP stable et un nom DNS interne, indépendamment du cycle de vie des Pods individuels.
| Type | Accessibilité | Cas d'usage |
|---|---|---|
| ClusterIP | Uniquement à l'intérieur du cluster | Communication inter-services (base de données, cache) |
| NodePort | Depuis l'extérieur via l'IP du Node + un port fixe (30000-32767) | Tests, développement (pas recommandé en production) |
| LoadBalancer | Depuis l'extérieur via un Load Balancer AWS (CLB/NLB) provisionné automatiquement | Exposer un service directement (sans Ingress) |
| ExternalName | Résout vers un nom DNS externe | Accéder à des services RDS, ElastiCache via un nom interne |
---
# Service ClusterIP — pour la communication interne
apiVersion: v1
kind: Service
metadata:
name: svc-mon-api
namespace: mon-application
labels:
app: mon-api-fastapi
spec:
type: ClusterIP
selector:
app: mon-api-fastapi # Correspond aux labels du Deployment
ports:
- name: http
port: 80 # Port du Service (interne)
targetPort: 8080 # Port du conteneur
protocol: TCP
---
# Service LoadBalancer — expose via un NLB AWS
apiVersion: v1
kind: Service
metadata:
name: svc-mon-api-public
namespace: mon-application
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
spec:
type: LoadBalancer
selector:
app: mon-api-fastapi
ports:
- name: http
port: 80
targetPort: 80803. ConfigMaps et Secrets Kubernetes
ConfigMap — configuration non sensible
apiVersion: v1
kind: ConfigMap
metadata:
name: config-mon-api
namespace: mon-application
data:
# Variables d'environnement
LOG_LEVEL: "info"
WORKERS: "4"
TIMEOUT: "30"
DATABASE_HOST: "rds-mon-app.ca-central-1.rds.amazonaws.com"
DATABASE_NAME: "production"
# Fichier de configuration complet
application.yaml: |
server:
host: 0.0.0.0
port: 8080
database:
pool_size: 10
max_overflow: 5
cache:
backend: redis
ttl: 300Secret Kubernetes
apiVersion: v1 kind: Secret metadata: name: secrets-mon-api namespace: mon-application type: Opaque stringData: # stringData accepte les valeurs en clair — K8s les encode en base64 automatiquement DATABASE_PASSWORD: "MonMotDePasseSecret" API_KEY: "sk-abc123..." JWT_SECRET: "ma-cle-jwt-super-secrete"
External Secrets Operator — synchroniser depuis Secrets Manager
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: secrets-aws-synchronises
namespace: mon-application
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: secrets-mon-api # Nom du Secret Kubernetes à créer
creationPolicy: Owner
data:
- secretKey: DATABASE_PASSWORD
remoteRef:
key: "mon-app/production/secrets"
property: "database_password"
- secretKey: API_KEY
remoteRef:
key: "mon-app/production/secrets"
property: "api_key"Cet article couvre les extraits les plus utiles — le cours complet AWS DevOps Infrastructure Code (10 chapitres, 39 leçons, exercices corrigés et projet final) t'emmène jusqu'au bout.
./acceder-au-cours-complet cours gratuit : Maîtriser Claude CodeFAQ
Combien de temps pour apprendre AWS DevOps Infrastructure Code ?
Faut-il des prérequis ?
Par où commencer concrètement ?
📬 Tu veux recevoir ce type de guide chaque semaine ? Abonne-toi gratuitement — code réel, zéro blabla.