Le Blog Amazon Web Services
Nouveauté pour AWS Lambda – Prise en charge des images de conteneur
Avec AWS Lambda, vous chargez votre code et l’exécutez sans que vous ayez à mettre en service ou à gérer des serveurs. De nombreux clients apprécient ce mode de fonctionnement, mais si vous avez investi dans la conteneurisation lors de vos cycles de développement, il n’était pas facile d’utiliser la même approche pour créer des applications à l’aide de Lambda.
Pour vous aider, vous pouvez désormais packager et déployer des fonctions Lambda sous forme d’images de conteneur d’une taille maximale de 10 Go. Vous pouvez aussi facilement construire et déployer des applications plus importantes qui reposent sur des dépendances de taille plus important, comme le Machine Learning ou les traitements intensifs de données. Tout comme les fonctions packagées sous forme d’archives ZIP, les fonctions déployées sous forme d’images de conteneur bénéficient de la même simplicité opérationnelle, de la mise à l’échelle automatique, de la haute disponibilité et des intégrations natives avec de nombreux services AWS.
Nous fournissons des images de base pour tous les moteurs d’exécution Lambda pris en charge (Python, Node.js, Java, .NET, Go, Ruby) afin que vous puissiez facilement ajouter votre code et vos dépendances. Nous proposons également des images de base pour les moteurs d’exécution personnalisés basés sur Amazon Linux que vous pouvez étendre pour inclure votre propre moteur d’exécution implémentant l’API Lambda Runtime.
Vous pouvez déployer vos propres images de base sur Lambda, par exemple des images basées sur les distributions Linux Alpine ou Debian. Pour fonctionner avec Lambda, ces images doivent implémenter l’API Lambda Runtime. Pour faciliter la construction de vos propres images de base, nous publions des clients d’interface d’exécution Lambda qui implémentent l’API Lambda Runtime pour tous les environnements d’exécution pris en charge. Ces implémentations sont disponibles via les gestionnaires de paquets natifs, afin que vous puissiez facilement les intégrer dans vos images, et sont partagées avec la communauté sous une licence Open Source.
Nous lançons également en Open Source un émulateur d’interface d’exécution Lambda (Lambda Runtime Interface Emulator) qui vous permet d’effectuer des tests en local de l’image du conteneur et de vérifier qu’elle fonctionnera lorsqu’elle sera déployée vers Lambda. Le Lambda Runtime Interface Emulator est inclus dans toutes les images de base fournies par AWS et peut également être utilisé avec toute autre image.
Vos images de conteneur peuvent également utiliser l’API Lambda Extensions pour intégrer des outils de surveillance, de sécurité et autres à l’environnement d’exécution Lambda.
Pour déployer une image de conteneur, vous en sélectionnez une dans un référentiel Amazon Elastic Container Registry (ECR). Voyons comment cela fonctionne en pratique à l’aide de quelques exemples, en utilisant d’abord une image fournie par AWS pour Node.js, puis en créant une image personnalisée pour Python.
Utilisation de l’image de base fournie par AWS pour Node.js
Voici le code (app.js
) d’une simple fonction Lambda Node.js générant un fichier PDF à l’aide du module PDFKit. À chaque invocation, elle crée un nouveau mail contenant des données aléatoires générées par le module faker.js. La sortie de la fonction utilise la syntaxe d’Amazon API Gateway pour renvoyer le fichier PDF.
Nous utilisons npm
pour initialiser le paquet et ajouter les trois dépendances dont nous avons besoin dans le fichier package.json
. De cette façon, nous créons également le fichier package-lock.json
. Nous l’ajoutons à l’image du conteneur pour avoir un résultat plus reproductible.
Maintenant, nous créons un fichier Dockerfile
pour créer l’image du conteneur pour notre fonction Lambda, en partant de l’image de base fournie par AWS pour le moteur d’exécution nodejs12.x
. Toutes les images de base fournies par AWS sont disponibles sur Docker Hub et Amazon ECR Public. Dans ce cas, nous utilisons l’image de base hébergée dans Docker Hub :
Pour utiliser l’image dans Amazon ECR Public, nous pouvons remplacer la première ligne par :
Le fichier Dockerfile ajoute le code source (app.js
) et les fichiers décrivant le paquet et les dépendances (package.json
et package-lock.json
) à l’image de base. Ensuite, nous lançons npm
pour installer les dépendances. Nous avons défini le CMD
sur le gestionnaire de fonction, mais cela pourrait également être surchargé lors de la configuration de la fonction Lambda.
Nous utilisons la CLI de Docker pour construire localement l’image du conteneur random-letter
:
Pour vérifier si cela fonctionne, nous démarrons l’image du conteneur localement en utilisant l’émulateur d’interface d’exécution Lambda :
Maintenant, nous testons une invocation de fonction avec cURL. Ici, nous passons une payload JSON vide.
S’il y a des erreurs, nous pouvons les corriger localement. Si cela fonctionne, nous passons à l’étape suivante.
Pour charger l’image du conteneur, nous créons un nouveau référentiel Amazon ECR dans notre compte et nous balisons l’image locale pour la pousser vers ECR. Pour nous aider à identifier les vulnérabilités logicielles dans nos images de conteneur, nous activons l’analyse d’image ECR.
Ici, nous utilisons la console AWS pour terminer la création de la fonction. Vous pouvez également utiliser l’AWS Serverless Application Model (SAM), qui a été mis à jour pour ajouter la prise en charge des images de conteneurs.
Dans la console Lambda, nous cliquons sur Créer une fonction. nous sélectionnons Image de conteneur, donnons un nom à la fonction, puis nous cliquons sur Parcourir les images pour rechercher la bonne image dans mes référentiels ECR.
Après avoir sélectionné le référentiel, nous utilisons la dernière image (latest
, qui est pratique pour nos tests, mais qui n’est pas forcément recommandé en production) que nous avons chargée. Lorsque nous sélectionnons l’image, la Lambda la traduit en empreinte numérique (digest) de l’image sous-jacente (à droite de la balise dans l’image ci-dessous). Vous pouvez voir l’empreinte numérique de vos images localement avec la commande docker images --digests
. De cette façon, la fonction utilise la même image même si la dernière balise est passée à une plus récente, et vous êtes protégés contre les déploiements involontaires. Vous pouvez mettre à jour l’image à utiliser dans le code de la fonction. La mise à jour de la configuration de la fonction n’a aucun impact sur l’image utilisée, même si la balise a été réaffectée à une autre image entre-temps.
En option, nous pouvons remplacer certaines des valeurs de l’image du conteneur. Nous ne le faisons pas maintenant, mais de cette façon, nous pouvons créer des images qui peuvent être utilisées pour différentes fonctions, par exemple en modifiant le gestionnaire de fonction dans la valeur CMD
.
Nous laissons toutes les autres options à leur valeur par défaut et nous sélectionnons Créer une fonction.
Lors de la création ou de la mise à jour du code d’une fonction, la plateforme Lambda optimise les nouvelles images de conteneurs et leurs mises à jour pour les préparer à recevoir des invocations. Cette optimisation prend quelques secondes voire minutes, en fonction de la taille de l’image. Après cela, la fonction est prête à être invoquée. Nous testons la fonction dans la console depuis l’onglet Tester puis en cliquant sur Tester.
Cela fonctionne ! Maintenant, ajoutons l’API Gateway comme déclencheur. Nous sélectionnons Ajouter un déclencheur et ajoutons l’API Gateway en utilisant une API HTTP. Pour simplifier, nous laissons l’API sans authentification pour nos tests (en production, il est recommandé d’avoir une stratégie d’authentification pour maîtriser les accès).
Maintenant, nous cliquons plusieurs fois sur le point de terminaison (endpoint) de l’API et nous téléchargeons quelques mails au hasard.
Cela fonctionne comme prévu ! Voici quelques-uns des fichiers PDF qui sont générés avec des données aléatoires provenant du module faker.js.
Construction d’une image personnalisée pour Python
Il est parfois nécessaire d’utiliser vos images de conteneur personnalisées, par exemple pour respecter les directives de votre entreprise ou pour utiliser une version du moteur d’exécution que nous ne prenons pas en charge.
Dans ce cas, nous souhaitons construire une image pour utiliser Python 3.9. Le code (app.py
) de notre fonction est très simple, nous voulons juste dire bonjour avec la version de Python qui est utilisée.
Comme nous l’avons déjà mentionné, nous partageons avec vous des implémentations Open Source des clients de l’interface d’exécution Lambda (qui mettent en œuvre la Runtime API) pour tous les environnements d’exécution pris en charge. Dans ce cas, nous commençons par une image Python basée sur Alpine Linux. Ensuite, nous ajoutons le client Lambda Runtime Interface Client for Python à l’image. Voici le fichier Dockerfile
:
Cette fois, le fichier Dockerfile est plus détaillé et construit l’image finale en trois étapes, conformément aux meilleures pratiques de Docker en matière de construction en plusieurs étapes. Vous pouvez utiliser cette approche en trois étapes pour construire vos propres images personnalisées :
- L’étape 1 consiste à construire l’image de base avec le moteur d’exécution, Python 3.9 dans ce cas, et GCC que nous utilisons pour compiler et lier les dépendances à l’étape 2,
- L’étape 2 consiste à installer le client d’interface d’exécution Lambda (Lambda Runtime Interface Client) et à construire la fonction et les dépendances,
- L’étape 3 consiste à créer l’image finale en ajoutant le résultat de l’étape 2 à l’image de base construite à l’étape 1. Ici, nous ajoutons aussi le Lambda Runtime Interface Emulator, mais c’est optionnel (voir ci-dessous).
Nous créons le script entry.sh
ci-dessous pour l’utiliser comme ENTRYPOINT
. Il exécute le client d’interface d’exécution Lambda pour Python (Lambda Runtime Interface Client for Python). Si l’exécution est locale, le client d’interface d’exécution est enveloppé par le Lambda Runtime Interface Emulator.
Maintenant, nous pouvons utiliser le Lambda Runtime Interface Emulator pour vérifier localement si la fonction et l’image du conteneur fonctionnent correctement :
Sans inclure l’émulateur d’interface d’exécution Lambda dans l’image du conteneur
Il est facultatif d’ajouter l’émulateur d’interface d’exécution Lambda à une image de conteneur personnalisée. Si nous ne l’incluons pas, nous pouvons tester localement en installant le Lambda Runtime Interface Emulator sur notre machine locale en suivant ces étapes :
- Dans l’étape 3 du fichier Dockerfile, nous supprimons les commandes copiant le Lambda Runtime Interface Emulator (
aws-lambda-rie
) et le scriptentry.sh
. Nous n’avons pas besoin du scriptentry.sh
dans ce cas. - Nous utilisons cet
ENTRYPOINT
pour démarrer par défaut le client Lambda Runtime Interface :
ENTRYPOINT [ "/usr/local/bin/python", "-m", "awslambdaric" ]
- Nous exécutons ces commandes pour installer le Lambda Runtime Interface Emulator sur notre machine locale, par exemple sous
~/.aws-lambda-rie
:
Tester l’image personnalisée pour Python
Lorsque le conteneur est exécuté localement, nous pouvons tester l’invocation d’une fonction avec cURL :
Le résultat est conforme à nos attentes !
Nous chargeons l’image sur ECR et crée la fonction comme précédemment. Voici notre test dans la console :
Notre image de conteneur personnalisée basée sur Alpine fait tourner Python 3.9 sur Lambda !
Disponible dès maintenant
Vous pouvez utiliser des images de conteneurs pour déployer vos fonctions Lambda dès aujourd’hui.
La prise en charge des images de conteneurs est proposée en plus des archives ZIP et nous continuerons à prendre en charge le format de package ZIP.
Il n’y a pas de frais supplémentaires pour utiliser cette fonctionnalité. Vous payez pour le référentiel ECR et le coût Lambda habituel.
Vous pouvez utiliser la prise en charge des images de conteneur dans AWS Lambda avec la console, l’interface de ligne de commande (CLI) d’AWS, les SDK d’AWS, le Serverless Application Model (SAM) d’AWS, le Cloud Development Kit (CDK) d’AWS, les boîtes à outils AWS pour Visual Studio, VS Code et JetBrains, et les solutions des partenaires AWS, notamment Aqua Security, Datadog, Epsagon, HashiCorp Terraform, Honeycomb, Lumigo, Pulumi, Stackery, Sumo Logic et Thundra.
Article original contribué par Danilo Poccia, Chief Evangelist (EMEA) et adapté en français par Charles Rapp, Architecte de Solutions dans l’équipe AWS France.