đ„ AWS Lambda (Serverless Compute)
Guide complet IDEO-Lab : FaaS, Triggers (API GW, S3, SQS), Runtimes, IAM Roles, Cold Starts & VPC.
Concept : Serverless (FaaS)
Function-as-a-Service. Zéro serveur à gérer (Pas d'OS, pas de Patchs).
Serverless FaaSConcepts Fondamentaux de Lambda
Concepts Fondamentaux de Lambda.
Principes FondementsConcept : ModĂšle ĂvĂ©nementiel
Une fonction Lambda ne "tourne" pas. Elle est dĂ©clenchĂ©e (Triggered) par un ĂvĂ©nement.
Event-Driven TriggerConcept : Runtimes & Handler
L'environnement (Python, Node, Java...). Le "Handler" est le point d'entrée.
Python Node.js HandlerConfig 1 : Execution Role (IAM)
(Crucial) La permission (IAM Role) que la fonction "assume" pour tourner.
IAM Role PermissionsConfig 2 : Mémoire (RAM)
De 128MB à 10GB. (Plus de RAM = Plus de vCPU alloué = Plus rapide).
Memory vCPUConfig 3 : Timeout (Durée)
Le temps max d'exécution. (Défaut: 3 sec, Max: 900 sec (15 min)).
Timeout 900 secTrigger 1 : API Gateway (Synchrone)
(API REST) Invoque la fonction (via HTTP POST/GET) et attend la réponse.
API Gateway SynchroneTrigger 2 : S3 (Asynchrone)
(Push) S3 (Event) invoque la fonction (s3:ObjectCreated:*) et n'attend pas la réponse.
Trigger 3 : SQS (Poll)
(Batch) Lambda "poll" (interroge) la file SQS et traite les messages (par lots).
SQS Event Source MappingScaling : Horizontal Massif
1000 Invocations (simultanées) = 1000 copies (conteneurs) de la fonction.
Horizontal ScalingScaling : Cold Start vs Warm Start
(Crucial) Démarrage à Froid (Init + Invoke) vs Démarrage à Chaud (Invoke).
Cold Start Warm StartScaling : Concurrency (Limite)
Limite (Défaut 1000/compte). (Reserved vs Provisioned Concurrency).
Concurrency ThrottlingRéseau : Lambda dans VPC (Privé)
(Le PiÚge) Requis pour accéder à RDS/ElastiCache (privés).
VPC RDSRéseau : VPC ENI (Hyperplane)
(Moderne) L'ENI (Carte Réseau) est partagée (Hyperplane). (Cold Start VPC fixé !).
Hyperplane ENI VPC Cold StartRéseau : AccÚs Internet (VPC)
Si Lambda (VPC) doit appeler une API (ex: Stripe), il lui faut un NAT Gateway.
NAT Gateway Subnet PrivéDéploiement 1 : ZIP (.zip)
Package (code.py + libs/). Max 250MB (dézippé).
Déploiement 2 : Layers (Dépendances)
Package (ex: pandas, numpy) séparé (partagé) (monté /opt).
Déploiement 3 : Container (ECR)
Package (Image Docker) (jusqu'Ă 10GB). (Base Image "Runtime Interface Client").
Container Image ECRMonitoring 1 : CloudWatch Logs
(Automatique) Tout print() / console.log() va dans un Log Group.
Monitoring 2 : CloudWatch Metrics
(Automatique) Invocations, Errors, Duration, Throttles.
Monitoring 3 : AWS X-Ray (Trace)
(Tracing) Voir la cascade (ex: API GW (50ms) -> Lambda (300ms) -> DynamoDB (80ms)).
X-Ray Tracing6.1. Le "Cold Start" (Démarrage à Froid)
Le Cold Start est le principal dĂ©fi de performance en Serverless. Il survient lorsqu'une requĂȘte arrive et qu'aucun conteneur d'exĂ©cution (Execution Environment) n'est **chaud (Warm)** et disponible.
Le Cycle de Vie de l'Environnement d'Exécution
| Phase | Action (Cold Start) | Durée / Facturation |
|---|---|---|
| **1. Init (Allocation/Configuration)** | Allocation de la micro-VM Firecracker, téléchargement du package ZIP/Container, démarrage du Runtime (JVM, Python Interpreter). | **Facturation GRATUITE (jusqu'à 10 secondes)**. C'est ici que la latence est la plus élevée. |
| **2. Invoke (Invocation)** | Exécution du code **Handler** (le point d'entrée de la fonction). | **Facturation PAYANTE** (à la milliseconde). |
| **Warm Start (Réutilisation)** | Le conteneur est réutilisé. Seule la phase **Invoke** est exécutée. | Latence minimale, coût d'exécution réduit. |
Optimisation des Variables d'Environnement et Connexions
Pour bĂ©nĂ©ficier au maximum du Warm Start, toutes les opĂ©rations coĂ»teuses (imports lourds, initialisation de clients Boto3, connexion Ă une BDD) doivent ĂȘtre placĂ©es dans le **scope global** (en dehors du Handler) pour s'exĂ©cuter uniquement lors de la phase **Init**.
# BONNE PRATIQUE : Connexion BDD hors Handler
# Cette ligne s'exécute 1 fois (Init Phase)
DB_CONNECTION = connect_to_database()
def lambda_handler(event, context):
# Cette ligne est réutilisée (Invoke Phase)
result = DB_CONNECTION.query(...)
return result
6.3. Concurrency Model (ModĂšle de Concurrence)
La concurrence définit le nombre de conteneurs (fonctions) qui peuvent s'exécuter simultanément pour votre compte/région (limite par défaut : 1000).
| ModÚle | Mécanisme | Coût |
|---|---|---|
| **Unreserved (Défaut)** | Puise dans le pool de concurrence non réservé restant au compte. | Payé à l'usage. Risque de **Throttling (Erreur 429)** si le compte atteint sa limite. |
| **Reserved Concurrency** | Vous réservez un nombre de slots (ex: 50) pour une fonction critique, garantissant sa scalabilité. | Gratuit. Garanti l'accÚs, mais peut **throttler** les autres fonctions. |
| **Provisioned Concurrency (PC)** | Maintient un nombre de conteneurs **prĂ©-chauffĂ©s** (Warm) 24/7 (Init phase dĂ©jĂ terminĂ©e). | **Payant Ă l'heure** pour le temps oĂč le PC est maintenu (mĂȘme sans invocation). **Ălimine le Cold Start.** |
Burst Limits (Limites de Rafale)
C'est la vitesse Ă laquelle Lambda peut crĂ©er de nouveaux conteneurs (Cold Start) pour gĂ©rer un pic de trafic soudain (le rate limit de la scalabilitĂ©). AWS gĂšre cette limite pour empĂȘcher la saturation des autres services (comme l'API SSM ou la BDD). Si cette limite est dĂ©passĂ©e, vous subissez Ă©galement du Throttling (429).
6.4. Isolation et Sécurité via Micro-VM Firecracker
Cloud computing repose sur la mutualisation des ressources. Firecracker est la technologie qui garantit la sĂ©curitĂ© et l'isolation entre les fonctions des diffĂ©rents clients sur le mĂȘme serveur physique.
Firecracker : Le Micro-Hyperviseur
Firecracker est un **Virtual Machine Monitor (VMM)** ultra-léger basé sur KVM, développé par AWS.
- **Isolation MatĂ©rielle :** Chaque fonction (mĂȘme de deux clients diffĂ©rents) est encapsulĂ©e dans sa propre **micro-VM**. Cela offre une isolation de sĂ©curitĂ© de niveau Hyperviseur, supĂ©rieure Ă l'isolation par conteneur classique (Docker/Cgroups).
- **Minimalisme :** Firecracker est minimaliste (moins de code = moins de surface d'attaque). Il ne gÚre que le strict nécessaire (mémoire, vCPU, ENI virtuelle).
- **Performance :** Le temps de démarrage d'une micro-VM est trÚs rapide (quelques centaines de millisecondes), minimisant l'impact de la latence du Cold Start (6.1).
5.1. Méthodes de Packaging : ZIP vs. Docker Container
AWS offre deux formats principaux pour empaqueter et déployer le code de votre fonction.
| CritĂšre | Package ZIP (Archive) | Image Conteneur (ECR) |
|---|---|---|
| **Taille Max.** | **250 MB** (code + dépendances). Suffisant pour la plupart des microservices. | **10 GB** (Image non compressée). Idéal pour le Machine Learning ou les dépendances lourdes. |
| **Workflow** | Upload direct via Console/CLI/SAM/Serverless Framework. | Build Docker -> Push vers **ECR** (Elastic Container Registry) -> Déploiement. |
| **Flexibilité** | Doit utiliser un **Runtime Managé** par AWS (Node.js, Python, Java, etc.). | Supporte **tout langage** ou framework (PHP, Rust, etc.) via le **Runtime Interface Client (RIC)**. |
Diagramme de Flux (Container)
Le flux Conteneur ajoute une couche ECR et Docker au processus de CI/CD Lambda.
[ Code Local ]
|
v
[ Docker Build ] --> [ ECR (Stockage Image) ] --> [ AWS Lambda Service (Pull) ]
|
v
[ Exécution ]
5.2. Layers Lambda (Librairies Partagées)
Les **Layers** permettent d'isoler et de partager des dépendances (librairies) lourdes ou communes entre plusieurs fonctions Lambda. Le code de la fonction devient plus léger et le déploiement est plus rapide.
Avantages Clés
- **Réduction de la Taille du Package :** Le package ZIP de la fonction ne contient que le code métier, pas les dépendances (ex: Numpy, Pandas).
- **Standardisation :** Toutes les fonctions peuvent utiliser la mĂȘme version d'une librairie (ex: Logger personnalisĂ©).
- **RĂ©utilisation :** Un Layer peut ĂȘtre attachĂ© Ă **plusieurs** fonctions dans le mĂȘme compte et rĂ©gion.
- **Patching Centralisé :** Mettre à jour la dépendance dans le Layer met à jour toutes les fonctions l'utilisant.
Structure du Layer (Python)
Le Layer doit respecter une structure de répertoire précise pour que Lambda le trouve au runtime.
# Structure du ZIP du Layer
mon_layer.zip
âââ python/
âââ lib/
â âââ pythonX.X/
â âââ site-packages/
â âââ [votre librairie]
âââ [votre librairie custom.py]
5.3. Gestion des Variables dâEnvironnement et Secrets
Les variables d'environnement (`Env Vars`) sont utilisées pour la configuration dynamique (ex: nom de la table DynamoDB, région).
RÚgles de Sécurité (Séparation des Secrets)
**Ne jamais stocker de secrets (mots de passe, clés API) directement en clair dans les variables d'environnement.**
| Type d'Information | Méthode (Standard) | Sécurité |
|---|---|---|
| **Configuration Non-Sensible** | Variables d'Environnement (`process.env.MY_VAR`) | Chiffrées au repos par AWS KMS (par défaut ou CMK). |
| **Secrets (Mots de Passe, API Keys)** | **Secrets Manager** ou **SSM Parameter Store (Secure String)** | Doivent ĂȘtre rĂ©cupĂ©rĂ©s au runtime par la fonction (nĂ©cessite la permission IAM `secretsmanager:GetSecretValue`). |
Code d'AccĂšs Ă un Secret (Python)
Récupération d'un secret depuis Secrets Manager :
import json
import boto3
def get_secret():
client = boto3.client('secretsmanager')
response = client.get_secret_value(SecretId='mon_secret_api')
# Le secret est renvoyé sous forme de string JSON
if 'SecretString' in response:
return json.loads(response['SecretString'])
return None
5.4. Versioning, Aliases et Déploiement Canari (CI/CD)
Le **Versioning** et les **Aliases** sont essentiels pour la gestion du cycle de vie des applications et le déploiement sans interruption (Zero Downtime).
Versioning et Aliases
- **Version (`$LATEST` et Nombres) :** Chaque déploiement (ZIP ou Container) crée une version immuable. `$LATEST` est la version en cours de développement.
- **Alias :** Un pointeur mutable vers une version spécifique (ou un mélange de versions). Ils sont utilisés pour séparer les environnements (DEV, STAGE, PROD).
Déploiement Canari (Traffic Shifting)
Un Alias peut pointer vers **deux versions différentes** avec une pondération de trafic. C'est la base du déploiement **Canari (Canary)** ou du **Blue/Green**.
# L'Alias "PROD" pointe vers :
# 90% du trafic -> Version: 15 (Ancienne)
# 10% du trafic -> Version: 16 (Nouvelle)
#
# Si la V16 est stable, on fait passer le trafic Ă 100% sur la V16.
Intégration CI/CD
Les outils de déploiement et d'orchestration modernes gÚrent le Versioning/Alias automatiquement :
- **AWS CodeDeploy :** GĂšre la transition de trafic (Traffic Shifting) entre les versions d'Alias (Canary, Linear, AllAtOnce).
- **Serverless Framework (ou SAM) :** Frameworks qui simplifient la configuration du packaging (ZIP/Layers/Containers) et le déploiement (Mise à jour d'Alias).
- **GitHub Actions / CodePipeline :** Peuvent déclencher les commandes de Serverless/SAM aprÚs un Merge dans la branche `main`.
4.1. IAM Role (RÎle d'Exécution) & POLP
La fonction Lambda interagit avec d'autres services (S3, DynamoDB, CloudWatch) en **assumant (endossant)** un **RÎle d'Exécution IAM**.
Ce rĂŽle doit ĂȘtre configurĂ© avec le **Principe du Moindre PrivilĂšge (POLP - Principle Of Least Privilege)** : n'accorder que les permissions **strictement nĂ©cessaires** pour effectuer la tĂąche de la fonction.
Les 3 Composants du RĂŽle
| Composant | RĂŽle | Exemple (Action) |
|---|---|---|
| **Trust Policy** | **Permet au service Lambda d'endosser ce rĂŽle.** (Obligatoire) | "Principal": {"Service": "lambda.amazonaws.com"} |
| **Basic Execution Policy** | **Permissions minimales pour fonctionner :** écrire les logs d'exécution sur CloudWatch. | logs:CreateLogGroup, logs:PutLogEvents |
| **Custom Policy** | **AccÚs aux cibles (Target) :** (S3, DynamoDB, Secrets Manager). (POLP s'applique ici). | s3:GetObject (sur un bucket spécifique), dynamodb:PutItem (sur une table spécifique). |
Exemple de Policy (Least Privilege)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mon-bucket-source/*"
},
{
"Effect": "Allow",
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:eu-west-3:1234567890:ma-file-queue"
}
]
}4.2. ContrĂŽle dâAccĂšs via Resource Policies
La **Resource Policy** est une politique IAM attachĂ©e **directement Ă la ressource Lambda** elle-mĂȘme. Elle ne contrĂŽle pas ce que la fonction fait (ça, c'est l'Execution Role), mais **qui** a le droit de l'invoquer (le Trigger).
Usage Principal : Le Filtre des Triggers
C'est cette politique qui permet à un service externe (API Gateway, S3, EventBridge) de "faire confiance" à la fonction Lambda pour l'invoquer (appelé `AddPermission` dans la console/CLI).
# Exemple de Resource Policy (Attachée à la fonction Lambda)
{
"Statement": [
{
"Sid": "AllowAPIGatewayInvocation",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:eu-west-3:1234567890:function:MaFonction",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:eu-west-3:1234567890:abcdef123/*/*"
}
}
}
]
}
Dans cet exemple, seule l'instance **spĂ©cifique** d'API Gateway identifiĂ©e par son ARN est autorisĂ©e Ă appeler la fonction (empĂȘchant un autre utilisateur AWS d'appeler cette Lambda via son propre API Gateway).
4.3. Encryption At Rest (Chiffrement au Repos - KMS)
Le chiffrement au repos protÚge les données stockées dans AWS lorsque la fonction n'est pas en cours d'exécution.
Qu'est-ce qui est chiffré ?
- **Code de la Fonction :** Le fichier `.zip` ou l'image conteneur (stockés dans S3 ou ECR managé par AWS) est chiffré.
- **Variables d'Environnement :** Les clés-valeurs stockées (ex:
DB_HOST) sont chiffrées. - **SystÚme de Fichiers `/tmp` :** Les données temporaires (jusqu'à 10GB) dans l'environnement `/tmp` sont chiffrées.
Clés KMS (Key Management Service)
Vous avez le choix entre deux types de chiffrement pour les données au repos :
| Type de Clé | RÎle | Audit |
|---|---|---|
| **AWS-Owned Key** | Chiffrement par défaut et automatique (gratuit). | Aucun audit n'est disponible (la clé est gérée par AWS). |
| **Customer Managed Key (CMK)** | Clé créée et gérée dans votre compte via KMS. | **Recommandé :** Vous contrÎlez l'accÚs via la **Key Policy** et auditez toutes les utilisations (chiffrement/déchiffrement) via **CloudTrail**. |
4.4. Encryption In Transit (Chiffrement en Transit - TLS)
Le chiffrement en transit protÚge les données lorsqu'elles se déplacent entre services (client-serveur ou serveur-serveur).
Entre le Client et Lambda (via API Gateway)
La communication (ex: navigateur -> API) est sécurisée par **TLS/SSL (HTTPS)**. Le certificat est généralement géré par **AWS Certificate Manager (ACM)** et installé sur l'**API Gateway** ou l'**ALB** qui expose la fonction.
Entre Lambda et les Services Cibles
Toutes les communications entre la fonction Lambda et les services AWS (S3, DynamoDB, SQS, KMS) se font **automatiquement via TLS (Port 443)** sur le réseau AWS.
MĂȘme si la fonction Lambda est dans un **VPC (Subnet PrivĂ©)** et utilise des **VPC Endpoints** pour accĂ©der Ă S3/DynamoDB, la connexion est chiffrĂ©e de bout en bout sur le backbone AWS.
Audit et Exigences
- **Exigences Externes :** Pour les appels à des APIs externes (ex: Stripe), le code doit **appliquer TLS 1.2 ou supérieur** (si l'API cible l'exige).
- **Rotation Certificats :** Les certificats cÎté serveur (pour les appels AWS) sont gérés et rotatifs par AWS. Le développeur n'a pas à s'en soucier.
1.1. Quâest-ce quâAWS Lambda ?
AWS Lambda est le service de **Function as a Service (FaaS)** leader du marché. Il permet d'exécuter votre code sans que vous ayez à vous soucier de l'infrastructure sous-jacente.
Lambda vs. EC2 (IaaS)
La distinction est fondamentale pour comprendre le gain opérationnel (Ops) :
| CritĂšre | EC2 (Infrastructure as a Service) | Lambda (Function as a Service) |
|---|---|---|
| **Unité de Déploiement** | Un serveur complet (Machine Virtuelle, VM). | Une fonction de code (Handler). |
| **Gestion du Serveur** | **Responsabilité du Client** (OS, Patching, Sécurité). | **Géré par AWS** (Serveur, OS, Patching, Scaling). |
| **Facturation** | Ă l'heure / Ă la seconde, tant que la VM est `Running`. | **Au temps de calcul effectif** (Ă la milliseconde) + Nombre d'invocations. |
| **Scaling** | Manuel ou via **Auto Scaling Group (ASG)** (lent : 5-10 min). | Automatique et instantané (par événement). |
1.2. La Philosophie du âServerlessâ
Le terme "Serverless" signifie que les tùches opérationnelles lourdes sont déplacées vers le fournisseur cloud (AWS), permettant aux développeurs de se concentrer sur la **logique métier (Business Logic)**.
- **Pas de Serveur Ă Provisionner :** AWS gĂšre l'allocation des ressources de calcul au moment de l'invocation.
- **Zéro Maintenance SystÚme :** Le patching de l'OS et des runtimes est la responsabilité d'AWS.
- **Pas de Scaling Manuel :** Le service s'adapte automatiquement Ă 1 ou 10 000 requĂȘtes concurrentes (horizontal scaling).
- **Concentration sur le Code :** Le développeur s'occupe uniquement du code de la fonction et des configurations (mémoire, timeout).
Le ModÚle d'Exécution (Event-Driven)
Lambda est un modÚle piloté par les événements (Event-Driven). La fonction "dort" (coût zéro) et est réveillée par un **Trigger**.
# Représentation du Flux
(ĂvĂ©nement/Trigger) ---> (AWS Lambda Service) ---> (Conteneur d'ExĂ©cution)
|
v
[ Votre Code ]
1.3. Les Langages (Runtimes) Supportés
Lambda fournit des **runtimes managés** pour les langages les plus populaires, ainsi que des options personnalisées pour les besoins spécifiques.
| Catégorie | Langages (Runtimes) | Notes (Performance) |
|---|---|---|
| **Scripting/Web** | Node.js (LTS), Python (3.x) | TrÚs rapides au **Cold Start** (démarrage à froid). Idéal pour les APIs et les tùches I/O. |
| **Compilation** | Java (LTS), Go, .NET | **Go** et les langages compilés sont les plus rapides au Cold Start (quasi-instantané). Java est plus lent (JVM), mais trÚs stable en Warm Start. |
| **Custom & Images** | **Images Conteneur**, **Custom Runtime** (ex: PHP, Rust) | Permet de dépasser la limite de taille (10 GB) ou d'utiliser des langages non supportés nativement (via l'API **RIC - Runtime Interface Client**). |
1.4. Cas dâUsage Typiques (UbiquitĂ© de Lambda)
Lambda est la "colle" (Glue Code) du cloud AWS, utilisée pour lier les services entre eux ou pour créer des applications légÚres et scalables.
| Cas d'Usage | RÎle de Lambda | Services Associés (Triggers/Targets) |
|---|---|---|
| **API Serverless** | Le backend logique de chaque route HTTP (ex: POST /user). | API Gateway, Load Balancers (ALB), DynamoDB/RDS. |
| **Traitement dâĂvĂ©nements** | ExĂ©cution d'une tĂąche asynchrone en rĂ©action Ă une modification de donnĂ©es. | S3 (ObjectCreated), DynamoDB Streams, Kinesis. |
| **Pipelines ETL** | Transformation, nettoyage et déplacement de données. | AWS Glue (Orchestration), S3 (Stockage), Aurora/Redshift (Cible). |
| **Automatisation dâInfrastructure** | Scripts d'administration (Ops) Ă dĂ©clenchement temporel ou Ă©vĂ©nementiel. | EventBridge Scheduler (Cron), CloudWatch Alarms, SNS. |
| **Backend IoT** | Ingestion et traitement en temps réel des données provenant de milliers de capteurs. | IoT Core, Kinesis Data Streams. |
5.1. Structure dâun Projet Lambda
La structure de votre package de déploiement (.zip) dépend de vos dépendances.
Python (Exemple)
Cas 1 : Sans dépendances (juste boto3, qui est inclus)
(lambda_function.zip)
âââ app.py (Contient votre "lambda_handler")
Cas 2 : Avec dépendances (ex: requests)
Vous devez installer les libs Ă la racine du zip : pip install requests -t ./package_dir
(lambda_function.zip)
âââ app.py (Contient votre "lambda_handler")
âââ requests/ (La librairie 'requests' installĂ©e)
âââ certifi/ (DĂ©pendance de 'requests')
âââ ...
Node.js (Exemple)
Node.js cherche les dépendances dans node_modules/. (npm install)
(lambda_function.zip)
âââ index.js (Contient votre "handler")
âââ package.json
âââ node_modules/
âââ axios/
âââ ...
5.2. Gestion des Dépendances (Layers vs Bundling)
Comment gérer les "libs" (ex: pandas, numpy, Pillow) ?
Option 1 : Bundling / Packaging (ZIP)
C'est la méthode vue en 5.1. Vous "bundlez" (regroupez) le code ET les dépendances dans un seul fichier .zip.
- Limite : Le .zip décompressé ne doit pas dépasser 250 MB.
- Outils (IaC) : Des outils comme AWS SAM (
sam build) ou Serverless Framework (sls package) automatisent ce "bundling" (lepip install -t ...et lezip) pour vous.
Option 2 : Lambda Layers (Couches)
(Recommandé pour les grosses libs) Une Layer est un .zip séparé (une "couche" du systÚme de fichiers) que Lambda "monte" (attache) dans le dossier /opt de votre fonction au démarrage.
Structure (Python) : Votre .zip de Layer DOIT avoir cette arborescence :
(pandas_layer.zip)
âââ python/
âââ lib/
âââ python3.12/
âââ site-packages/
âââ pandas/
âââ numpy/
Avantages :
- DRY (Don't Repeat Yourself) : Partagez une Layer (
pandas-v1) entre 50 fonctions Lambda. - Déploiement rapide : Votre code (
app.py) ne pĂšse que 2KB (dĂ©ploiement en 1s), mĂȘme si la Layer pĂšse 200MB (car elle ne change pas). - Versioning : Vous pouvez mettre Ă jour la Layer (
pandas-v2) indépendamment du code de la fonction.
5.3. Variables dâEnvironnement
Permet de passer des configurations Ă votre code (os.environ.get('MA_VAR')) sans le "hardcoder".
- Usage (Paramétrage) : Idéal pour différencier les environnements.
- Fonction (Dev) :
TABLE_NAME = "users-dev" - Fonction (Staging) :
TABLE_NAME = "users-staging" - Fonction (Prod) :
TABLE_NAME = "users-prod"
- Fonction (Dev) :
Ne JAMAIS mettre de secrets (mots de passe) en clair !
Mauvaise Pratique : DB_PASSWORD = "Password123!". (Visible en clair par toute personne ayant accĂšs "ReadOnly" Ă la console Lambda).
Bonne Pratique : Stocker les Secrets (SSM / Secrets Manager)
Stockez les secrets dans AWS Secrets Manager (pour les identifiants BDD/RDS) ou SSM Parameter Store (SecureString) (pour les clés d'API).
Flux de code (Bonne Pratique) :
- Variable d'Env :
SECRET_ARN = "arn:aws:secretsmanager:..." - RĂŽle IAM : Donnez Ă la Lambda la permission
secretsmanager:GetSecretValue. - Code (
Init) : Le code (Boto3) utilise leSECRET_ARNpour appeler l'APIGetSecretValueet récupérer le mot de passe en mémoire au démarrage (Cold Start).
import boto3
import os
# (Phase INIT : Exécuté 1 fois au Cold Start)
SECRET_ARN = os.environ.get('SECRET_ARN')
client = boto3.client('secretsmanager')
response = client.get_secret_value(SecretId=SECRET_ARN)
DB_PASSWORD = response['SecretString'] # (Récupéré en mémoire)
def lambda_handler(event, context):
# (Phase INVOKE)
# Utilise DB_PASSWORD (déjà chargé) pour se connecter
conn = connect_to_db(DB_PASSWORD)
...
5.4. Runtimes Gérés vs Images Conteneur
Ce sont les deux façons de packager (5.1) et d'exécuter (2.1) votre fonction.
| CritÚre | Runtimes Gérés (Standard .zip) | Images Conteneur (ECR) |
|---|---|---|
| Package | Archive .zip (Code + Layers) | Image Docker (poussée sur ECR) |
| Limite de Taille | 250 MB (Dézippé, total) | 10 GB |
| Dépendances OS | Non (Limité aux libs incluses dans Amazon Linux 2) | Oui (ContrÎle total, ex: apt-get install ffmpeg) |
| Cold Start (Latence) | TrÚs rapide (Téléchargement .zip optimisé) | Plus lent (Téléchargement de l'image Docker, ex: 5GB) |
| Simplicité | TrÚs simple (Défaut) | Plus complexe (Nécessite Dockerfile, ECR, push...) |
Quand utiliser un Conteneur pour Lambda ?
Utilisez les Runtimes Gérés (.zip) par défaut. N'utilisez les Images Conteneur que si :
- Votre package (Code + Dépendances) dépasse la limite de 250 MB.
- Vous avez besoin de dépendances systÚme (OS) (ex:
apt-get,yum install) qui ne sont pas dans le runtime Amazon Linux 2 de base (ex:ffmpegpour vidéo,tesseractpour OCR). - Vous avez un workload ML/IA (ex: PyTorch, TensorFlow) qui pÚse plusieurs GB.
- Vous voulez une consistance Dev/Prod absolue (l'image Docker locale est la mĂȘme que sur AWS).
4.1. Types de Déclencheurs (Triggers) Principaux
Un déclencheur est un service AWS ou une ressource qui invoque votre fonction Lambda. Le mode d'invocation (Synchrone, Asynchrone, Poll) est la distinction la plus importante.
| ModĂšle d'Invocation | Services (Exemples) | Description du Flux |
|---|---|---|
| Synchrone (Request-Response) | ⹠API Gateway (REST/HTTP) ⹠ALB (Application Load Balancer) ⹠Cognito (Hooks utilisateur) | L'appelant (ex: API GW) attend que Lambda finisse son exécution et récupÚre la réponse (return response;) pour la renvoyer au client (HTTP 200). |
| Asynchrone (Event) | âą S3 (s3:ObjectCreated)âą EventBridge (RĂšgles, ĂvĂ©nements) âą CloudWatch Events (Cron) âą SNS, SES | L'appelant (ex: S3) "lance" la fonction et n'attend pas la rĂ©ponse (Fire-and-Forget). Le service Lambda gĂšre les retries (2x) et la DLQ (Dead Letter Queue) en cas d'Ă©chec. |
| Poll (Event Source Mapping) | ⹠SQS (File d'attente) ⹠DynamoDB Streams (CDC) ⹠Kinesis Data Streams ⹠Kafka (MSK) | Le service Lambda (via un "poller" interne) "lit" (ReceiveMessage) la source, récupÚre un batch (lot) de messages/enregistrements, et invoque votre fonction 1 fois avec ce batch. |
4.2. Invocations Directes (SDK / CLI)
Vous n'ĂȘtes pas obligĂ© d'attendre un Ă©vĂ©nement AWS. Vous pouvez appeler (invoquer) une fonction Lambda vous-mĂȘme, depuis n'importe quel code (ex: Boto3) ou la CLI.
Invocation via SDK (Boto3 - Python)
Vous devez spécifier le InvocationType :
import boto3
import json
client = boto3.client('lambda')
# --- 1. Invocation SYNCHRONE (J'attends la réponse) ---
# (Bloquant, attend le 'return' de la fonction)
response_sync = client.invoke(
FunctionName='ma-fonction-prod',
InvocationType='RequestResponse', # (Défaut)
Payload=json.dumps({'key': 'value'})
)
print(json.loads(response_sync['Payload'].read()))
# Output: {'statusCode': 200, 'body': '...'}
# --- 2. Invocation ASYNCHRONE (Je n'attends pas) ---
# (Non-bloquant, "Fire-and-Forget")
response_async = client.invoke(
FunctionName='ma-fonction-batch',
InvocationType='Event',
Payload=json.dumps({'fichier': 'gros_fichier.csv'})
)
print(response_async['StatusCode'])
# Output: 202 (Accepted)
Invocation via AWS CLI
# Invoquer (Synchrone) et attendre la réponse (dans 'output.json')
aws lambda invoke \
--function-name ma-fonction-prod \
--payload '{"key": "value"}' \
output.json
# Invoquer (Asynchrone) et ne pas attendre
aws lambda invoke \
--function-name ma-fonction-batch \
--invocation-type Event \
--payload '{"fichier": "gros_fichier.csv"}' \
output.json
# (output.json sera vide, status 202)
4.3. Cas d'Usage par Déclencheur
1. S3 : Traitement de fichiers (Génération de vignettes)
L'architecture classique de traitement d'images (ou PDF, CSV, etc.).
- Trigger :
s3:ObjectCreated:*sur le bucketuploads/. - RĂŽle IAM :
s3:GetObject(suruploads/*),s3:PutObject(surthumbnails/*). - Code Lambda : (Python + Layer
Pillow)- RécupÚre le
event['Records'][0]['s3']['object']['key']. - Télécharge l'image (
s3.download_file) vers/tmp/. - Redimensionne l'image (
Pillow.Image.thumbnail). - Uploade le thumbnail (
s3.upload_file) vers le bucketthumbnails/.
- RécupÚre le
2. SQS : Worker Asynchrone (Découplage)
Idéal pour "découpler" une API (rapide) d'un traitement (lent) (ex: envoi d'email, génération de PDF).
(Client) -> [API GW] -> [Lambda (A) - Rapide] ---- (Envoi 1 message) ----> [đš SQS Queue]
|
(Poll ESM)
|
[ đ„ Lambda (B) - Lent ]
|
(Envoi Email SES)
Flux : Lambda (A) (API) ne fait que valider la donnée et l'envoyer à SQS (réponse en 50ms). Lambda (B) (le "Worker") prend le message de SQS (en batch) et prend (ex:) 5 secondes pour se connecter au SMTP (SES) et envoyer l'email. Le client (API) n'attend pas 5 secondes.
3. EventBridge (Scheduler) : Automatisation (Cron)
Remplace les "tĂąches cron" sur un serveur.
- Trigger :
EventBridge Rule->Schedule. - Expression :
cron(0 5 * * ? *)(Tous les jours Ă 5h00 UTC). - Code Lambda : (Python +
boto3)rds_client = boto3.client('rds')rds_client.create_db_snapshot(...)(Faire un backup de la BDD Prod).ec2_client = boto3.client('ec2')ec2_client.stop_instances(...)(ArrĂȘter les EC2 de Dev pour la nuit).
4. API Gateway : Backend d'API / Microservice
Le pattern "Backend Serverless" (Full REST API).
- Trigger :
API Gateway (HTTP API ou REST API). - Route :
GET /users/{id}-> Mappé (Intégration) versLambda:GetUserFunction. - Code Lambda :
- RécupÚre l'ID :
user_id = event['pathParameters']['id']. dynamo_client.get_item(Key={'PK': user_id}).return {'statusCode': 200, 'body': json.dumps(item)}.
- RécupÚre l'ID :
3.1. Lambda dans une Architecture Event-Driven (EDA)
L'architecture "Event-Driven" (PilotĂ©e par les Ă©vĂ©nements) est le cĆur de Lambda. Le principe est le dĂ©couplage : les services ne s'appellent pas directement, ils Ă©mettent des "Ă©vĂ©nements" (faits) et Lambda rĂ©agit.
La fonction Lambda agit comme la "colle" (Glue Code) entre les services AWS.
Flux : Source â Lambda â Cible
(Service Source) (Service "Glue") (Service Cible)
[Ex: S3 (PutObject)] ---- (ĂvĂ©nement JSON) ----> [ đ„ AWS Lambda ]
|
(boto3.client('dynamodb'))
|
v
[Ex: DynamoDB (PutItem)]
Avantages :
- Découplage : S3 (Source) ne sait pas (et n'a pas besoin de savoir) que DynamoDB (Cible) existe. Il ne fait qu'émettre un événement.
- Résilience : Si le service Cible (DynamoDB) est en panne, Lambda peut gérer les "retries" (nouvelles tentatives) ou envoyer l'événement échoué dans une Dead Letter Queue (DLQ) sans bloquer la Source (S3).
- Scalabilité : Si 1000 fichiers sont uploadés sur S3, AWS démarre 1000 Lambdas (concurrentes) pour tout traiter en parallÚle.
3.2. Lambda + API Gateway (Backend API REST / HTTP)
C'est le pattern "Backend Serverless" le plus courant. Il remplace une architecture EC2 + Nginx + Django/Node.js.
(Client Web/Mobile)
|
(HTTP POST /users)
|
v
[ âïž API Gateway ] --- (Route: "POST /users") ---> [ đ„ Lambda (Fonction A) ]
|
(HTTP GET /users/123)
|
v
[ âïž API Gateway ] --- (Route: "GET /users/{id}") --> [ đ„ Lambda (Fonction B) ]
- API Gateway (Le "Routeur") : GĂšre les routes HTTP (
/users,/products), le throttling (limitation de débit), les clés d'API, et (crucialement) l'authentification. - Lambda (La "Logique Métier") : GÚre une seule route (ex:
create_user). Reçoit l'événement (HTTP JSON) et retourne une réponse (HTTP JSON).
Gestion de l'Authentification (par API GW)
- AWS Cognito : (Pour les clients/utilisateurs finaux) API GW vérifie le Token JWT (fourni par Cognito) avant de déclencher Lambda.
- AWS IAM : (Pour les services internes) API GW vérifie la Signature AWS (SigV4) (fournie par un autre service, ex: une EC2) avant de déclencher Lambda.
- Lambda Authorizer : (Custom) API GW appelle une 3Úme Lambda (dédiée à l'auth) pour valider un token (ex: Auth0, OIDC custom) avant de déclencher la Lambda métier.
3.3. Lambda + S3 (Traitement Asynchrone)
Cas d'usage trÚs fréquent pour le traitement de fichiers ("data processing"). L'invocation est asynchrone (S3 ne se soucie pas de si la Lambda réussit ou échoue).
Cas 1 : Traitement d'images (Thumbnails)
- Trigger :
s3:ObjectCreated:*surBucket-A(Filtre Préfixe:uploads/, Suffixe:.jpg). - RÎle IAM Lambda : Doit avoir
s3:GetObject(surBucket-A) ets3:PutObject(surBucket-B). - Code Lambda (Python) :
- Reçoit l'
event(JSON) avec le nom du bucket/clé. - Utilise
boto3.s3.download_file()(vers/tmp/). - Utilise une Layer (ex:
Pillow) pour redimensionner l'image (image.thumbnail(...)). - Utilise
boto3.s3.upload_file()(versBucket-B, cléthumbnails/image_thumb.jpg).
- Reçoit l'
Cas 2 : Transcodage Vidéo / ETL
Une Lambda (max 15 min) est trop courte pour transcoder une vidéo de 2h ou un ETL de 3h.
Architecture (Orchestration) :
(S3 PUT video.mp4) -> (Trigger) -> [ đ„ Lambda (A) ] -> (API Call) -> [ đ€ AWS MediaConvert / AWS Glue (Job) ]
Ici, Lambda (A) ne fait que lancer (démarrer) le "gros" service (MediaConvert/Glue) qui, lui, va tourner 3h.
3.4. Lambda + DynamoDB / RDS (Couche Logique)
Lambda agissant comme la couche "software" (logique métier) devant la couche "données" (base de données).
Lambda en réaction à DynamoDB Streams
C'est le pattern "Change Data Capture (CDC)" ou "Chorégraphie de Microservices".
(Service A - Commande)
|
(Ăcrit dans Table "Orders")
|
(DynamoDB Stream) <-- (Un "journal" de tous les changements)
|
(Poll/Trigger ESM)
|
v
[ đ„ Lambda (Service B - Notification) ]
|
v
[ âïž SES (Envoi Email Confirmation) ]
Flux : Quand un item est INSERTED (Nouvelle commande) dans la table "Orders", le Stream (journal) capture cet événement. Le service Lambda (qui "écoute" ce stream) est invoqué et envoie l'email de confirmation. Le Service A (Commandes) est totalement découplé du Service B (Notifications).
Lambda + RDS (ex: PostgreSQL)
Le PiÚge du VPC : Une base RDS (ex: PostgreSQL) est (par bonne pratique) dans un Subnet Privé (sans accÚs Internet).
Pour que Lambda (ex: API GW) puisse parler Ă RDS, Lambda doit ĂȘtre "attachĂ©e" au mĂȘme VPC (dans les Subnets PrivĂ©s).
Conséquence : La Lambda (étant dans un Subnet Privé) perd son accÚs Internet par défaut. Si elle doit (aussi) appeler une API (ex: Stripe), elle aura besoin d'un NAT Gateway.
Le PiÚge des Connexions (RDS) : Si 1000 Lambdas (concurrentes) démarrent, elles tentent d'ouvrir 1000 connexions (psycopg2.connect()) à RDS, ce qui peut saturer (max_connections) la BDD.
Solution : Utiliser RDS Proxy (un "pooler" de connexion managé).
3.5. Orchestration (EventBridge & Step Functions)
Quand la logique devient complexe, Lambda seul ne suffit pas.
EventBridge (Le "Bus d'ĂvĂ©nements" / ChorĂ©graphie)
Permet un découplage "Many-to-Many". (Routage d'événements).
[Lambda (Service A)] -- (ĂvĂ©nement "UserCreated") --> [ đ EventBridge (Bus) ]
|
(RĂšgle 1: source=User, detail=...)
|
v
[ đ„ Lambda (Service B - Email) ]
Step Functions (L' "Orchestrateur" / Workflow)
Pour gĂ©rer des workflows longs (jusqu'Ă 1 an), avec Ă©tat (stateful), retries, et logique complexe. (Ăvite le "Lambda Hell" : A->B->C).
Vous définissez le workflow en JSON (Amazon States Language) :
{
"StartAt": "ValiderCommande",
"States": {
"ValiderCommande": {
"Type": "Task",
"Resource": "arn:aws:lambda:...",
"Next": "ChoixPaiement"
},
"ChoixPaiement": {
"Type": "Choice",
"Choices": [
{ "Variable": "$.type", "StringEquals": "CB", "Next": "PayerCB" },
{ "Variable": "$.type", "StringEquals": "PayPal", "Next": "PayerPayPal" }
]
},
"PayerCB": { ... (Appelle Lambda B) ... },
...
}
}
Avantages : GÚre l'état, les Try/Catch, les Retry (avec backoff) et les Wait (ex: "Attendre 3 jours") sans qu'une Lambda ne tourne (et ne soit facturée).
3.6. Patterns d'Architecture Fréquents
1. Fan-out (Ăventail)
Un événement (Source) déclenche plusieurs traitements (Cibles) en parallÚle.
Exemple (SNS Fan-out) :
[S3 (Upload Facture)]
|
v
[ đ„ Lambda (A) - Analyse PDF ]
|
v
[ topic (SNS) "FactureAnalysée" ]
|
+--- (Subscription 1) ---> [ đ„ Lambda (B) - Envoi Email Client ]
|
+--- (Subscription 2) ---> [ đ„ Lambda (C) - Sauvegarde RDS (Compta) ]
|
+--- (Subscription 3) ---> [ đš SQS (File d'attente "Archivage") ]
2. Fan-in (Agrégation)
Opposé de Fan-out. Attendre que plusieurs traitements (parallÚles) soient terminés avant de continuer (agréger).
Exemple (Step Functions) : C'est le pattern le plus complexe à gérer (état). Step Functions (3.5) le gÚre nativement avec l'état Parallel.
(Start)
|
(Ătat "Parallel")
|
+--- (Branche A) ---> [ đ„ Lambda (A) - Traite VidĂ©o 1080p ]
|
+--- (Branche B) ---> [ đ„ Lambda (B) - Traite VidĂ©o 720p ]
|
+--- (Branche C) ---> [ đ„ Lambda (C) - Traite VidĂ©o 360p ]
|
(Attend A, B, et C)
|
v
[ đ„ Lambda (D) - AgrĂ©ger & Notifier ]
|
(End)
3. Microservices "Serverless"
C'est la combinaison de tous ces patterns. Chaque "domaine métier" (ex: Commandes, Paiements, Utilisateurs) est un service indépendant, composé de :
- API (Interface) : API Gateway
- Logique (Métier) : Fonctions Lambda
- Ătat (Base de donnĂ©es) : Table DynamoDB
- Communication (ĂvĂ©nements) : EventBridge (ChorĂ©graphie)
2.1. Qu'est-ce qu'une "Fonction Lambda" ?
Une fonction Lambda n'est pas seulement votre code. C'est un "package" logique qui inclut trois composants essentiels :
1. Le Code (Artefact de déploiement)
Votre logique applicative, packagée de deux façons :
- Archive .zip : (Classique) Un fichier .zip contenant votre code (
app.py) et vos dépendances (/libou via Layers). - Image Conteneur : (Moderne) Une image Docker (jusqu'à 10GB) poussée sur ECR (Elastic Container Registry). Permet d'embarquer des dépendances OS (
apt-get) ou des modĂšles ML volumineux.
2. La Configuration (Ressource AWS)
Les métadonnées qui définissent comment le code s'exécute :
- Handler : Le point d'entrée (ex:
app.lambda_handler). - Runtime : Le "langage" (ex:
Python 3.12,Node.js 20.x,Java 17,Go 1.x,.NET 8, ouprovided.al2pour un Custom Runtime (PHP, Rust...)). - Mémoire : De 128MB à 10GB (le vCPU est alloué proportionnellement).
- Timeout : Durée max (1s à 900s / 15 min).
- Architecture :
x86_64(Intel/AMD) ouarm64(Graviton2, moins cher). - Variables d'Environnement : (ex:
LOG_LEVEL="INFO",DB_HOST=...).
3. Les Permissions (RÎle d'Exécution IAM)
(Le plus critique) La fonction "assume" (endosse) un IAM Role pour interagir avec AWS. Si votre code doit lire S3 (s3:GetObject) ou écrire dans CloudWatch Logs (logs:PutLogEvents), ce RÎle DOIT avoir ces permissions.
2.2. Le ModĂšle d'Invocation ĂvĂ©nementielle
Une Lambda ne "tourne" pas. Elle est dĂ©clenchĂ©e (Triggered) par un ĂvĂ©nement. Cet Ă©vĂ©nement est un JSON (payload) qui est passĂ© au paramĂštre event du handler.
ĂvĂ©nements DĂ©clencheurs (Triggers)
- API Gateway : (Expose la Lambda comme une API REST/HTTP).
- S3 : (ex:
s3:ObjectCreated:*sur un bucket). - SQS : (Traite les messages d'une file, en batch).
- EventBridge (Scheduler) : (ex: Un "Cron" tous les jours Ă 5h du matin).
- DynamoDB Streams : (ex: "DÚs qu'un item est modifié dans cette table...").
- Kinesis, SNS, Cognito, ALB...
Invocation Synchrone vs Asynchrone
| Mode | Exemple de Trigger | Comportement (Qui attend ?) | Gestion d'erreur (Ăchec Lambda) |
|---|---|---|---|
| Synchrone (Request-Response) | API Gateway, ALB, Cognito | L'appelant (API GW) attend que Lambda finisse (return response;). La connexion HTTP reste ouverte (max 29s pour API GW). | L'appelant (API GW) reçoit une erreur 502 Bad Gateway. C'est à l'appelant (client) de gérer le "retry". |
| Asynchrone (Event) | S3, EventBridge, SNS | L'appelant (S3) "lance" la Lambda et part immédiatement (n'attend pas la réponse). S3 reçoit un 202 Accepted du *service* Lambda. | Le service Lambda gÚre les "retries" automatiquement (2 fois par défaut) avant d'envoyer l'événement échoué à une Dead Letter Queue (DLQ) (si configurée). |
| Poll (ESM) (Event Source Mapping) | SQS, DynamoDB Streams | Le service Lambda "poll" (interroge) SQS, récupÚre un batch (ex: 10 messages) et invoque votre fonction 1 fois. | (Complexe) Par défaut, si la fonction échoue, le batch entier retourne à SQS (risque de boucle). (Activer ReportBatchItemFailures pour ne renvoyer que le message échoué). |
2.3. Le Contexte d'Exécution (Execution Context)
Le "Contexte d'Exécution" est le conteneur (basé sur Firecracker) que Lambda provisionne pour exécuter votre fonction. C'est cet environnement qui est "réchauffé" (Warm).
Phases (Init vs Invoke)
Comprendre ces deux phases est la clé pour optimiser les "Cold Starts" (2.4).
# (Code Python)
# -------- PHASE 1 : INIT (Démarrage à Froid) --------
# (Exécuté 1 SEULE FOIS, lors du Cold Start)
# (Facturation : Non facturé (max 10s))
import boto3
import pandas as pd
print("INIT: Démarrage du conteneur...")
# (Bonne pratique : Initialiser les clients/connexions ici)
s3_client = boto3.client('s3')
db_connection = ... # (Si hors VPC)
# --------------------------------------------------
# -------- PHASE 2 : INVOKE (Handler) --------
# (Exécuté à CHAQUE INVOCATION)
# (Facturation : Facturé à la milliseconde)
def lambda_handler(event, context):
# (Le 'context' est un objet AWS avec les métadonnées)
print(f"Request ID: {context.aws_request_id}")
print(f"Temps restant (ms): {context.get_remaining_time_in_millis()}")
# (Le code 'Init' (s3_client) est réutilisé ici)
response = s3_client.get_object(...)
return "OK"
# --------------------------------------------------
Réutilisation (Warm) : Si une 2Úme invocation arrive rapidement, AWS réutilise ce conteneur. Il saute la phase "Init" (s3_client existe déjà ) et exécute seulement la phase "Invoke" (lambda_handler).
2.4. Le "Cold Start" (Démarrage à Froid)
Définition : Un "Cold Start" est la latence (délai) subie lors de la premiÚre invocation, car AWS doit créer un Contexte d'Exécution (2.3) à partir de zéro.
Phases d'un Cold Start (Ce qui prend du temps)
- (AWS) Allocation du conteneur Firecracker.
- (AWS) Téléchargement du code (Image ECR ou .zip S3).
- (AWS) Démarrage du Runtime (ex: Démarrage de la JVM pour Java, ou
python3.12). - (Code Client) Exécution de la phase
Init(2.3) (import pandas,boto3.client()...). - (Code Client) Exécution de la phase
Invoke(lambda_handler).
Warm Start (Démarrage à Chaud)
Un "Warm Start" se produit si AWS réutilise un conteneur existant. Il saute les étapes 1 à 4 et exécute directement l'étape 5 (Invoke).
Impact sur la Latence (Varie énormément)
- Python / Node.js / Go : Cold Start trĂšs rapide (ex: 50ms - 300ms).
- Java / .NET (C#) : Cold Start trÚs lent (ex: 2s - 10s) (à cause du démarrage de la JVM/CLR).
- Lambda dans un VPC (Avant 2019) : (Historique) Ajoutait 10-15 secondes (pour créer l'ENI). (ProblÚme résolu par AWS Hyperplane).
Moyens de réduire les Cold Starts
- 1. Provisioned Concurrency (PC) : (La solution payante) Vous payez AWS (Ă l'heure) pour garder (ex:) 50 conteneurs "prĂ©-chauffĂ©s" (Warm) 24/7, prĂȘts Ă recevoir des requĂȘtes (
Invoke). (Pour API Web Ă faible latence). - 2. Optimiser le code
Init: Ne pas importer de librairies lourdes (pandas) si ce n'est pas nécessaire. - 3. Augmenter la Mémoire : Plus de RAM = Plus de vCPU = Phase
Initplus rapide. (Souvent, 2GB RAM est plus rapide que 512MB). - 4. SnapStart (Java Uniquement) : AWS prend un "snapshot" (image) de la JVM (mémoire) aprÚs l'
Init, permettant un redémarrage (Warm) quasi-instantané.
2.5. Limitations (Quotas) de Base
Lambda n'est pas fait pour tout (pas pour les calculs de 3 heures). Il a des limites (certaines "Hard", d'autres "Soft" (ajustables)).
| Ressource | Limite (Défaut) | Type |
|---|---|---|
| Timeout (Durée) | 900 secondes (15 minutes) | Hard |
| Mémoire (RAM) | 128 MB (Min) à 10,240 MB (10 GB) (Max) | Hard |
| CPU | Proportionnel Ă la RAM (Max 6 vCPU Ă 10 GB) | Hard |
| Taille Package (.zip) | 250 MB (Dézippé, incluant les Layers) | Hard |
| Taille Image (Container) | 10 GB | Hard |
Payload (event) Synchrone | 6 MB (ex: Body d'une requĂȘte API Gateway) | Hard |
Payload (event) Asynchrone | 256 KB (ex: ĂvĂ©nement S3 / SNS) | Hard |
Stockage /tmp | 512 MB (Espace disque "Scratch" éphémÚre) | Hard (Ajustable 10GB via "Ephemeral Storage") |
| Exécutions Simultanées (Concurrency) | 1000 (Par Région, Par Compte) | Soft (Ajustable via Support AWS) |
âServerlessâ â âSans Serveursâ
Le terme "Serverless" (Informatique sans serveur) est un nom marketing. Il y a (bien sûr) des serveurs. La différence est que vous ne les gérez pas. AWS s'occupe de l'allocation, du patching, du scaling et de la haute disponibilité de l'infrastructure d'exécution.
Votre seule responsabilité est de fournir le code applicatif.
Différence IaaS / PaaS / FaaS (Niveau de Gestion)
| Tùche Gérée | IaaS (ex: EC2) | PaaS (ex: RDS, Beanstalk) | FaaS (ex: Lambda) |
|---|---|---|---|
| Code Applicatif (Logique) | Vous | Vous | Vous |
| Scaling (Scale-Out/In) | Vous (Auto Scaling Group) | AWS (GĂ©rĂ©) | AWS (Automatique, par requĂȘte) |
| Runtime (ex: Python 3.12) | Vous (apt install) | AWS (Vous choisissez) | AWS (Vous choisissez) |
| OS (Patching Sécurité) | Vous (apt update) | AWS (Géré) | AWS (Totalement Géré) |
| Serveurs (Hardware, VM) | Vous (Choix Instance) | AWS (Totalement Géré) | AWS (Totalement Géré) |
| Réseau / Data Center | AWS (Géré) | AWS (Géré) | AWS (Totalement Géré) |
AWS Lambda (Functions as a Service)
AWS Lambda est un service de calcul FaaS (Function-as-a-Service). Il exécute votre code (une "fonction") à la demande, en réponse à des événements (Triggers).
ModÚle d'exécution (Stateless) :
- La fonction "dort" (coût $0).
- Un événement (Trigger) arrive (ex: un
PUTsur S3, un appelAPI Gateway). - AWS "réveille" (ou crée) un conteneur d'exécution (c'est le Cold Start).
- AWS exécute votre Handler (point d'entrée) en lui passant l'événement (JSON).
- La fonction s'exécute (max 15 min).
- La fonction retourne une réponse (ou pas).
- Le conteneur "s'endort" (reste "Warm" quelques minutes) ou est détruit.
Stateless (Sans Ă©tat) : Chaque invocation est (potentiellement) un nouveau conteneur. Vous ne devez jamais stocker d'Ă©tat (ex: variables globales) entre deux invocations. L'Ă©tat doit ĂȘtre persistĂ© (ex: DynamoDB, S3, RDS).
Le "Handler" (Python)
C'est le point d'entrée de votre code. Il prend toujours 2 arguments :
# Fichier: app.py (Handler: "app.lambda_handler")
def lambda_handler(event, context):
"""
:param event: (dict) Le JSON du Trigger (ex: infos S3, body API GW)
:param context: (object) Métadonnées d'exécution (Request ID, Log Group, Temps restant)
"""
# 1. Log (va sur CloudWatch Logs)
print(f"ĂvĂ©nement reçu: {event}")
# 2. Logique métier
message = "Traitement terminé."
# 3. Retour (crucial pour API GW, ignoré par S3)
return {
'statusCode': 200,
'body': message
}
Backend API (Web/Mobile)
C'est le cas d'usage le plus fréquent. Remplacer un serveur (EC2/Django/Node.js) par une API 100% serverless.
Architecture : (Client) -> (API Gateway) -> (Lambda) -> (DynamoDB/RDS)
Avantage : Scaling "infini" (gÚre 1 req/jour comme 1 million req/heure) et ne coûte rien (ou presque) si inutilisé.
Traitement de Données (Event-Driven)
Utiliser les événements AWS comme "déclencheurs" (Triggers).
- Traitement S3 (Images) : (Trigger:
S3:ObjectCreated) -> Lambda se déclenche -> Crée un Thumbnail (Pillow) -> Sauvegarde sur S3 (autre bucket). - Traitement S3 (Logs/CSV) : (Trigger:
S3:ObjectCreated) -> Lambda se déclenche -> Lit le CSV (Pandas) -> InsÚre les lignes dans RDS/DynamoDB. - File SQS (Découplage) : (Trigger:
SQS Message) -> Lambda "dĂ©pile" les messages (un par un ou en batch) pour un traitement asynchrone (ex: envoi d'emails). - EventBridge (Bus d'ĂvĂ©nements) : (Trigger:
EventBridge Rule) -> Déclencher une Lambda quand (par ex:) une instance EC2 change d'état (EC2 State Change).
Automatisation (Ops / DevOps)
Remplacer les scripts cron ou bash sur un serveur d'admin.
- "Cron" (Scheduler) : (Trigger:
EventBridge Scheduler (Cron)) -> Lambda (tous les matins Ă 4h) -> Fait un Snapshot (boto3) des volumes EBS (backup). - "Glue Code" : (Trigger:
Alerte CloudWatch) -> Lambda se déclenche -> Envoie une notification (requests) sur Slack/Teams.
Une fonction Lambda "dort" (n'existe pas) jusqu'Ă ce qu'un ĂvĂ©nement (Event) la dĂ©clenche (Trigger).
L'événement est un JSON (payload) qui contient les informations (ex: "Qui m'appelle et pourquoi ?").
Types d'Invocation (Triggers)
| Type | Service (Exemple) | ModĂšle (Push/Pull) | Description |
|---|---|---|---|
| Synchrone (Request-Response) | API Gateway (3.1) ELB (ALB) Cognito | Push | L'appelant (API GW) attend que Lambda finisse (return response;) et renvoie la réponse (HTTP 200). |
| Asynchrone (Event) | S3 (3.2) SNS EventBridge | Push | L'appelant (S3) "lance" la fonction et part immédiatement (n'attend pas la réponse). Lambda renvoie "OK, bien reçu". |
| Event Source Mapping (ESM) | SQS (3.3) DynamoDB Streams Kinesis | Pull (Poll) | C'est Lambda (le service) qui "poll" (interroge en boucle) la source (SQS) et s'auto-invoque (en batch) si messages il y a. |
Le Runtime est l'environnement d'exécution (OS + Langage) fourni par AWS.
Runtimes Managés (AWS)
- Node.js : (18.x, 20.x) (TrĂšs rapide au Cold Start (4.2))
- Python : (3.9, 3.10, 3.11, 3.12) (Populaire, rapide)
- Java : (11, 17, 21) (Performant, mais Cold Start plus lent (JVM))
- Go : (1.x) (Compilé, Cold Start quasi-nul)
- .NET : (6, 7, 8)
- Ruby : (3.2)
Runtimes Custom
provided.al2(Amazon Linux 2) : (Bring Your Own Language) Vous pouvez amener du PHP, Rust, C++, Swift... (via "Custom Runtime")- Container Image (6.3) : Vous fournissez une image Docker (ex: Debian + PHP) qui respecte l'API "Runtime Interface Client".
Le "Handler" (Point d'entrée)
C'est la fonction (dans votre code) qu'AWS doit exécuter. (Configuré via Handler : ex: app.lambda_handler).
Il prend toujours 2 arguments : event et context.
# (Exemple Python: app.py)
# 'event' = Le JSON du Trigger (ex: infos S3, ou body API GW)
# 'context' = Métadonnées (Request ID, Log Group, Temps restant)
def lambda_handler(event, context):
# 1. Lire l'événement (Input)
name = event.get('name', 'World')
# 2. Logguer (va sur CloudWatch Logs (7.1))
print(f"Invocation ID: {context.aws_request_id}")
print(f"Received event: {event}")
# 3. Traiter (Business Logic)
response_message = f"Hello, {name}!"
# 4. Retourner la réponse (Output)
# (Ignoré si Async (S3), mais Crucial si Sync (API GW))
return {
'statusCode': 200,
'body': response_message
}
(PiÚge n°1) C'est la premiÚre cause d'échec d'une Lambda. La fonction "plante" (Task timed out ou Permissions error) car elle n'a pas les droits IAM.
La fonction Lambda doit "Assumer" (Assume) un IAM Role (Execution Role) pour avoir le droit d'interagir avec AWS.
1. Relation d'Approbation (Trust Policy)
Le RĂŽle (IAM) doit "faire confiance" (AssumeRole) au service Lambda.
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}2. Permissions (Policy)
Le RĂŽle (IAM) doit avoir les permissions (Policies) pour ce que le code (Handler) (1.3) tente de faire.
Permission Minimale (Obligatoire) : Logging
Si vous n'ajoutez pas ceci, la fonction ne peut mĂȘme pas Ă©crire ses logs (print()) (7.1) et vous ne verrez jamais l'erreur.
(Policy: AWSLambdaBasicExecutionRole)
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}Permissions Additionnelles (Selon le code)
- (Code lit S3) -> Ajouter
s3:GetObject(sur le Bucket S3). - (Code écrit DynamoDB) -> Ajouter
dynamodb:PutItem(sur la Table). - (Code accĂšde Ă RDS (VPC)) -> Ajouter
ec2:CreateNetworkInterface,ec2:DeleteNetworkInterface(PolicyAWSLambdaVPCAccessExecutionRole) (5.1). - (Code lit Secrets) -> Ajouter
secretsmanager:GetSecretValue.
La seule "ressource" que vous configurez (via un "slider") est la Mémoire (RAM).
Plage (Range)
- Min : 128 MB
- Max : 10 240 MB (10 GB)
CorrĂ©lation MĂ©moire â vCPU
Vous ne configurez pas le CPU. Lambda alloue (automatiquement) du CPU proportionnellement à la RAM demandée.
| Mémoire (RAM) Allouée | vCPU (Proportionnel) Alloué |
|---|---|
| 128 MB | ~0.08 vCPU (Partagé) |
| 1 024 MB (1 GB) | ~0.6 vCPU |
| 1 769 MB (â 1.8 GB) | 1.0 vCPU (Plein) |
| 3 008 MB (â 3 GB) | 2.0 vCPU (Plein) |
| 10 240 MB (10 GB) | 6.0 vCPU (Plein) |
Optimisation (Coût vs Vitesse)
La facturation (1.1) est (Prix RAM) x (Durée ms).
TĂąche (CPU-Bound) : (Ex: Calculer un hash, compresser image)
- (128MB / 0.08 vCPU) -> Dure 10 sec -> Coût : (1x) * (10s) = 10 Unités
- (1024MB / 0.6 vCPU) -> Dure 1 sec -> Coût : (8x) * (1s) = 8 Unités
Conclusion : Augmenter la RAM (128 -> 1024) peut rendre la fonction plus rapide (CPU) et (parfois) moins chÚre (car la durée (ms) diminue plus vite que le prix (RAM) n'augmente).
(Outil) : Utiliser "AWS Lambda Power Tuning" (Step Function) pour trouver le "sweet spot" (coût/vitesse) (ex: 768 MB).
C'est le "garde-fou". Le temps maximum (chronomĂštre) qu'une invocation (1.3) a le droit de durer.
Limites
- Minimum : 1 seconde
- Défaut (PiÚge n°1) : 3 secondes
- Maximum : 900 secondes (15 minutes)
ScĂ©nario d'Ăchec (Task timed out)
C'est l'erreur la plus fréquente aprÚs les "Access Denied" (2.1).
- (Config) Vous laissez le Timeout à 3 sec (défaut).
- (Code) Votre fonction (Python) appelle une API externe (
requests.get(...)). - (Runtime) L'API externe est lente (prend 5 sec).
- (Lambda) Ă 3.0 sec, le service Lambda "tue" (KILL) (
SIGKILL) votre fonction (en plein milieu). - (Logs (7.1)) Vous voyez l'erreur :
"Task timed out after 3.01 seconds".
Bonne Pratique (Timeout)
- Ne jamais mettre 15 min (900 sec) (sauf Batch). Si l'App bug (boucle infinie), vous payez 15 min de CPU pour rien.
- Mettre une valeur raisonnable (ex: 10-30 secondes) pour les API Web.
- (Dans le code) Le
context(1.3) (context.get_remaining_time_in_millis()) permet de savoir "Combien de temps il me reste ?" (pour un "graceful shutdown").
Timeout vs API Gateway
Si Lambda (Trigger: API GW (3.1)), il y a 2 Timeouts :
- (API GW) Timeout (Max 29 sec).
- (Lambda) Timeout (Max 15 min).
Si Lambda prend 35 sec (pour répondre), API GW (le client) aura déjà "raccroché" (504 Gateway Timeout) à 29 sec.
C'est le trigger Synchrone (Request-Response). Permet de créer une API REST (Serverless).
Flux : (Client HTTP) POST /login -> (API GW) -> (Trigger Lambda) -> (Lambda) return response -> (API GW) -> (Client HTTP) 200 OK.
Le "Payload" (event) (Format 2.0)
Ce que Lambda reçoit (event) (1.3) de l'API GW (HTTP) :
{
"version": "2.0",
"routeKey": "POST /login",
"rawPath": "/login",
"headers": {
"content-type": "application/json",
"user-agent": "curl/7.64.1",
...
},
"requestContext": {
"http": { "method": "POST", "path": "/login" },
"stage": "prod",
...
},
"body": "{\"username\": \"admin\", \"password\": \"123\"}",
"isBase64Encoded": false
}La "Réponse" (return) (Format 2.0)
Ce que Lambda doit retourner (return) (1.3) Ă l'API GW :
{
"isBase64Encoded": false,
"statusCode": 200,
"headers": {
"Content-Type": "application/json",
"Set-Cookie": "token=abc..."
},
"body": "{\"message\": \"Login successful\"}"
}PiÚge : Si votre code (Python) plante (Exception) ou renvoie un return mal formaté (ex: return "OK" (String)), API Gateway renvoie 502 Bad Gateway (Internal Server Error) au client.
C'est le trigger Asynchrone (Event). (Fire-and-forget).
Flux : (User) PUT image.jpg -> (S3) -> (Event Notification) -> (Trigger Lambda) -> (Lambda) (Traite l'image...).
S3 n'attend pas la réponse de Lambda. L'upload (PUT) est "OK" (200) instantanément.
Configuration (S3 Event Notification)
- Event types :
s3:ObjectCreated:*(Upload),s3:ObjectRemoved:*(Delete). - Prefix : (Filtre)
images/(Ne déclenche que pour ce dossier). - Suffix : (Filtre)
.jpg(Ne déclenche que pour les JPG).
Le "Payload" (event)
Ce que Lambda reçoit (event) (1.3) de S3 :
{
"Records": [
{
"eventTime": "2025-11-10T15:00:00Z",
"eventName": "ObjectCreated:Put",
"s3": {
"bucket": {
"name": "mon-bucket-input",
"arn": "arn:aws:s3:::mon-bucket-input"
},
"object": {
"key": "images/photo.jpg",
"size": 10240,
"eTag": "..."
}
}
}
// (Peut contenir plusieurs "Records" si S3 batche)
]
}Retries & DLQ (Asynchrone)
Si l'invocation (Asynchrone) échoue (Plante, Timeout (2.3)) :
- (AWS) Retente (Retry) automatiquement (2 fois).
- (AWS) (AprÚs 2 échecs) Envoie l'événement (JSON) vers une DLQ (Dead Letter Queue) (si configurée).
Bonne Pratique : Toujours configurer une DLQ (une file SQS (3.3) ou SNS) sur les Lambda (Asynchrones) pour ne pas "perdre" les événements (fichiers) échoués.
C'est le trigger Event Source Mapping (ESM) (Polling). Idéal pour découpler (débuffer) des systÚmes (ex: API (rapide) -> SQS (buffer) -> Lambda (traitement lent)).
Flux (ESM)
- (Service Lambda) "Poll" (
ReceiveMessage) (en Long Polling) la file SQS. - (SQS) "OK, voici 10 messages (Batch)".
- (Service Lambda) Invoque votre fonction Lambda 1 fois (Synchrone) avec un "payload" (
event) contenant les 10 messages. - (Votre Lambda) Traite les 10 messages (
for message in event['Records']...). - (Votre Lambda)
return;(SuccĂšs). - (Service Lambda) (Si succĂšs)
DeleteMessageBatch(supprime les 10 messages de SQS).
Configuration Clé (ESM)
BatchSize: (Défaut 10, Max 10 000) Nb de messages à prendre par invocation.BatchWindowInSeconds: (Défaut 0, Max 300) Attendre (ex: 5 sec) pour "remplir" le batch (si la file est peu active).
Gestion d'Erreur (Batch Partiel)
PiÚge (Défaut) : (Batch de 10) Si la 3Úme (sur 10) message fait planter (Exception) la fonction -> (Lambda) Ne supprime aucun message -> (SQS) Les 10 messages réapparaissent (Visbility Timeout) -> (Lambda) Re-traite les 10 -> Re-plante sur le 3Úme -> (Boucle Infinie).
Solution (Moderne) :
- (Config ESM) Activer
ReportBatchItemFailures. - (Code Lambda)
try/except(autour de chaque message (dans la bouclefor)). - (Code Lambda)
return { "batchItemFailures": [ {"itemIdentifier": "ID_MSG_3"} ] }.
Résultat : Lambda supprime les 9 (succÚs) et ne remet que le 3Úme (échec) dans la file (pour retry, ou DLQ SQS).
Lambda ne fait pas de Scaling Vertical (Augmenter la RAM/CPU d'une instance). Lambda fait du Scaling Horizontal (Scale-Out).
RÚgle : 1 Invocation (simultanée) = 1 "Environnement d'Exécution" (Conteneur).
Exemple (vs EC2)
| Scénario | EC2 (ASG, t3.large) | Lambda (FaaS) |
|---|---|---|
| 1 Utilisateur (1 req/sec) | 1 EC2 (t3.large) (CPU 1%).(Facturé 100%). | 1 Conteneur (Warm) (4.2). (Facturé ~100ms / sec). |
| 1000 Utilisateurs (simultanés) | (ASG) Démarre 4 autres EC2 (t3.large). (Prend 5 min). | (Lambda) Démarre 1000 Conteneurs (concurrents). (Prend 2 sec). |
"Burst" (Rafale) : Lambda peut absorber (par défaut) une rafale (Burst) de 500 à 3000 nouvelles invocations (concurrentes) instantanément (selon Région), puis 500/min ensuite.
(Le PiÚge de Performance n°1) C'est le délai (latence) requis pour démarrer un nouvel Environnement d'Exécution (Conteneur) (quand il n'y en a pas de "chaud" (Warm) disponible).
Les 2 Phases d'un Cold Start (Démarrage à Froid)
| Phase | Description | Facturé ? | Impact (Latence) |
|---|---|---|---|
Init (Initialisation) | (AWS) TĂ©lĂ©charge le code (.zip) (AWS) DĂ©marre le Runtime (ex: python3.12)(Client) ExĂ©cute le code global ( import pandas, db_conn = ...) (hors Handler). | Non (Jusqu'Ă 10 sec) | ĂlevĂ© (50ms (Go) Ă 10 sec (Java/VPC)) |
Invoke (Invocation) | (AWS) Exécute la fonction Handler (lambda_handler(event, context)) (1.3). | Oui (ms) | (Business Logic) |
Warm Start (Démarrage à Chaud)
Si une 2Ăšme requĂȘte arrive (ex: 50ms aprĂšs la 1Ăšre), AWS rĂ©utilise l'Environnement (Conteneur) (dĂ©jĂ "Init").
Flux : (AWS) Exécute seulement la phase Invoke (lambda_handler(...)).
Résultat : Latence quasi-nulle (pas de Init).
Bonne Pratique (Optimisation Init)
TOUT ce qui peut ĂȘtre fait 1 fois (Imports, Connexion DB (si hors VPC), Clients AWS (Boto3)) doit ĂȘtre mis en dehors du Handler (en scope global) pour ĂȘtre exĂ©cutĂ© (gratuitement) pendant l'Init et rĂ©utilisĂ© (en cache) par les Invoke (Warm).
Concurrency (ExĂ©cutions SimultanĂ©es) : C'est le nombre d'invocations (conteneurs) qui tournent en mĂȘme temps (Ă la mĂȘme milliseconde).
1. Account Concurrency (Throttling)
(Garde-fou) AWS impose une limite (par défaut 1000) d'exécutions simultanées par compte, par région.
Si 1001 requĂȘtes arrivent (simultanĂ©ment), la 1001Ăšme Ă©choue (Erreur 429 - ThrottlingException).
(Bonne Pratique) : Mettre une Alarme (CloudWatch Metric (7.2) Throttles) et demander une augmentation (Support) si besoin.
2. Reserved Concurrency (Réservation)
(Configuration par fonction). (Ex: MaFonctionA, Reserved = 100).
- Garantie (Positif) : Garantit que
MaFonctionA(critique) aura toujours 100 "slots" (sur les 1000 du compte) pour elle. - Limite (Négatif) : Plafonne (throttle)
MaFonctionAĂ 100. (La 101Ăšme invocation (sur A) sera throttlĂ©e, mĂȘme si le compte (1000) est libre).
3. Provisioned Concurrency (PC)
(Configuration par fonction/alias). (Ex: MaFonctionA, Provisioned = 50).
- Objectif : Tuer le Cold Start (4.2).
- Flux : (AWS) Démarre (
Init) 50 Environnements (Conteneurs) et les garde "prĂ©-chauffĂ©s" (Warm) 24/7. - RĂ©sultat : Les 50 premiĂšres invocations (simultanĂ©es) sont garanties d'ĂȘtre "Warm" (Latence minime).
- CoĂ»t : Payant (FacturĂ© Ă l'heure oĂč l'environnement est "ProvisionnĂ©" (idle), mais moins cher que l'exĂ©cution).
Cas 1 : Lambda "Hors VPC" (Défaut)
Par défaut, une Lambda (1.1) tourne dans un VPC (interne) managé par AWS.
- Avantage : AccĂšs automatique Ă Internet (ex:
requests.get('api.google.com')). - Avantage : Zéro Cold Start (4.2) réseau.
- Inconvénient : Ne peut pas voir vos ressources Privées (ex: RDS, ElastiCache, EC2) (qui sont dans votre VPC).
Cas 2 : Lambda "Dans VOTRE VPC" (Optionnel)
C'est une configuration (optionnelle) requise uniquement si la fonction (6.3) doit accéder à une ressource privée (ex: rds.amazonaws.com (Endpoint privé)).
Configuration (VPC)
Lors de la création, vous devez spécifier :
- VPC : Votre VPC (ex:
vpc-main). - Subnets : (Au moins 2) Subnets Privés (ex:
private-a,private-b). - Security Group : (Un SG (ex:
sg-lambda) pour la fonction).
Le PiĂšge (AccĂšs Internet)
En mettant Lambda dans un Subnet Privé (pour voir RDS), elle perd (automatiquement) son accÚs à Internet (Cas 1).
ProblĂšme : (Code 6.3) boto3.client('secretsmanager') (Appel API AWS Publique) -> Connection Timeout.
Solution : Il faut (aussi) un NAT Gateway (5.3) (ou un VPC Endpoint "Interface").
L'Ancien ProblĂšme (Avant 2019) : Cold Start VPC
Historiquement, mettre une Lambda dans un VPC (5.1) était un désastre de performance (Cold Start de 10-15 secondes).
Raison : (à chaque Cold Start) AWS devait (dynamiquement) : 1. Trouver une IP (dans votre Subnet) -> 2. Créer une ENI (Elastic Network Interface) -> 3. Attacher l'ENI à l'hÎte Lambda.
La Solution (Moderne) : AWS Hyperplane
(Déployé automatiquement depuis 2019). AWS a refait le backend réseau de Lambda.
Flux (Moderne) :
- (à la création de la Fonction) AWS crée (en avance) des ENIs "Hyperplane" (partagées) dans vos Subnets/SG (VPC).
- (Au Cold Start (Invoke)) (50-100ms) AWS "mappe" (virtuellement) le nouveau conteneur Lambda à l'ENI (Hyperplane) déjà existante.
Résultat : Le "Cold Start VPC" (le délai d'attachement de l'ENI) a disparu. Le seul Cold Start (4.2) qui reste est celui du Runtime (Init).
Pré-requis (IAM)
Pour que cela (Hyperplane) fonctionne, l'IAM Role (2.1) de la fonction doit (toujours) avoir la Policy AWSLambdaVPCAccessExecutionRole (ec2:CreateNetworkInterface, ec2:DeleteNetworkInterface...).
Scénario : Ma Lambda (Django) (6.3) doit :
1. Lire RDS (Base de données) (ex: 10.0.1.50) (Ressource Privée)
2. Appeler l'API Stripe (api.stripe.com) (Ressource Publique/Internet)
La Contradiction
- (Pour 1) Je dois mettre Lambda dans un Subnet Privé (dans mon VPC) (5.1).
- (PiÚge) Un Subnet Privé (par définition) n'a PAS de Route (
0.0.0.0/0) vers l'Internet Gateway (IGW). - (Résultat) L'appel (2) (
api.stripe.com) échoue (Connection Timeout).
Solution 1 : NAT Gateway (Standard)
C'est la solution "classique" (utilisée aussi pour EC2).
- (VPC) Provisionner un NAT Gateway (PaaS) (dans un Subnet Public). (Facturé $/heure + $/GB).
- (VPC) Modifier la Route Table du Subnet PrivĂ© (oĂč vit Lambda).
- (VPC) Ajouter une Route :
Destination: 0.0.0.0/0->Target: nat-gateway-id.
Flux : (Lambda Privée) -> (Route Table Privée) -> (NAT GW (Public)) -> (IGW) -> (Internet (Stripe)).
Solution 2 : VPC Endpoints (Interface)
Si la Lambda (VPC) (5.1) n'appelle que des APIs AWS (ex: S3, DynamoDB, Secrets Manager (6.3)) (pas Stripe/Google).
- (VPC) Créer un VPC Endpoint (Interface) (PaaS, Powered by PrivateLink) pour
com.amazonaws.eu-west-3.secretsmanager. - (Endpoint) AWS place une ENI (IP Privée, ex:
10.0.1.100) dans votre Subnet Privé.
Flux : (Lambda Privée) boto3.client('secretsmanager') -> (DNS) secretsmanager.eu-west-3... résout vers 10.0.1.100 (Privé) -> (Appel API via le réseau AWS privé, sans NAT, sans IGW).
C'est la méthode de déploiement "classique" (Fichier Archive .zip).
Structure (Ex: Python)
Si vous n'avez pas de dépendances (libs) :
(MonCode.zip)
-> app.py (Contient le handler (1.3))
-> utils.py
Si vous avez des dépendances (ex: requests) (et n'utilisez pas Layers (6.2)) :
# (Local)
pip install requests -t ./package
# (Ziper le contenu de "package", pas le dossier "package")
cd package
zip -r ../MonCode.zip .
cd ..
# (Ajouter le code)
zip -g MonCode.zip app.py
(MonCode.zip)
-> app.py
-> requests/ (La lib)
-> requests-2.31.0.dist-info/
...
Limites (ZIP)
- Taille (Upload direct) : 50 MB (zippé).
- Taille (via S3) : 250 MB (dézippé, incluant les Layers (6.2)).
- Espace
/tmp: 512 MB (Espace disque "Scratch", éphémÚre, non-garanti). (Max 10 GB si "Ephemeral Storage" activé).
C'est la méthode recommandée pour gérer les dépendances (libs) lourdes (ex: pandas, numpy) ou partagées.
Une "Layer" (Couche) est un .zip (séparé) qui contient les dépendances.
Flux (Python)
- (Local) Créer la structure (obligatoire) :
mkdir -p python/lib/python3.12/site-packages - (Local)
pip install pandas -t ./python/lib/python3.12/site-packages - (Local)
zip -r pandas-layer.zip ./python - (AWS) Créer une "Layer" (ex:
pandas-v1) en uploadantpandas-layer.zip. - (AWS) (Lambda) Attacher la "Layer" (
pandas-v1) Ă la fonction Lambda. - (Code Lambda)
import pandas as pd-> (Ăa marche !)
Fonctionnement (Runtime)
- (Au Cold Start (4.2)) AWS "dézippe" la (ou les) Layer(s) dans le dossier
/optde l'Environnement (Conteneur). - Le Runtime (Python) inclut (automatiquement)
/opt/python/lib/python3.12/site-packagesdans sonPYTHONPATH.
Avantages
- Taille (Code) : Votre
app.zip(6.1) reste petit (ex: 5 KB). (Upload/DĂ©ploiement rapide). - Partage (DRY) : 50 fonctions Lambda (Python) peuvent partager la mĂȘme Layer (
pandas-v1). - Versioning : Mettre Ă jour
pandas(v2) = Uploader une nouvelle Layer (pandas-v2) et pointer les Lambda dessus (sans re-déployer le code).
Alternative au .zip (6.1). Permet de packager la fonction (Code + Dépendances) comme une Image Docker.
Avantages
- Taille (Limite) : Jusqu'Ă 10 GB. (Permet d'embarquer des modĂšles ML (PyTorch), FFMPEG, etc.).
- Consistance (Dev/Prod) : L'Image (Docker) qui tourne en local (Dev) est exactement la mĂȘme (bit-pour-bit) que celle qui tourne sur Lambda (Prod).
- Dépendances (OS) : Permet d'
apt-get installdes librairies OS (non-incluses dans Amazon Linux 2 (1.3)).
Dockerfile (Exemple Python)
# 1. Utiliser l'image de base (fournie par AWS)
FROM public.ecr.aws/lambda/python:3.12
# 2. Copier le code (Handler (1.3))
COPY app.py ${LAMBDA_TASK_ROOT}
# 3. Copier les dépendances (pip)
COPY requirements.txt .
RUN pip install -r requirements.txt -t ${LAMBDA_TASK_ROOT}
# (Optionnel) Installer des libs OS
# RUN yum install -y ffmpeg
# 4. Définir le "Handler" (CMD)
CMD [ "app.lambda_handler" ]
Flux de Déploiement
- (Local)
docker build -t mon-app . - (AWS ECR) Authentifier Docker (
aws ecr get-login-password...) - (Local)
docker tag mon-app:latest 111.dkr.ecr.eu-west-3.amazonaws.com/mon-app:latest - (Local)
docker push ...(Upload vers ECR). - (AWS Lambda) "Créer Fonction" -> "Depuis Image Container" -> Pointer vers l'URL ECR.
(Automatique) C'est la destination (standard) pour toute la sortie (stdout, stderr) de votre fonction (print(), console.log()).
Pré-requis : L'IAM Role (2.1) doit avoir la Policy AWSLambdaBasicExecutionRole (logs:PutLogEvents...).
Structure (Log Groups)
Chaque fonction Lambda crée (automatiquement) son propre Log Group :
- Log Group :
/aws/lambda/ma-fonction-prod - Log Streams : (Fichiers de log)
2025/11/10/[1]...,2025/11/10/[2]...(1 Stream par Conteneur (4.1) concurrent).
Ce que Lambda loggue (Automatiquement)
Chaque invocation (1.3) génÚre (au moins) 3 lignes de log (systÚme) :
# 1. (Démarrage)
START RequestId: 123-abc Version: $LATEST
# 2. (Votre Code)
[INFO] 2025-11-10T15:00:00Z 123-abc Received event: {'name': 'Test'}
# 3. (Fin)
END RequestId: 123-abc
# 4. (Rapport - Facturation)
REPORT RequestId: 123-abc Duration: 50.12 ms Billed Duration: 51 ms Memory Size: 128 MB Max Memory Used: 64 MB Init Duration: 150.45 ms
Init Duration (Cold Start)
Le REPORT est la seule façon de savoir si une invocation était un Cold Start (4.2). Si Init Duration (ex: 150ms) est présent = Cold Start. Si absent = Warm Start.
(Automatique) AWS Lambda envoie (automatiquement) des métriques (agrégées) à CloudWatch (permettant Graphes & Alarmes).
Métriques Clés (à Alarmer)
| Métrique | Unité | Description | Alarme (Bonne Pratique) |
|---|---|---|---|
Invocations | Count | Nombre de fois (total) que la fonction a été appelée (SuccÚs + Erreur). | (Alarme (SUM < 1) (si "Dead Man's Switch" / Cron)). |
Errors | Count | Nombre de fois oĂč le Handler (1.3) a plantĂ© (Exception) ou (Timeout (2.3)). | Alarme (SUM > 0) (Notification PagerDuty/Slack). |
Throttles | Count | Nombre de fois oĂč l'invocation a Ă©tĂ© refusĂ©e (Erreur 429) (Limite Concurrency (4.3) atteinte). | Alarme (SUM > 0) (Indique une surcharge du compte). |
Duration | Milliseconds | Temps d'exécution (Invoke) (4.2) (ex: 50ms). | Alarme (p95 > 2000ms) (Indique un ralentissement (ex: API externe)). |
ConcurrentExecutions | Count | Nombre (max) d'instances (conteneurs) (4.1) tournant en mĂȘme temps. | (Alarme (MAX > 800) (Proche de la limite compte (1000))). |
C'est le service de Tracing DistribuĂ©. Il permet de suivre une seule requĂȘte (Trace) Ă travers plusieurs services (Microservices).
ProblĂšme (CloudWatch (7.2) ne suffit pas)
Mon API (3.1) est lente (Duration = 5 secondes). Pourquoi ?
Le code Lambda (app.py) (1.3) fait 3 appels réseau :
- (Lambda) -> (API GW Externe (Stripe))
- (Lambda) -> (DynamoDB
PutItem) - (Lambda) -> (SNS
Publish)
OĂč sont passĂ©es les 5 secondes ? (Stripe ? DynamoDB ?)
Solution : AWS X-Ray
Activation
- (Config Lambda) Activer "Active Tracing" (case Ă cocher).
- (IAM Role (2.1)) Ajouter Policy
AWSXRayDaemonWriteAccess. - (Code Python) Importer le SDK X-Ray (
pip install aws-xray-sdk) et "patcher" (instrumenter) les libs (Boto3, Requests) (patch_all()).
Résultat (Service Map)
X-Ray (UI) affiche un "Waterfall" (cascade) de la Trace (RequĂȘte 123) :
(Trace ID: 123-abc) - Total: 5050ms
-> (API Gateway) (5ms)
-> (Lambda: ma-fonction) (5045ms)
-> (Init) (150ms)
-> (Lambda: Handler) (4895ms)
-> (HTTP: api.stripe.com) (Subsegment) (4500ms) (LE COUPABLE !)
-> (AWS: DynamoDB) (PutItem) (Subsegment) (200ms)
-> (AWS: SNS) (Publish) (Subsegment) (195ms)
Conclusion : La BDD (Dynamo) est rapide (200ms). C'est l'API externe (Stripe) qui est lente (4.5 sec).
