/ serverless

Un « Hello World » sans serveur avec Node, AWS Lambda et Serverless

Sans serveur dites-vous ?

 
Depuis environ un an, il y a un terme qui revient sans arrêt avec insistance dans les diverses communications que je lis : serverless. Ce mot résonne encore et encore.

Qu’est-ce qui fait que la notion d’architecture sans serveur semble si cool tout à coup ? Jusque-là, lorsque l’on avait besoin d’exécuter du code en backend (c’est-à-dire pas sur la machine cliente), il était nécessaire de le placer sur un serveur, doté d’un système d’exploitation et de logiciels en mesure de faire tourner ce code. D'abord, il a fallu que ce soit un serveur physique : un ordinateur, dans un datacentre ou ailleurs, avec un accès physique au réseau. Puis sont apparues les technologies de virtualisation, qui ont permis, sur un même serveur physique, d’exposer plusieurs serveurs virtuels, visibles comme autant de machines indépendantes. Puis ces technologies se sont améliorées et de nombreuses machines virtuelles peuvent être aujourd’hui réparties sur de nombreux serveurs physiques, avec des capacités de redondance avancées. C’est la révolution Platform As A Service (PaaS).

Cependant, un serveur, qu’il soit physique ou virtuel, nécessite d’y installer un système d’exploitation, les logiciels qui vont permettre l’exécution du code, de la surveillance, et de la maintenance. Pour pouvoir passer des pics de charge et pour augmenter la tolérance aux pannes, il faudra de plus envisager d’en faire tourner plusieurs en parallèle (clusterisation), cela nécessitant un niveau supplémentaire de maintenance et de surveillance.

Puis le Cloud Computing ayant pris un essor considérable, certains se sont alors posé la question de pouvoir exécuter du code publiquement, dans le Cloud, de manière indépendante de toute machine, système d’exploitation, sans que le développeur n’aie à se soucier de l’infrastructure sous-jacente. Je pense que c’est une nouvelle révolution qui s’amorce, aussi importante que celle du PaaS, qui a permis l’émergence du Cloud Computing moderne. On commence à parler de Function as A Service (FaaS), et cela permet d’envisager un changement radical de point de vue : Imaginez n’avoir à gérer que vos fonctions logicielles. Plus de gestion de serveurs. Vous n’avez plus à vous préoccuper que du code. Cela sonne plutôt bien…

Dans le concept FaaS, nous avons la possibilité de déployer n’importe quel morceau de code dans le Cloud. Un évènement (par exemple une requête HTTP) déclenche l’appel de la fonction. Celle-ci retourne alors une valeur (par exemple dans la réponse HTTP), et le processus est terminé, jusqu’au prochain déclenchement. Si vous avez déjà écrit une API REST, vous vous sentirez comme chez vous. Tous les services et les points de terminaison que vous conserviez habituellement à un endroit seront seulement maintenant découpés en un tas de petits snippets, des microservices. L’objectif est de s’abstraire complètement des serveurs du point de vue des développeurs. Ce type de services est évidemment très facile à mettre à l'échelle pour s’adapter à la charge, cela étant complètement transparent pour le développeur. L’exploitant qui assure l’infrastructure facture alors le service en fonction de la demande, généralement au temps de calcul utilisé. Évidement, la capacité de traitement évolue automatiquement en fonction de la demande : vous n’aurez plus à vous demander si votre instance EC2 est suffisante…

FaaS commence à être quelque chose d’abouti, car il y a eu quelques problèmes de jeunesse, qui ont été résolus.

L'infrastructure cachée

 
Pour comprendre comment écrire des applications sans serveur, nous devons d'abord aborder le sujet de ce qui se cache derrière tout cela. Quels sont les outils et services à notre disposition qui rendent la chose possible ?

Plusieurs acteurs se sont mis sur ce marché. Parmi les géants, on trouve évidemment Google avec Google Cloud Functions, et Amazon avec AWS Lambda. Dans cet article, nous allons présenter l’offre de Amazon Web Services : Lambda.

AWS Lambda

« AWS Lambda est un service cloud qui vous permet d'exécuter du code sans provisionner ou gérer de serveurs. » (documentation AWS)

C’est le cœur du système proposé par Amazon. Les fonctions Lambda peuvent réagir à tout un tas d’évènements, comme par exemple l’ajout de données dans un bucket S3, ou bien comme nous allons le voir, à une requête HTTP (sur un « Endpoint »).

AWS API Gateway

Le déclenchement sur requête HTTP est rendu possible par la passerelle API (API Gateway). Gateway fournit les points de terminaison REST qui déclenchent les fonctions. Imaginez une application Express de base. Vous créez généralement une méthode app.get() pour une route particulière, comme ceci :

app.get('/', function(req, res, next) {
    /* executer un code */
});

 
Quand un utilisateur appelle la route /, un évènement déclenche la fonction de callback associée. Chez AWS, la passerelle est la route, Lambda est la fonction de callback.

Le framework Serverless

Il est en théorie possible de créer des fonctions Lambda ainsi que les routes les déclenchant via l’API Gateway intégralement depuis la console Amazon Web Services. Ce n’est cependant pas une sinécure. Lors de mon premier essai, j’ai passé une journée entière à essayer de comprendre quoi faisait quoi. La documentation est très complexe, et pas vraiment « beginner friendly ».

Il existe cependant un framework sous forme d’un module npm, serverless, qui permet de complètement automatiser tout le processus.

Le framework Serverless regroupe tous les outils dont vous avez besoin dans un package facile à mettre en œuvre, simplifiant la création et le déploiement d’applications sans serveur. Il s’occupe de toutes les tâches fastidieuses que vous auriez autrement à faire dans la console AWS, comme la création de fonctions et la connexion aux événements.

On se jette à l'eau !

 
Allons-y et créons notre première fonction. Je vais exposer tout le processus sous la forme d’un tutoriel pas à pas pour un bon vieux « Hello World », le but ici n’étant pas de vous apprendre à programmer une API REST, mais juste de vous montrer comment déployer une fonction serverless.

1. Installer serverless globalement

 
Dans un terminal :

$ npm install -g serverless

 
Serverless est maintenant installé de manière globale sur votre machine. Les commandes Serverless sont maintenant disponibles dans le terminal où que vous soyez. Notez que sur Linux, vous devrez faire cette installation en tant que super-utilisateur ou sous sudo.

2. Créer un utilisateur IAM dans la console AWS

 
Si ce n’est déjà fait, créez-vous un compte Amazon Web Services. Un compte gratuit suffit largement pour faire de nombreux tests, vous n’avez pas à vous inquiéter de casser votre tirelire. Une fois votre compte validé, ouvrez la console AWS et ouvrez le menu déroulant « services » du coin en haut à gauche. Vous verrez une foule de services s’afficher. Inscrivez IAM dans le champ de recherche et lancez la recherche.

AWS_IAM_1

Vous serez dirigés vers la page principale IAM de votre compte. Déroulez le pavé « Créer des utilisateurs IAM » et cliquez le bouton « Gestion des utilisateurs ». Cliquez alors le bouton bleu en haut à gauche « Ajouter un utilisateur ».

AWS_IAM_2

Donnez-lui un nom, ainsi que les droits Accès par programmation. Puis passez à l’étape suivante.

AWS_IAM_3

Vous pouvez maintenant ajouter une série de permissions à l’utilisateur. Comme nous allons confier à Serverless le soin de créer ou effacer de nombreux assets, soyons radicaux : cliquez sur « Attacher directement les stratégies existantes » puis en dessous cochons AdministratorAccess.

AWS_IAM_4

En passant à l’étape suivante, vous verrez que l’utilisateur a été créé. Cliquez sur le bouton bleu en bas. Vous pouvez maintenant voir l’ID de clé d’accès et la Clé d’accès secrète. Prenez-en bonne note ou bien téléchargez le fichier .csv, et gardez cela de côté, en lieu très, très sûr… Ce sont des données critiques, qu’il est important de conserver à l’abri et de protéger.

Ceci étant fait, nous pouvons avancer en entrant ces clés dans la configuration Serverless.

3. Entrer les clés IAM dans la configuration serverless

 
Revenez à votre terminal et tapez ce qui suit en une seule ligne, en remplaçant bien entendu par les valeurs récupérées ci-dessus :

$ serverless config credentials –provider aws –key xxxxxxxxxxxxxxxx –secret  xxxxxxxxxxxxxxxx

 
À partir de maintenant , votre installation Serverless est prête pour exécuter vos commandes.

4. Créer votre premier service

 
Créez un nouveau répertoire pour héberger vos services applicatifs Serverless. Ouvrez-y un terminal, vous êtes prêts à créer un service. Qu’est-ce qu’un service me direz-vous ? Vous pouvez voir cela un peu comme un projet… C’est l’endroit où vous définissez des fonctions AWS Lambda, les évènements qui vont les déclencher et toute l’infrastructure AWS requise.

Entrez dans votre terminal :

$ serverless create –template aws-nodejs –path hello-world

 
Cette commande va créer un nouveau service. Il faut indiquer un template pour cette fonction. Nous y indiquons aws-nodejs, qui va définir le runtime sur node.js, ce que nous voulions. Le path va créer un répertoire pour le service, ici nommé hello-world.

5. Explorer le répertoire du service avec un éditeur de code

 
Ouvrez le dossier hello-world avec votre éditeur de code favori. Il devrait s’y trouver trois fichiers. Le fichier serverless.yml contient toutes les informations de configuration du service. Ici vous allez spécifier des options de configuration générales aussi bien que fonction par fonction. Il devrait pour l’instant ressembler à ceci, avec une tonne de lignes de commentaires, non reproduites ici :

# serverless.yml 
service: hello-world

provider:
  name: aws
  runtime: nodejs6.10

functions:
  hello:
    handler: handler.hello

La propriété functions liste toutes les fonctions du service. Vous pouvez voir que hello est actuellement l’unique fonction définie dans le fichier handler.js. La propriété handler pointe sur le fichier et le module contenant le code de votre fonction. Par défaut, ce fichier se nomme handler.js.

En ouvrant handler.js, vous verrez le module et la fonction nommée hello. La fonction prend trois paramètres. Le paramètre event représente les données d’évènement passées à la fonction. Le paramètre context renseigne la fonction sur le contexte dans lequel elle a été appelée, son temps de traitement, son état et d’autres informations importantes. Le dernier paramètre est une fonction de callback qui va renvoyer des données en retour. Dans cet exemple, la réponse est renvoyée dans le second paramètre de la fonction de callback. Le premier représente toujours une erreur, et contiendra null si tout s’est bien passé.

// handler.js

module.exports.hello = (event, context, callback) => {
	const response = { statusCode : 200, body : 'Bonjour le monde !'};
	callback(null, response);
} ;

 
Cela est très bien, mais nous ne pouvons pas encore déclencher la fonction. Il n’y a pas d’évènement qui y soit connecté. Pour gérer cela, revenons dans serverless.yml, décommentez et modifiez les lignes où vous voyez events:

# serverless.yml
service: hello-world

provider:
  name: aws
  runtime: nodejs6.10

functions:
  hello:
    handler: handler.hello
    events:  # décommentez ces lignes
      - http:
        path: hello
        method: get

Vérifiez bien que vous respectez bien l’indentation du fichier : events devrait se situer juste au même niveau sous handler. Il est maintenant temps de déployer la fonction sur AWS.

6. Déploiement sur AWS Lambda

 
Cela est très facile et rapide. Dans le répertoire du service, lancez cette commande :

$ serverless deploy -v

 
Vous allez voir dans votre terminal fleurir de nombreux messages, cela étant dû à l’option -v , qui signifie bien entendu verbose.

AWS_deploy

Mais le plus important, dans ces messages, c’est que vous y obtiendrez le point d’entrée. Serverless a automatiquement créé une passerelle API et l’a connectée à la fonction Lambda. Vérifions tout de suite : si nous entrons ce point d’accès dans la barre d’adresse du navigateur, nous obtenons la réponse « Bonjour le Monde ! » souhaitée.

Vous pouvez aussi tester la fonction en ligne de commande en tapant :

$ serverless invoke -f hello -l

 
Cela va renvoyer l’objet réponse en entier avec aussi des informations sur l’état de la fonction, comme le temps de réponse et l’utilisation mémoire.

Tester l'application en local

 
Lors de la mise au point de fonctions évoluées, il peut cependant être vraiment pénible de devoir déployer la fonction à chaque fois que l’on veut la tester.

Heureusement, il existe Serverless Offline, un module npm qui permet de tester tout le code localement avant de pousser sur AWS.

1. Créer package.json dans le répertoire du service

 
Rendez-vous dans un terminal dans le répertoire hello-world et lancez, en répondant aux questions habituelles :

$ npm init

 
Ceci va créer le traditionnel fichier package.json dans le répertoire du service.

2. Installer Serverless Offline

 
On fait alors une installation de module de développement classique :

$ npm install serverless-offline --save-dev

 
Ajoutons alors deux nouvelles lignes à serverless.yml pour porter à la connaissance du framework les nouvelles commandes :

# serverless.yml
service: my-service

provider:
  name: aws
  runtime: nodejs6.10

functions:
  hello:
    handler: handler.hello
    events:
      - http:
        path: hello/get
        method: get

# ajouter ces deux lignes
plugins:
  - serverless-offline

Pour être certains que vous avez tout installé correctement, lancez la commande :

$ serverless

 
Vous devriez voir deux lignes commençant par offline dans les différents choix proposés.

3. Lancer la fonction localement

 
Si tout va bien, vous disposez maintenant sur votre machine locale d’une véritable émulation de Lambda et l’API gateway d’Amazon. Il n’y a plus alors qu’à lancer :

$ serverless offline start

 
Vous verrez alors toutes les routes s’afficher dans le terminal. Vos Lambdas tournent maintenant sur votre machine. Le port par défaut est 3000. Ouvrez un navigateur, et vous pourrez constater qu’en tapant l’adresse http://localhost:3000/hello vous obtiendrez la même réponse « Bonjour le Monde ! » que plus haut.

Fantastique. Plus besoin de pousser sans arrêt du code vers AWS pour vérifier le fonctionnement de vos fonctions. Vous pouvez tester en local et ne pousserez que lorsque vous serez certains que tout fonctionne.

Gestion des erreurs et monitoring

 
Comment monitorer et avoir un compte rendu des erreurs d’une application sans serveur ? Disons-le, les logs de l’AWS CloudWatch sont odieux. Cela peut prendre une éternité pour trouver une fonction défaillante dans une application très simple, imaginez l’horreur avec des applications à grande échelle…

Il existe cependant une solution gratuite et prometteuse, c’est Dashbird. On ne vous demande pas de carte de crédit, il n’y a donc aucune raison de ne pas essayer.

Cela prend cinq minutes à configurer et mettre en place, en grande partie grâce à un excellent tutoriel de premiers pas. Vous pourrez alors voir tout ce qui se passe dans l’application, erreurs, charge, requêtes et même avoir un suivi du coût facturé par Amazon dans le cas d’exploitations à grande échelle. Vous aurez donc un œil sur la santé globale de votre application et sur votre budget. Il y a même un monitoring temps réel inclus.

dashbird1

dashbird2

Conclusion

 
Vous avez maintenant négocié la transition du développement web traditionnel ou Cloud vers la révolution serverless. Avec les quelques outils que nous venons de voir, vous pouvez maintenant créer des applications fantastiques, redimensionnables et fiables.

La seule chose qui puisse nous retenir est notre propre état d’esprit. Cependant il ne faut pas croire que les fonctions Lambdas puissent être l ‘équivalent d’un serveur. Néanmoins cela va dans la bonne direction. Les outils comme Serverless et Dashbird facilitent grandement la transition, et apportent une aide vraiment précieuse. Cela n’est pour l’instant adapté qu’à des micro-services ou des API REST, certaines applications plus lourdes demanderont toujours un serveur pour fonctionner. Mais nous ne sommes pour le moment qu’au début de cette aventure, non ?

Je vous encourage à vous familiariser, à jouer avec les fonctions serverless. Essayez d’inclure cela dans vos processus de développement.

Merci et à bientôt.

Liens

 
AWS Lambda : https://aws.amazon.com/fr/lambda/details/

Serverless framework : https://serverless.com/

Documentation Serverless : https://serverless.com/framework/docs/

Documentation Serverless Offline : https://github.com/dherault/serverless-offline (dans le README)