URL: https://linuxfr.org/users/julieng-2/journaux/du-serverless-au-faas-et-du-golang-c-est-l-ete Title: # Du serverless au FaaS - et du Golang -, c'est l'été Authors: JulienG Date: 2022年09月07日T20:43:18+02:00 License: CC By-SA Tags: serveur, cli, serverless, faas et golang Score: 12 Bonsoir, ## 0. Introduction L'été, sa chaleur écrasante et ses travaux périscolaires : cette année, je m'étais donné deux objectifs, la définition et la mise en œuvre d'une (petite) solution _FaaS_ (_function as a service_) et l'apprentissage de Go. Difficile de faire de l'architecture de SI si on ne se contente que de la définition de l'ouvrage, et depuis des années j'entends du bien (et aussi beaucoup de mal) sur le langage de Google : alors autant tester soi-même, l'un et l'autre. Je n'avais pas prévu d'en faire un article, mais lorsqu'il y a quelques jours (à date de rédaction de ces lignes), un article a attiré mon attention : "_2022, l'année de l'explosion du serverless_" ([article du JDN](https://www.journaldunet.com/web-tech/cloud/1514083-2022-l-annee-de-l-explosion-du-serverless/)), cela m'a motivé. Car voilà quelques années, j'avais eu l'occasion d'écrire une thèse pro sur des sujets similaires. [La présentation de la soutenance](https://www.slideshare.net/nothus1/penser-son-systme-dinformation-apprhender-ses-volutions-230728506) y fait directement référence, en associant FaaS et RDF comme deux des outils modernes et indispensables pour produire des traitements automatiques hautement distribués et porteur de sens partagés entre les organisations. C'est dire si le sujet me passionne. Pour autant le code que j'ai produit n'a pas d'autre perspective qu'un travail de meilleure compréhension du sujet - et accessoirement d'avoir un outil pour mes propres besoins, sur mon serveur de développement. Je donne plus loin le lien vers le dépôt, sous licence MIT. De plus, c'est pile dans l'actualité : nous parlerons de mise à l'échelle, particulièrement ici de réduction vers 0 du coût des processus. En cette période de "fin d'abondance", c'est bienvenu... Enfin et comme vous pouvez vous en doutez, les lignes que vous lisez comme le travail de développement m'ont demandés quelques heures au carré. Malgré tout le soin que j'ai apporté à l'écriture de cet article et au reste, j'ai la bonne certitude d'avoir laissé de (grosses ?) boulettes. Merci de votre modération dans vos commentaires (je suis [très] ouvert à une critique quand elle fait plus de trois mots !). Le sujet _serverless_ que j'aborde n'est pas le plus simple et, reconnaissons-le, le plus limpide. Il est soumis à l'interprétation et donc à nos propres biais. C'est une discipline "jeune" où l'aspect commercial agit beaucoup sur la communication et la formation qui en est faite (pour le meilleur et le pire). Je mets ici le terme jeune entre guillemets car certaines approches sont des héritages lointains, qui ont parfois des dizaines d'années. Mais cet article est déjà considérablement trop long pour en faire l'exégèse... ------------------------------------------------------------------------------ ## 1. _Serverless_, Ce que c'est ### Du concept global La définition n'est pas facile, car le concept reste globalement flou. Évidemment c'est le concept est un trompe-l’œil : il y a ___toujours___ un serveur quelque part. Sa gestion est simplement et totalement transparente pour l'équipe de développement, qui n'assure pas la gestion d'un parc d'infrastructure. Au-delà, c'est la gestion même d'un "service" (c'est-à-dire un service _rendu au client_) qui est également géré par celui qui l'héberge l'applicatif. Pour l'organisation qui porte le développement (entreprise, association, projet ouvert, etc.), cela a plusieurs avantages : - généralement il y a la fonction "_scale-to-zero_", c'est-à-dire que l'applicatif ainsi hébergé, s'il n'y est pas utilisé, ne consomme pas de ressources vives (seulement son stockage). La facture en cas de non-utilisation est donc soit particulièrement réduite, soit nulle ; - le déploiement est facile, au sens où l'on utilise généralement une API Web ou via une ligne de commande simple et courte ; - la sécurité, la sûreté reposent en partie sur le service sous-jacent, même si les fonctions d'authentification, de protection contre les attaques de force brute ou contre les déni de service, ne sont pas toujours compris (voir point suivant) ; - la facture se fait au "hit", à l'appel à l'applicatif... ... Ce qui est là un des principaux défauts, dû à la gestion économe des ressources : le temps de démarrage. Du fait que l'applicatif est éteint (parfois "mis en pause" mais généralement le coût n'est alors pas nul pour l'hébergement), le premier appel porte le coût de démarrage. Ce coût peut être très important comme nous le verrons plus loin. Il faut donc avoir des stratégies efficaces de démarrage, que l'applicatif doit porter en son sein, notamment par exemple, en l'optimisant avec un tampon local important lorsque c'est possible. Autre point possiblement problématique, c'est la montée en charge ou mise à l'échelle (la fameuse "_scalabilité_"). Lorsque le développeur poussera son applicatif, il ne saura pas ni combien de noeuds sont en usage - ni même s'il y en aura plusieurs -, et selon quelle configuration, son infrastructure sera à un instant donné. Si le tampon doit être "unique", au sens où toutes les instances doivent partager le même, il faut donc prévoir un service dédié type _memcached_ ou _redis_. C'est là des principaux points que j'énonce mais loin d'être exhaustif. Si l'approche vous tente et que vous ne dépassez pas le cadre d'une organisation à quelques personnes pour une charge anecdotique ou presque, mieux vaut se tourner sur une solution _serverless_ très légère, mono-noeud par principe, car vous ne gagnerez que les avantages. Bien évidemment, si vous n'êtes pas dans ces situations, avoir une part de _serverless_ dans votre architecture n'est pas sans impact voire peut-représenter un risque majeur. D'autant que les solutions actuelles de _serverless_ "à destination des développeurs" et notamment celle qui me semble la plus (re)connue OpenFaas, fonctionne quasi-systématiquement avec un "gros machin" comme Kubernetest (même si des contre-exemples existent [ici](https://blog.alexellis.io/faas-containerd-serverless-without-kubernetes/) pour l'explication et [là](https://github.com/openfaas/faasd) pour le dépôt). C'est-à-dire qu'on a une mise en oeuvre loin d'être évidente pour aboutir à cette abstraction tant désirée. Pour l'avoir testé sur une infrastructure personnelle - un Rancher à deux fournisseurs de VM distincts -, c'est vite inommable en terme de débogue... ### Du particulier A cet instant de l'article, vous vous direz peut-être "_serverless n'est pas FaaS !_" et globalement je serais d'accord avec vous. En effet, vous pouvez parfaitement utiliser un service quelconque ([DaaS](https://fr.wikipedia.org/wiki/Data_as_a_service) ou [SaaS](https://fr.wikipedia.org/wiki/Software_as_a_service)), afin de pousser votre logique métier quelque part (ici, le "_as a service_" est le support à cette logique métier). Vous ne payerez au mieux qu'à concurrence de la consommation réelle ou au pire au forfait et, parfois, l'adaptation d'une équipe de développeur sans aucune notion d'infrastructure (hélas ça existe), peut alors s'intégrer dans ces types de services sans (trop) douleur. Cependant vous risquez d'être extrêmement limité dans le format du code exécuté, de sa taille et de sa complexité. Ou alors avoir de l'[IaaS](https://fr.wikipedia.org/wiki/Infrastructure_as_a_service) ou du [PaaS](https://fr.wikipedia.org/wiki/Platform_as_a_service) : c'est une abstraction moins forte, qui permet d'avoir facilement un environnement prêt à l'emploi - mais la notion de serveur à configurer reste encore largement présente. En résumé, tout dépend de votre _volonté d'abstraction_ de la réalité physique des bits sur un bout de plastique couvert de silicium et autres métaux. Ce n'est une frontière entre tout et rien : c'est une échelle parfois assez subtile. Chacun des concepts que j'ai énoncé, recouvre une portion plus ou moins importante de la couche ultime que constitue le _serverless_. La frontière de ce dernier (me) semble comme pour les autres concepts, une frontière poreuse où l'on répond à un besoin, il est donc normal, notamment pour le point évoqué du PaaS, que les deux concepts se chevauchent par endroit. Pourtant ils sont bien dissemblables et c'est [Cloudfare](https://www.cloudflare.com/fr-fr/learning/serverless/glossary/serverless-vs-paas/) qui porte - avis personnel -, le meilleur exemple : > "_L'informatique sans serveur peut être comparée au fait de tirer de l'eau d'un robinet, l'eau représentant la puissance de calcul. Dans une maison moderne, on peut ouvrir un robinet à tout moment pour obtenir toute l'eau dont on a besoin. Le PaaS s'apparente davantage à un distributeur d'eau avec un service de livraison de bonbonnes. Il est toujours possible d'obtenir autant d'eau potable que nécessaire, mais il ne suffit pas d'ouvrir le robinet ; le consommateur doit demander au fournisseur de lui livrer davantage de bonbonnes si la demande augmente. Dans les deux cas, un tiers s'occupe des services en « backend » c'est-à-dire en arrière plan - en purifiant l'eau, en l'acheminant l'eau au bâtiment, etc. - mais seule l'eau du robinet peut être dosée avec précision, à la demande et en temps réel._> _(...) Pour poursuivre avec la métaphore de l'eau, les consommateurs qui utilisent l'eau du robinet paient exactement la quantité d'eau qu'ils consomment. De même, la facturation de l'informatique sans serveur est extrêmement précise, et les développeurs ne paient que ce qu'ils utilisent. Certains fournisseurs d'informatique sans serveur ne facturent aux développeurs que le temps précis d'exécution de leurs fonctions, jusqu'à quelques fractions de seconde pour chaque instance individuelle de chaque fonction. D'autres fournisseurs facturent selon le nombre de demandes._> _Les consommateurs qui utilisent un distributeur d'eau et qui se font livrer des bonbonnes d'eau ne paient également que ce qu'ils utilisent, mais ils paient à la bonbonne et non au mètre cube. De la même manière, certains fournisseurs de PaaS ne facturent aux développeurs que ce que leur application utilise. Cependant, la facturation est loin d'être aussi précise que pour l'informatique sans serveur. D'autres fournisseurs de PaaS facturent leurs services au mois. Les développeurs peuvent généralement définir la quantité de puissance de calcul qu'ils souhaitent obtenir. Cependant, cette décision est prise à l'avance et n'est pas une réaction aux augmentations et aux diminutions de l'utilisation en temps réel._> _Cette différence ne signifie pas nécessairement que l'architecture sans serveur est toujours plus abordable. De même qu'il devient rapidement très cher de laisser couler un robinet d'eau en permanence, les applications web dont le flux d'utilisation est important et constant sans grande fluctuation peuvent être coûteuses à faire fonctionner en utilisant l'informatique sans serveur._" ### De l'usage réel Une fois ces considérations aqueuses passées, reste à formaliser le _[FaaS](https://en.m.wikipedia.org/wiki/Function_as_a_service)_. Imaginez que le _serverless_ est l'ensemble des technologies pour faire une abstraction (quasi-)totale du sous-jacent technique et d'infrastructure. Le _FaaS est une modalité du _serverless_ : c'est la technique (et souvent un _framework_ pour accompagner le déploiement du code) permettant au développeur non seulement de faire abstraction de la partie hébergement, mais aussi même dans le cas extrême, d'où provient la charge de travail. Le périmètre d'action est alors très réduit : vous produisez une fonction qui sera appelée dans un processus que vous ne maîtrisez pas. Mais dont la mise à l'échelle, la sécurité et la sûreté, la gestion en temps réel, est porté pour vous. Du fait que nous sommes au XXIe siècle, les appels sont principalement (voire exclusivement dans de nombreux cas), portés seulement par le réseaux. Revenons à OpenFaas quelques instants et [le premier exemple](https://docs.openfaas.com/tutorials/first-python-function/) donné : ```python3 import requests import json def handle(req): result = {"found": False} json_req = json.loads(req) r = requests.get(json_req["url"]) if json_req["term"] in r.text: result = {"found": True} print json.dumps(result) ``` ... et c'est tout. Le reste se résume en un fichier de pré-requis et un fichier de déclaration de cette fonction. En deux-trois commandes, vous envoyez ça dans un coin de l'univers, en supportant une charge virtuellement sans limite (ou seulement celui de votre compte en banque). Si vous n'avez pas d'activité, aucune charge pour la fonction n'existe (pas de processus en activité) : c'est le _scale-to-zero_, le graal du _Green (Washing) IT_. Ici OpenFaas a assuré plusieurs fonctionnalités essentielles pour nous : - l'écoute du réseau sur un serveur où l'instance d'OpenFaas tourne, - la récupération de la requête entrante, - son éventuelle répartition de charge vers d'autres instances OpenFaas, - le contrôle de l'intégrité de la requête (_parse_) - la détection de la fonction appelée puis éventuellement, le contrôle de sécurité pour l'appel, - le démarrage d'un nouveau conteneur pour la prendre en charge (ou l'envoi à un conteneur existant), - l'envoi d'une requête à ce conteneur dans un format attendu, - la réception par le processus au sein du conteneur de la requête, - le lancement la fonction `handle` définie plus haut, _(... ici le traitement par la fonction ...)_ - la récupération d'erreur (`try / except`) ou du retour normal, - l'envoi du processus vers l'extérieur du contenur, - la récupération du retour par l'instance d'OpenFaas, - le contrôle de l'intégrité du retour, - la production d'un retour pour le client final, - l'envoi de ce retour au client final. Rien que ça - et je vous ai épargné la réalité des appels de signaux, des traitements réseaux, etc. On ne mesure parfois pas bien, et moi le premier, la quantité absolument folle d'énergie, de travail, de synergie qu'il faut pour arriver à produire un tel système informatique. Le nombre incalculable de choses qui peuvent mal tourner. Je trouve ça vertigineux. Bref aparté : si vous connaissez le paradoxe de la veste en laine, ce vertige ne doit être que plus grand encore (sinon courrez voir [la chaîne de Mr Phi](https://monsieurphi.com/2017/06/19/adam-smith-grain-de-philo-5/))... On atteint d'un certain côté à une division du travail quasi-parfaite entre des compétences diverses ; faisant perdre l'aspect "généraliste" de l'informatique des premiers temps, que tant de passionnés comme moi apprécient... ### Des considérations L'aspect intéressant du _FaaS_ au-delà d'une baisse toujours plus grande de la barrière d'entrée dans le développement (notamment pour les profils junior), est aussi le contrôle laissé par le développeur à son infrastructure pour optimiser ses propres moyens. Comme vous ne vous préoccupez pas du processus qui porte la "fonction" ni "où" ce processus est exécuté, l'infrastructure est (et doit) être en capacité de rationaliser sa consommation de ressources : bref, elle va couper tout ce qui est inutile. On en revient à la partie aqueuse : on coupe le robinet pendant qu'on se brosse les dents. On "_scale-to-zero_" (on réduit l'échelle en bon français !). Le _FaaS_ n'existe pourtant pas de manière unique, comme si on abordait systématiquement le problème avec une même approche. D'autant que j'ai passé ici sous un relatif silence l'aspect "coût en temps" qui est le point noir général de la solution. Le _FaaS_ peut-être vu alors avec deux principales applications : - un processus qui existe tant qu'il y a de l'activité, et qui est éteint lorsque celle-ci s'arrête (avec un délai modifiable). On se rapproche là considérablement d'un serveur classique. L'avantage : le temps de démarrage est porté seulement par la première requête et qu'un cache partagé entre plusieurs requêtes peut exister. L’inconvénient : il est délicat de définir, voire totalement contre-productif d'avoir un délai d'extinction fixe (rarement un SI se comporte avec une grande régularité et si tel est le cas, il existe d'autres solutions bien plus simples que le FaaS...) ; - un processus déclenché par requête, comme on peut l'avoir avec FastCGI. L'avantage est alors une plus grande isolation entre les requêtes, ainsi qu'un coût réellement nul s'il n'y a pas de requête (le processus s'arrête à la fin du traitement de sa requête). Le coût de démarrage est souvent sensible dans le coût temporel total et il est porté individuellement par l'ensemble des requêtes. Évidemment ces applications négligent volontairement dans l’approche, un aspect essentiel : il faut _toujours_ un processus d'écoute actif, qui déclenchera l'une ou l'autre. Il n'y a pas de magie : si un requête arrive, du client final ou d'une balance de charge, il faut pouvoir être en écoute et répondre, mettre en œuvre la solution. Pour cela, plusieurs solutions existent. Cela que je propose plus loin, avec _systemd_, permet une réduction possible de 100% de la charge sur un OS pour la solution de _FaaS_ : elle est elle-même allumée et éteinte par le système d'exploitation suivant l'activité. Du reste je n'ai pas poussé l'exemple (et le vice) jusqu'à éteindre mon ordinateur - mais vous imaginez bien qu'avec une balance de charge extérieure, on peut sans difficulté éteindre jusqu'aux machines physiques. Le _FaaS_ permet alors de réduire pour une entreprise, de réduire sa dépense au seul coût de possession. La solution de _FaaS_ pour être tout à fait professionnelle ou à tout le moins complète, dispose donc nécessairement de plusieurs composants et règles de gestion, pour faire coller la partie développement logi(ciel/que) à l'infrastructure. ------------------------------------------------------------------------------ ## 2. Le cas d'étude ### La présentation générale : FAASS - Function As A (Simple) Service Le dépôt est ici : [https://github.com/JGarderon/faass](https://github.com/JGarderon/faass). Il contient une seule branche, et j'ai posté [une version `alpha2`](https://github.com/JGarderon/faass/releases/tag/alpha2). Je n'ai pas de "plan sur la comète" - si ça intéresse quelqu'un, je suis prêt à échanger et à aider à l'usage, mais ce travail est pensé et prévu comme un exercice d'entraînement et pour un usage véritablement personnel (remarquez, Linus disait ça aussi... ;)). A ce jour, je prends en charge aujourd'hui deux types différents de "route", qui sont les appels possibles : - une "fonction" (_function_), qui est exécuté dans un conteneur dédié. C'est véritablement du _FaaS_. Le mécanisme derrière, s'appuie sur _stdin_/_stdout_ pour la communication avec le serveur. C'est un choix motivé pour ne pas à réinventer la route côté processus piloté : on se met d'accord sur une procédure d'échange (ici un corps en deux parties, chacune avec une taille définie par un entier déclaré à leur début). Donc pas besoin d'un framework d'exécution comme dans OpenFaas ; - un "service" (_service_), qui est un conteneur lancé et arrêté en fonction des besoins. C'est donc moins dans la logique _FaaS_ que celle du _serverless_. Ici l'échange se fait en HTTP sur un port défini dans la configuration. Le service est arrêté passé une période d'inactivé et rédémarré lorsqu'un client revient. Forcément en fonction de la situation, il sera plus ou moins efficace d'utiliser l'un ou l'autre : - pour des traitements par lot, la version "service" est efficace car elle restera active sans discontinuité durant le temps nécessaire ; - par contre pour un appel très occasionnel, la version "fonction" est suffisante. Autre élément à prendre en compte : la partie "fonction" est la seule qui permet de déclarer via API, un script ou un exécutable qui sera lancé au sein du conteneur. Le service ne dispose qu'un point de montage vers le dossier temporaire. Si vous souhaitez tester les performances dans les mêmes conditions que les miennes, voici un squelette de ma commande locale : ```bash ab -n 1500 -c 50 -s 2 http://127.0.0.1:9090/lambda/{la route à tester} ``` ### La mise en route A cette heure, je n'ai pas eu le temps d'étoffer les tests fonctionnels, donc ne vous inquiétez pas du retour anecdotique de la console : ```bash julien@julien-Vostro-7580:~/Developpement/faasd/test-go-faas$ ./build-and-test.sh --- --- --- start tmp path existent cache path existent example function existent --- --- --- build 2022年09月06日 23:27:28,188 - general - SPECIAL - FaasS = Function as a (Simple) Service --- Created by Julien Garderon (Nothus) from August 01 to September 06, 2022 MIT Licence --- This is a POC - Proof of Concept -, based on the idea of the OpenFaas project /!\ NOT INTENDED FOR PRODUCTION, only dev /!\ 2022年09月06日 23:27:28,188 - general - OK - all is ready for work ! 2022年09月06日 23:27:28,189 - general - INFO - build asked 2022年09月06日 23:27:28,488 - general - OK - build finished 2022年09月06日 23:27:28,488 - general - SPECIAL - ending of script --- --- --- functional tests 2022年09月06日 23:27:28,612 - general - SPECIAL - FaasS = Function as a (Simple) Service --- Created by Julien Garderon (Nothus) from August 01 to September 06, 2022 MIT Licence --- This is a POC - Proof of Concept -, based on the idea of the OpenFaas project /!\ NOT INTENDED FOR PRODUCTION, only dev /!\ 2022年09月06日 23:27:28,612 - general - OK - all is ready for work ! 2022年09月06日 23:27:31,784 - build_and_run - OK - execute test 'test_lambda_url_notfound_get' (pass) 2022年09月06日 23:27:31,785 - build_and_run - OK - execute test 'test_lambda_url_invalid_get' (pass) 2022年09月06日 23:27:31,787 - build_and_run - OK - execute test 'test_home_get' (pass) 2022年09月06日 23:27:32,853 - build_and_run - OK - execute test 'test_lambda_services_get' (pass) 2022年09月06日 23:27:33,708 - build_and_run - OK - execute test 'test_lambda_functions_get' (pass) 2022年09月06日 23:27:34,404 - build_and_run - OK - run without error 2022年09月06日 23:27:34,404 - general - SPECIAL - ending of script --- --- --- stop ``` _Même si certains de vos tests passent en rouge sur votre poste, l'applicatif a déjà été construit et est donc prêt à l'emploi. Du fait de la puissance des machines hôtes, avec les délais de connexion, le script de tests peut partir en erreur (faux positif)._ Vous aurez ensuite besoin d'un certificat auto-signé pour démarrer l'applicatif (pour l'instant c'est obligatoire, je rajoute prochainement cet aspect comme option dans la configuration). De [nombreux tutoriels](https://doc.ubuntu-fr.org/tutoriel/comment_creer_un_certificat_ssl) existent... Tout est prêt pour le lancement. Commençons simplement par... l'arrêt via ctl+c : ```bash julien@julien-Vostro-7580:~/Developpement/faasd/test-go-faas$ ./faass INFO: 2022年09月04日 12:13:46 main.go:68: UI path found : /home/julien/Developpement/faasd/test-go-faas/content INFO: 2022年09月04日 12:13:46 main.go:75: Authorization secret found ; API active ^CINFO: 2022年09月04日 12:13:48 main.go:127: interrupt received ; shutting down WARNING: 2022年09月04日 12:13:48 server.go:23: Shutdown ListenAndServeTLS terminated INFO: 2022年09月04日 12:13:48 main.go:138: process gracefully stopped ``` Si vous souhaitez repartir de zéro pour la configuration voir d'un environnement vierge (effacez `./conf.json`), `faass` le fera pour vous : ```bash julien@julien-Vostro-7580:~/Developpement/faasd/test-go-faas$ ./faass -prepare WARNING: 2022年09月04日 12:16:19 utils.go:74: Unable to create environment for UI contents "/home/julien/Developpement/faasd/test-go-faas/content" : mkdir /home/julien/Developpement/faasd/test-go-faas/content: file exists ; pass ``` Il créera ainsi l'arborescence locale si nécessaire. A partir de maintenant, je vous conseille d'avoir trois consoles ouvertes : - la première pour `./faass` (utilisez `GODEBUG=http2debug=2 ./faass` pour [du _très_ verbeux](https://pkg.go.dev/net/http#pkg-overview)) ; - la deuxième avec `docker stats` pour suivre l'activité réelle des conteneurs ; - la troisième où vous tapez les commandes de requêtes. Dans cette dernière console, je vous conseille de tirer les images demandées dans la configuration, l'application ne prennant pas encore cette étape au démarrage : - `docker pull nginx` ; - `docker pull python:3`. Là, tout est prêt ! __Lancement d'une fonction (sans authentification par défaut)__ Dans la console n°3 : ```bash julien@julien-Vostro-7580:~/Developpement/faasd/test-go-faas$ curl -k -X GET 'https://127.0.0.1:9090/lambda/example-function' --data-raw 'coucou' coucou ``` Notez ici, que le fichier `example-function.py`, se comporte comme un serveur d'écho, en rajoutant simplement un entête HTTP supplémentaire. Dans la console n°2, vous aurez la sortie suivante : ``` INFO: 2022年09月04日 20:01:43 main_server.go:152: known real desired url : /lambda/example-function INFO: 2022年09月04日 20:01:43 main_server.go:168: known desired url : example-function WARNING: 2022年09月04日 20:01:43 main_server.go:95: run container for route 'exampleFunction' ``` Enfin dans la console n°1, vous aurez (si vous êtes rapide !), un aperçu du conteneur. Ce dernier a été entièrement "effacé" de votre système lorsque le processus Python s'est arrêté (comportement de l'arguemnt `--rm`). __Lancement d'un service (avec authentification par défaut)__ Dans la console n°3 : ```bash julien@julien-Vostro-7580:~/Developpement/faasd/test-go-faas$ curl -k -X GET -H "Authorization: Basic YWRtaW46YXplcnR5" https://127.0.0.1:9090/lambda/example-service
If you see this page, the nginx web server is successfully installed and working. Further configuration is required.
For online documentation and support please refer to
nginx.org.
Commercial support is available at
nginx.com.
Thank you for using nginx.