TP 3 - Lambda đ
đ§± Mise en place
Allez sur la plateforme AWS Academy et accédez au cours AWS Academy Learner Lab [43226]. Puis cliquez sur Modules
> Learner Lab
. Lancez votre environnement en cliquant sur Start Lab
. Une fois le cercle passé au vert, cliquez sur AWS Details
et AWS CLI
. Les clés que vous voyez vont permettre un accÚs programmatique à votre compte. Cherchez le dossier .aws
sur votre machine puis remplacez le contenu du fichier credentials
par les clefs que vous venez de récupérer.
Ma premiĂšre Lambda
đ DĂ©finition de la Lambda
Une fois sur la console AWS, cherchez le service Lambda
dans la barre de recherche. Sur le tableau de bord Lambda, cliquez sur Créer une fonction
. Laissez lâoption CrĂ©er Ă partir de zĂ©ro
cochĂ©e, donnez un nom Ă votre fonction Lambda, et, pour le langage dâexĂ©cution sĂ©lectionnez Python3.12
. Conservez lâarchitecture x86_64, et dĂ©pliez Modifier le rĂŽle d'exĂ©cution par dĂ©faut
, sélectionnez Utiliser un rÎle existant
et sélectionnez le rÎle LabRole
. Créez votre fonction.
đ§ââïž Ă la diffĂ©rence des instances EC2, une fonction Lambda a besoin dâun rĂŽle pour fonctionner. Sans entrer dans les dĂ©tails, un rĂŽle va dĂ©terminer les droits de la fonction. Comme votre compte nâa pas le droit de crĂ©ation de rĂŽle, vous ne pouvez pas crĂ©er un rĂŽle Ă la volĂ©e, et il faut sĂ©lectionner le rĂŽle
LabRole
déjà créé.
Une fois sur la page de votre fonction, un code de base est proposé par AWS. Ce code retourne simplement un code 200 et le texte Hello from Lambda!
. Vous allez lancer cette fonction via le bouton Test
. CrĂ©ez un nouvel Ă©vĂ©nement de test, que lâon va appeler test_basique
, et laissez le JSON de base. Votre événement de test sera un simple JSON de la forme :
{
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
Enregistrez-le et cliquez de nouveau sur Test
. Normalement, tout devrait bien se passer.
Maintenant, vous allez lĂ©gĂšrement modifier la fonction. Au lieu de simplement retourner une chaĂźne de caractĂšres fixe, elle va retourner lâheure actuelle. Importez la classe datetime
du module éponyme et utilisez le code datetime.now().strftime("%m/%d/%Y, %H:%M:%S")
pour avoir lâheure et la date du jour sous forme de chaĂźne de caractĂšres. Comme votre fonction a Ă©tĂ© modifiĂ©e, il faut la redĂ©ployer avec le bouton Deploy
. Une fois fait, testez-la de nouveau pour voir si tout fonctionne.
Ajout de lâinvocation toutes les minutes
Sur la page de votre Lambda, cliquez sur + Ajouter un déclencheur
. La source va ĂȘtre EventBridge
. Créez une nouvelle rÚgle avec le nom minuteur
. Le type de rĂšgle sera Expression de planification
et lâexpression rate(1 minute)
.
đ§ââïž EventBridge permet de gĂ©rer les Ă©vĂ©nements comme des alarmes quand un seuil est dĂ©passĂ©, mais aussi les Ă©vĂ©nements planifiĂ©s.
Votre fonction sera dĂ©sormais appelĂ©e toutes les minutes. Malheureusement, comme il nây a pas de destination pour votre fonction, les rĂ©sultats disparaissent dans le nĂ©ant du cloud. Il est toutefois possible de voir quâelle est invoquĂ©e en allant sur lâonglet Surveiller
puis Journaux
. Vous allez voir une ligne par minute, mais comme notre fonction ne log rien, vous nâallez voir aucun rĂ©sultat.
đ§ââïž Il est possible dâajouter un logger (utile pour le debug) en faisant des
print()
(ce nâest pas idĂ©al), ou en utilisant le modulelogging
.import os import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def Lambda_handler(event, context): logger.info('## ENVIRONMENT VARIABLES') logger.info(os.environ) logger.info('## EVENT') logger.info(event)
âïž Automatiser ce dĂ©ploiement
En vous aidant du code disponible ici https://github.com/HealerMikado/Ensai-CloudComputingLab3, créez un script terraform pour automatiser ce déploiement.
đšPousser les rĂ©sultats dans une file SQS
Maintenant, vous allez faire en sorte que votre fonction envoie ses rĂ©sultats dans une file SQS. Cherchez le service SQS et crĂ©ez une file. Choisissez le type Standard et donnez-lui le nom de votre choix. Gardez toutes les valeurs par dĂ©faut et crĂ©ez votre file. Copiez lâURL de la file.
Retournez sur la page de votre Lambda et modifiez le code pour publier dans la file SQS en vous aidant du code suivant :
import json
import boto3
from datetime import datetime
sqs = boto3.client('sqs') #client is required to interact with sqs
def Lambda_handler(event, context):
# event provenant d'une Lambda
data = int(json.loads(event["Records"][0]["body"])["data"])
sqs.send_message(
QueueUrl="VOTRE URL SQS",
MessageBody=json.dumps({"body" : data})
)
return {
'statusCode': 200,
'body': data
}
Déployez la nouvelle fonction, puis attendez quelques minutes. Ensuite, retournez sur la page de votre file SQS et cliquez sur Envoyer et recevoir des messages
, puis sur Rechercher des messages
. Vous devriez voir des messages apparaĂźtre. Cliquez sur lâun dâeux et vous devriez voir votre message.
đ FĂ©licitations ! Vous venez de mettre en place une architecture 100% serverless qui va rĂ©aliser un traitement toutes les minutes et pousser le rĂ©sultat dans une file pour ĂȘtre utilisĂ© par un autre service par la suite. MĂȘme si le code Python du traitement est assez simple, lâarchitecture, elle, ne lâest pas. Vous pourriez par exemple, avec ce systĂšme, faire une requĂȘte toutes les heures Ă un webservice pour mettre Ă jour des donnĂ©es en base.
đ§źUne calculatrice
Maintenant vous allez rĂ©aliser une calculatrice en utilisant une fonction Lambda. Voici le schĂ©ma dâarchitecture globale.
Vous allez devoir créer :
- Deux files SQS, une pour lâinput et une pour lâoutput.
- Une fonction Lambda qui va aller chercher les clés
number1
,number2
etoperation
et faire le calcul demandĂ©. Les opĂ©rations que lâon souhaite faire sont lâaddition, la soustraction, la multiplication et la division.
Le déclencheur de la fonction Lambda passe des paramÚtres dans le dictionnaire event
. Pour obtenir la clé number1
, vous devez faire float(json.loads(event["Records"][0]["body"])["number1"])
.
đ§ââïž Pour vous aider Ă comprendre ce code, les messages rĂ©cupĂ©rĂ©s par la Lambda sont dans la clĂ©
Records
. SQS nâenvoie pas les messages Ă la fonction Lambda, câest la fonction qui les pull. Sauf quâelle peut en rĂ©cupĂ©rer plusieurs Ă la fois, et la clĂ©Records
est une liste. Pour simplifier, on ne regarde que le premier message, dâoĂč leevent["Records"][0]
. Si vous avez envie, vous pouvez boucler sur les éléments de la liste. Ensuite, chaque message est contenu dans la clébody
. Les messages sont considĂ©rĂ©s comme des strings car il nây a aucune raison que ce soit un JSON, donc il nous faut le transformer en dictionnaire avec unjson.loads()
. Enfin, il est possible de rĂ©cupĂ©rer les clĂ©s que lâon souhaite. Attention Ă leur type ! Il faut spĂ©cifier que les nombres sont bien des nombres.
Pour tester votre application, vous pouvez :
- Faire un test via lâonglet test de la fonction Lambda avec le JSON suivant :
{
"Records": [
{
"messageId": "bc8007e9-6a6d-41d4-ba09-2fcf16e5e6c3",
"receiptHandle": "AQEB92BoJQllWCtZSiiIQ69fXXX4ac7cpxxcbTirw4/b+ziBTzAxlwXFMbj3w6wbOPom4jPusM9453dZDXi4iVH/vf97fFk6yg/EkP9UZRYrK5OwfWiIxQJkklWe8ZKK84uYVhGIDi5kBfWTCnsX6u83+GE59g/UWc0+jbYvOArOLwCCOTRqbH3spkG/GhDHlyxVwPv/K+xNM+7pqQX21yjSQdiLwwlk7dDJwiNGatRq9D1vIDHduabmHn2I1sLrq778ZkZXS4YJ6IYeFXC+kWVYlSy+lXyVxHfxBVXQcU8PsSNv6MsoBDgjU1LD43NFikQLVI5F/+HnBEX2AzhoJPBMz/eijKW1miJNZ48G9gg2H2DOt0x2OQtg2M2VqtxROmD06gHUPsr67vvBH2J5m77Oxw==",
"body": "{\n\"number1\":1,\n\"number2\":5,\n\"operation\":\"+\"\n}",
"attributes": {
"ApproximateReceiveCount": "18",
"SentTimestamp": "1681393246569",
"SenderId": "AROAZ2UVGELJYYC7FJZIV:user2476414=__tudiant_test",
"ApproximateFirstReceiveTimestamp": "1681393246569"
},
"messageAttributes": {},
"md5OfBody": "cb76cceb2fbc7622690cdf4f256ea8e0",
"eventSource": "aws:sqs",
"eventSourceARN": "arn:aws:sqs:us-east-1:675696485075:lab-input-queue",
"awsRegion": "us-east-1"
},{
"messageId": "bc8007e9-6a6d-41d4-ba09-2fcf16e5e6c3",
"receiptHandle": "AQEB92BoJQllWCtZSiiIQ69fXXX4ac7cpxxcbTirw4/b+ziBTzAxlwXFMbj3w6wbOPom4jPusM9453dZDXi4iVH/vf97fFk6yg/EkP9UZRYrK5OwfWiIxQJkklWe8ZKK84uYVhGIDi5kBfWTCnsX6u83+GE59g/UWc0+jbYvOArOLwCCOTRqbH3spkG/GhDHlyxVwPv/K+xNM+7pqQX21yjSQdiLwwlk7dDJwiNGatRq9D1vIDHduabmHn2I1sLrq778ZkZXS4YJ6IYeFXC+kWVYlSy+lXyVxHfxBVXQcU8PsSNv6MsoBDgjU1LD43NFikQLVI5F/+HnBEX2AzhoJPBMz/eijKW1miJNZ48G9gg2H2DOt0x2OQtg2M2VqtxROmD06gHUPsr67vvBH2J5m77Oxw==",
"body": "{\n\"number1\":1,\n\"number2\":5,\n\"operation\":\"+\"\n}",
"attributes": {
"ApproximateReceiveCount": "18",
"SentTimestamp": "1681393246569",
"SenderId": "AROAZ2UVGELJYYC7FJZIV:user2476414=__tudiant_test",
"ApproximateFirstReceiveTimestamp": "1681393246569"
},
"messageAttributes": {},
"md5OfBody": "cb76cceb2fbc7622690cdf4f256ea8e0",
"eventSource": "aws:sqs",
"eventSourceARN": "arn:aws:sqs:us-east-1:675696485075:lab-input-queue",
"awsRegion": "us-east-1"
}
]
}
-
CrĂ©ez un message dans la queue dâinput et voyez si le rĂ©sultat apparaĂźt dans la queue dâoutput. Voici un exemple de message :
{"number1":1,"number2":5,"operation":"+"}
đ FĂ©licitations, vous venez de mettre en place une architecture 100% serverless avec trois services qui communiquent entre eux. Mettre des files entre des services permet de dĂ©coupler les services et dâavoir un systĂšme plus modulable. Par exemple, dans notre cas, notre Lambda ne sait pas dâoĂč proviennent les donnĂ©es, elle sait juste les prendre depuis une file. Ainsi, la source des donnĂ©es peut changer, du moment que la nouvelle source alimente la file SQS, il nây aura pas de raison de changer la Lambda. De la mĂȘme maniĂšre, notre Lambda ne se prĂ©occupe pas du service qui va utiliser les donnĂ©es quâelle produit. Elle les dĂ©pose simplement dans une file pour quâun consommateur puisse les rĂ©cupĂ©rer. Les files SQS agissent comme des zones tampons entre les services.
Sâil vous reste du temps pendant le TP, commencez le TP notĂ©.