AWS : Lambda
AWS Lambda permet d'exécuter du code sans gérer de serveurs. Cet article décrit le déploiement d'une fonction qui restitue une page HTML via une Function URL, les méthodes de test applicables et les opérations de nettoyage des ressources associées.
AWS Lambda est un service d'exécution serverless orienté événements. Une fonction Lambda exécute du code en réponse à des déclencheurs (HTTP via Function URL ou API Gateway, événements S3, messages SNS/SQS, EventBridge, etc.). Le modèle de facturation repose sur le temps d'exécution et la mémoire allouée : il n'y a pas de coût pour des serveurs continus, seules les invocations et la durée d'exécution sont facturées.
Chaque invocation s'exécute dans un environnement d'exécution : une micro-VM Firecracker contenant le runtime et le code de la fonction. Son cycle de vie comporte trois phases :
- Init : création de l'environnement, téléchargement du code, démarrage du runtime et exécution du code situé hors du handler (imports, connexions, lecture de fichiers). C'est le cold start.
- Invoke : exécution du handler pour un événement. Un environnement ne traite qu'une invocation à la fois ; des requêtes simultanées provoquent la création d'environnements supplémentaires.
- Shutdown : après une période d'inactivité, Lambda détruit l'environnement.
Entre deux invocations, l'environnement est gelé puis réutilisé : ce qui a été initialisé hors du handler (clients SDK, connexions, caches en mémoire, fichiers dans /tmp) persiste. Initialiser les ressources coûteuses au niveau du module plutôt que dans le handler exploite cette réutilisation.
La mémoire allouée (128 Mo à 10 Go) détermine aussi la puissance CPU, attribuée proportionnellement. Le timeout est plafonné à 15 minutes. Les logs et métriques sont émis vers CloudWatch, et l'exécution requiert un rôle IAM limité aux actions nécessaires (principe du moindre privilège).
Cas d'usage courants : backends HTTP légers, transformations d'objets S3, tâches asynchrones, webhooks et prototypes rapides. Pour des charges statiques ou des assets lourds, l'utilisation de S3 + CloudFront reste préférable.
Créer la fonction
La création de la fonction peut s'effectuer depuis la console AWS Lambda.
La fonction peut être configurée avec des valeurs simples, par exemple runtime nodejs22.x, architecture x86_64 et un nommage tel que http-function-url-tutorial. Le rôle d'exécution peut être créé automatiquement et doit autoriser l'envoi de logs vers CloudWatch.
Le plan "Getting started with Lambda HTTP" fournit un index.html et un handler simple lisant ce fichier et renvoyant son contenu comme body HTML. La fonction traite une requête HTTP et retourne un document HTML.
Exemple de handler
Le handler renvoie le contenu de index.html. Exemple (ESM) :
// index.mjs
import fs from 'node:fs';
// Exécuté une seule fois par environnement, pendant la phase Init
const html = fs.readFileSync('index.html', 'utf8');
export async function handler(event, context) {
// `event` contient les données de la requête HTTP ou l'événement déclencheur.
// `context` fournit des métadonnées d'exécution (requestId, timeout restant, etc.).
return {
statusCode: 200,
headers: { 'Content-Type': 'text/html' },
body: html,
};
}
Le handler reçoit deux paramètres principaux : event et context. Pour une invocation via Function URL, event suit le format payload 2.0 d'API Gateway HTTP API : requestContext.http.method, rawPath, headers, queryStringParameters, et body (encodé en base64 si isBase64Encoded vaut true). La lecture de index.html au niveau du module n'a lieu qu'au cold start ; les invocations suivantes servent la chaîne déjà en mémoire. Le paramètre context fournit des informations sur l'exécution en cours (identifiant de la requête, temps restant avant timeout). Les messages envoyés via console.log apparaissent automatiquement dans CloudWatch Logs.
Le démarrage initial d'un environnement d'exécution peut entraîner un "cold start" qui augmente la latence pour la première invocation. Les cold starts sont plus perceptibles pour certains runtimes et lorsque la fonction a des dépendances lourdes. Les stratégies pour réduire l'impact comprennent la provisioned concurrency (environnements pré-initialisés et facturés en continu), SnapStart (restauration d'un instantané de l'environnement initialisé, pour Java, Python et .NET) et la réduction de la taille du bundle.
Les variables d'environnement permettent de paramétrer le comportement sans modifier le code. Les layers servent à partager des dépendances entre fonctions et à réduire la taille des packages déployés.
Invoquer la Function URL
Pour vérifier le déploiement, l'onglet Code affiche le handler et le fichier index.html. L'ouverture de l'URL de Function (Configuration → Function URL) dans un navigateur déclenche l'invocation et retourne la page HTML.
L'URL a la forme https://<url-id>.lambda-url.<region>.on.aws/. Le test en ligne de commande s'effectue avec la commande suivante (remplacer <FUNCTION_URL> par l'URL fournie par la console) :
curl -i "<FUNCTION_URL>"
Vérifier les logs
Les logs CloudWatch fournissent les informations de diagnostic et les traces d'exécution. Les entrées START/END/REPORT et les erreurs JavaScript y sont visibles. Pour suivre les logs en temps réel, utiliser :
aws logs tail /aws/lambda/http-function-url-tutorial --follow --since 1h
La CLI AWS permet également d'invoquer la fonction directement sans passer par la Function URL :
aws lambda invoke --function-name http-function-url-tutorial out.txt
La différence principale est l'endpoint : aws lambda invoke appelle l'API de gestion de Lambda, authentifiée par IAM, et transmet le payload fourni tel quel comme event, sans l'enveloppe HTTP construite par la Function URL (méthode, en-têtes, chemin). La réponse n'est pas non plus traduite en réponse HTTP. Le mode d'authentification d'une Function URL est soit NONE (URL publique, contrôlée par une policy basée sur les ressources de la fonction), soit AWS_IAM : les requêtes HTTP doivent alors être signées (SigV4) par une identité autorisée à lambda:InvokeFunctionUrl ; les SDK AWS gèrent cette signature automatiquement. Depuis octobre 2025, les nouvelles Function URL exigent en outre, dans les deux modes, la permission lambda:InvokeFunction ; la condition lambda:InvokedViaFunctionUrl restreint cette dernière aux appels passant par l'URL. En mode NONE, la console crée automatiquement la policy contenant les deux autorisations.
Alternatives et bonnes pratiques
Pour un contenu public statique, S3 associé à CloudFront sert les fichiers sans exécuter de code ni facturer d'invocations. Pour restreindre l'accès à une fonction, le mode AWS_IAM, ou un API Gateway doté d'un mécanisme d'authentification (JWT, clés d'API, authorizer Lambda), remplace une URL publique. Côté performance, le code s'empaquette en un bundle minimal et toute initialisation coûteuse se place hors du handler.
Exemple : chaînage de deux fonctions Lambda
Un chaînage direct entre deux fonctions Lambda permet d'illustrer les concepts d'invocation et de permissions sans introduire d'infrastructure supplémentaire. Dans cet exemple, la fonction producer invoque de manière asynchrone la fonction consumer via l'API Lambda (Invoke avec InvocationType='Event').
Extrait du producer (Python) :
import os, json, boto3
lambda_client = boto3.client('lambda')
CONSUMER = os.environ.get('CONSUMER_FUNCTION_NAME', 'lambda-consumer')
def handler(event, context):
payload = { 'message': 'Hello from producer', 'input': event }
lambda_client.invoke(
FunctionName=CONSUMER,
InvocationType='Event',
Payload=json.dumps(payload).encode()
)
return { 'statusCode': 202, 'body': json.dumps({'sent': True}) }
Comportement attendu du consumer : consigner le payload reçu dans les logs CloudWatch et exécuter le traitement asynchrone. Pour une invocation asynchrone, la réponse renvoyée par le consumer n'est pas retournée à l'appelant.
Avec InvocationType='Event', l'API Lambda place l'événement dans une file interne et répond immédiatement 202. Si le consumer échoue, Lambda réessaie jusqu'à deux fois, avec un délai croissant ; l'événement peut aussi être délivré plusieurs fois dans de rares cas. Au-delà des tentatives, il est perdu, sauf si une destination on-failure (file SQS, topic SNS, bus EventBridge, autre fonction) ou une dead-letter queue est configurée sur le consumer.
Permissions minimales : le rôle d'exécution de la fonction producer doit inclure l'action lambda:InvokeFunction ciblant l'ARN de la fonction consumer (ex. arn:aws:lambda:REGION:ACCOUNT_ID:function:lambda-consumer).
Test rapide (CLI) :
aws lambda invoke --function-name lambda-producer \
--cli-binary-format raw-in-base64-out --payload '{}' /tmp/out.json
cat /tmp/out.json
# Consulter les logs du consumer dans CloudWatch pour vérifier la réception
Remarques pratiques :
- Vérifier la taille du payload ; pour des objets volumineux, stocker sur S3 et transmettre un lien.
- Inclure des métadonnées (horodatage, requestId) facilite le traçage entre producer et consumer.
- Rendre le consumer idempotent : les nouvelles tentatives et les livraisons multiples décrites plus haut peuvent traiter deux fois le même événement. Un identifiant unique dans le payload, enregistré après traitement (par exemple dans DynamoDB avec une écriture conditionnelle), permet d'ignorer les doublons.
Nettoyage
La suppression des ressources commence par la suppression de la Function URL si elle n'est pas nécessaire, puis par la suppression de la fonction :
aws lambda delete-function-url-config --function-name http-function-url-tutorial
aws lambda delete-function --function-name http-function-url-tutorial
# Le groupe de logs n'est pas supprimé avec la fonction
aws logs delete-log-group --log-group-name /aws/lambda/http-function-url-tutorial
Après suppression de la fonction, supprimer le rôle IAM si celui-ci n'est plus utilisé. Par défaut, les groupes de logs créés par Lambda conservent les logs indéfiniment : une durée de rétention (aws logs put-retention-policy) évite l'accumulation de coûts de stockage sur les fonctions conservées.
Conclusion
Une fonction Lambda associe un handler, un rôle d'exécution et un déclencheur ; la Function URL fournit un point d'entrée HTTP sans API Gateway. Le cycle Init / Invoke / Shutdown explique à la fois les cold starts et l'intérêt d'initialiser les ressources hors du handler, et l'invocation asynchrone entre fonctions impose des consommateurs idempotents. Les ressources annexes (groupe de logs, rôle IAM) survivent à la suppression de la fonction et se nettoient séparément.