This is Serverless 🗣
À crier comme "This is Sparta" 😃
On entend un peu tout et n'importe quoi autour de Serverless. Il y a principalement beaucoup d'incompréhension et clairement un effet de mode. On peut facilement trouver plusieurs définitions, floues et minimalistes.
Je vous propose une histoire courte, un tour d'horizon, pour que vous puissiez vous faire votre propre opinion.
La semaine dernière j'ai eu le plaisir d'être invité à parler à ServerlessCPH pour présenter notre approche du Serverless. La conférence est en fait une forme de prolongation sur une journée de MicroCPH (1 track sur 2 jours) qui est organisée depuis plusieurs années. Et quitte à voyager, autant partir plusieurs jours, profiter de la ville et enchainer les 3 jours de conférence 🎉
Les organisateurs ont rassemblé une belle LineUp et ont vraiment bien organisé le programme et les conférenciers se sont enchainé presque avec poésie. Je ne vais pas vous couvrir toute la conférence, mais seulement les points que j'ai envie d'en retenir.
#MicroCPH
Le premier speaker a été Michael Nygard qui nous a parlé de Couplage et de Découplage.
Ce que j'ai surtout retenu, c'est qu'il faut combattre l'obsession de découpler les composants de l'architecture. C'est globalement ce que l'on fait quand on conçoit un module, un composant ou un service en généralisant son usage, parce qu'on va l'exposer à tout un ensemble d'autres composants qui n'est pas du tout spécifié.
Le découplage ne peut pas être un style d'architecture à lui tout seul. Si on conçoit tous les services pour qu'ils fonctionnent en ignorant les autres, on finit avec un océan de micro-service, avec un terrain fantastique à effet de bord. Chaque nouveau service est absorbé par le système et s'y noie.
Alors oui, c'est un manque de vision, mais surtout une absence de couplage.
Michael nous a ensuite présenté différents couplages dans l'ingénierie habituelle.
Par exemple le Sharfenberg's Coupler (Attelage en français) qui a été dessiné en 1903 et est toujours d'actualité. Au final, ce sont deux systèmes, eux-même appendices de plus grands systèmes (les locomotives, voir la rame tout entière), qui vont s'assembler et permettre à deux systèmes qui ne sont peut-être même pas de la même époque de fonctionner ensemble. Les locomotives, en particulier les ingénieurs qui les ont conçues, n'ont pas prévu que les deux systèmes fonctionnent ensemble. Ils sont parfaitement découplés. Ce sont les deux éléments du couplage qui leur permettent de travailler ensemble.
Vous avez déjà senti, dans la rame, la résistance qui augmente quand les tiges s’imbriquent. Et d’un coup ça se relâche, les deux rames ont un certain degré de liberté, elles ne sont plus en tension. Le coupleur définit les bornes de cette liberté, de cette articulation entre les deux systèmes. Bref, dans la conception de nos systèmes, il faut donner autant d'attention aux composants qui découplent qu'à ceux qui couplent. Le découplage sans couplages bien conçus n'est qu'un paradis pour les effets de bords.
On a eu le bonheur ensuite d'entendre parler Jonas Bonér mais aussi Ben Stopford qui nous ont parlé d'architectures basées sur des évènements, de CQRS et de Kafka streams comme les habitués l'auront deviné.
Ce que j'en ai retenu, c'est un lâcher-prise. Oui, ces systèmes ne sont pas déterministes. La consistance est une option. Le découplage du bus d'évènement signifie qu'à l'extérieur du service ou du micro-service, les choses seront "Eventually Consistent". Ça peut faire un peu peur, on aime le contrôle, mais au final, c'est une forme de compromis. On ne peut pas avoir la concurrence, la "scalabilité" et la consistance absolue.
J'ai également vécu le talk de Stefan Tilkov comme une baffe. Les back-ends engineers ont bien découpé le monolithe JEE, ont fait de beaux micro-services, mais en fait le front-end est magnifique monolithe. Oui, parce qu'en fait, ce sont les "fronteux" qui s'en occupent. Pire, on a déplacé une grande partie des décisions que prend le logiciel, de la "business logic" dans ces énormes SPAs. Et la preuve c'est cette dépendance à un Framework (👋 Angular.io ?).
Heureusement que @d_kubyshkin est venu offrir une solution.
Il nous a expliqué comment ils se sont organisés chez Zalando pour répartir la responsabilité des fragments du front-end en prenant appui sur Mosaic. Cela leur a permis de se libérer de la frontière entre le front et le reste et construire de véritable features teams, responsables de parties entières du workflow. (photos sur twitter).
Tout ça c'était très sympa ! À chaque fois, les experts en Microservices parlaient de Serverless comme si c'était la prochaine tendance à surveiller. Se permettant même de faire des vannes : "On verra bien comment ils feront quand ils auront 2000 fonctions en prod", "On a découpé le gros monolithe 💩 en plein de petits micro-services [💩,💩,💩,…], maintenant on re-découpe les micro-services en fonctions : [[💩,💩,💩,…], [💩,💩,💩,…][💩,💩,💩,…], …] : Problème résolu !"
Si vous n'avez jamais vu de fonctions, je vous propose la documentation des produits de GCP et Azure ou encore OpenFaaS.
#ServerlessCPH
Le lendemain on est donc entré dans #ServerlessCPH. Quand j'ai commencé à voir des gens avec des Slides "EC2 GTFO", je me suis senti déjà plus dans ma zone de confort.
Avec globalement deux points de vue du sujet qui, au premier coup d'oeil s'opposent, mais au final se complètent énormément.
Le premier est Ben Kehoe qui globalement explique que chez iRobot, ils font des robots mais c'est pas leur métier de gérer des backends etc.
Le serverless, c'est se concentrer sur le métier, sur le fait d'apporter de la valeur business et pas passer son temps à maintenir l'existant. C'est plus que du NoOps, on n'y pense pas du tout, tout juste à l'étape design pour évaluer les effets de bords.
C'est tout le réseau de services que vous pouvez utiliser. Par exemple, utiliser Algolia plutôt que de l'Elasticsearch, c'est déjà du Serverless. Parce que c'est pas à nous de penser aux failovers, à la montée en charge. On définit les indexes, on se concentre sur l'expérience des utilisateurs. Pour le reste, ça tiens et c'est tout.
Et du coup, le vendor-locking n'est pas fondamentalement mal, s'il permet de se libérer du fardeau opérationnel.
L'autre coté de la même pièce de monnaie c'était le sujet de Austen Collins. C'est une personne qui aime le YAML et les CLIs, ce qui attire rapidement ma compassion en fait. Si Serverless parle de Multi-Cloud c'est surtout parce qu'il veut qu'on puisse tirer le meilleur de chaque plateforme. Il y a effectivement pas mal de conférenciers qui sont sur AWS et voudraient pouvoir utiliser BigQuery, mais ne le font pas.
Austen a mis le doigt sur le couplage, ce sont les "Triggers" ou les "Events" qui déclenchent les fonctions qui apportent le plus de valeur et viennent avec le vendor-locking.
Nous par exemple, sur 98 fonctions en prod, on doit en avoir 80 qui sont déclenchées par des triggers propres au SDK Firebase, 3 ou 4 qui sont des Webhooks pour faire ETL depuis d'autres entreprises et le reste ce sont des Cron Jobs qui viennent d'un service externe via HTTP.
Bref c'est le sujet qu'il aborde avec Event Gateway et CloudEvents.
C'est quoi notre vision de #Serverless ?
En résumé, voici l'histoire que je suis venu raconter à Copenhague. On a monté la boite à deux développeurs. On a pas décidé du jour au lendemain de faire du serverless ou des fonctions, ce n'est pas un choix d'architecture. C'était surtout que l'on savait que passer du temps à discuter avec les développeurs, à aller chercher des boites chouettes et à vendre le service, c'était super important. Et on a toujours tranché de façon à ne passe se charger avec de la maintenance. On a aussi toujours voulu garder la capacité à pouvoir déployer un PoC en production dans la journée.
Quand on nous a dit "Sepa, c'est facile, c'est juste un Cron qui fait du XML à coder", on a utilisé Stripe Subscriptions.
Pour les fichiers on a intégré Filestack dès le début. Twilio, Algolia, etc… C'est ce que Yann IRBAH appelait "Web as a Framework" avant que Serverless soit cool.
Et les fonctions sont venues plus tard.
Ce que l'on ne veut plus faire c'est du jobbing avec un système comme Resque que j'ai adoré à l'époque où je faisais du Rails (Rails 3 tbh). On a même refait un peu la même chose sur notre node en utilisant Bee-queue contre un Redis. En fait, les workers forment à eux seuls un monolithe. Et quand tu rajoutes un job, si celui-ci plante, il impacte tous les autres, c'est un joyeux dawa.
Je ne referai plus des Clients-Serveur où le Client commande un job au serveur web qui le cache dans un Redis.
La SPA est un composant comme les autres et elle utilise un eventbus ou autre pour émettre un évènement sans rien attendre en retour. Et le découplage se situe directement à ce niveau. Pas juste derrière une API.
Notre SPA ne "Commande" jamais une fonction.
Les fonctions sont venues par praticité. Je voulais rajouter une feature un peu gadget et je voulais pas mettre le dawa sur les workers et du coup je l'ai poussée sur une fonction. Au fur et à mesure on a continué a réécrire les fonctionnalités des workers node vers des fonctions.
Un jour on a eu une fonction qui a mis 25 minutes pour compléter le job et ça n'a eu aucun impact sur le système. D'habitude c'est grave, parce que le serveur web se prend un requête bloquante pendant 25 minutes et ça peut impacter de véritables utilisateurs qui demandent juste à avoir la SPA par exemple. Mais là non, c'est pas grave, parce que les fonctions sont parfaitement isolées.
Ces fonctions sont conçue de manière très "jetable". Elle sont le plus souvent conçues pour fonctionner spécifiquement avec un service externe (algolia, twilio, pipedrive, sendgrid) et assurent le couplage entre notre système et le système externe.
Par contre, notre serveur web est toujours chez Clever. Il est toujours conçu pour être requêté par n'importe quel service externe (browser, scrapper) et il est toujours conçu de cette manière, découplé par design, et ne réduit pas le scope de ses consommateurs. C'est en soit un Microservice et pas une fonction et ça à du sens.
Il y a aussi une notion d'échelle. On conçoit des systèmes pour qu'ils soient capable de prendre des charges énormes alors qu'on en a rarement besoin. "Oui, on est une grosse entreprise avec des milliers de clients, il faut que vous soyez prêt" =>résultat une fois en prod : 2 appels par semaine, heureusement qu'on a mis une fonction ! Un kafka nous aurait couté une fortune !
Par contre, si on passe sur M6, notre serveur web va être chargé et Clever va savoir gérer la solution.
Je parle de notre expérience avec tous ces sujets, et notamment des Do and Don't. Vous pouvez retrouver les slides ci-dessous.
Pour résumer
Là où il y a couplage, les fonctions c'est bien. On les conçoit pour un usage hyper-spécifique et borné. Si on conçoit le composant par aspect, il vaut mieux que ce soit une forme de Micro-service, conçu pour être utilisé par un maximum de "clients". A priori, d'après moi ce sont deux cas d'usage totalement différents. Si le cold-start de la fonction peut avoir un impact sur l'expérience des utilisateurs, alors c'était une mauvaise idée.
Et le #serverless, d'après moi, ce n'est pas juste des fonctions et bien plus que du NoOps.
La conversation continue !
Après, je n'ai définitivement pas la science infuse et je suis content que le débat reste ouvert. Je serais content d'échanger avec vous sur ces sujets, que ce soit en AFK (on se voit au Web2Day ou à TakeOff Conf?) ou ici dans la section commentaire de cet article.
💙