đź“» C'est quoi un micro service ? | Radio DevOps #21

:microscope: Les micros services sont-ils partout ? Mais attends c’est quoi un micro service ?

Est-ce que cela à révolutionner notre manière de concevoir des applications ?

:radio: Nous en parlons dans #RadioDevOps avec : @mcorbin, @DamyR et @Uggla.

Radio #DevOps est le #podcast dédié à notre mouvement issu de la communauté des #CompagnonsDuDevOps.

L’article de blog : 📻 C'est quoi un micro service ? | Radio DevOps #21 - Lydra | Artisans DevOps

DĂ©couvre les podcasteurs :

Radio DevOps est disponible dans toutes les applications de podcast.

As-tu déjà mis en place les micros-services dans ton travail ?

2 « J'aime »

Merci pour ce podcast très intéressant tout au long. Je réagit a travers ce message simplement au début du podcast, sinon je vais passer la nuit a rédiger :slight_smile:

Je note bien que l’intitulé est c’est quoi un microservice et que mon message est dédié à la question quelle sont les raisons d’utiliser les microservices.

Afin de ne braquer personne je precise que je ne suis ni anti-microservice, ni pro-monolithe. En revanche je suis anti-dogme et pro-réflechi-a-ton-besoin-avant-de-copier-sur-les-autres-comme-un-con.

:point_right: C’est quoi une API.

J’ai l’impression que lorsque on évoque une API, on pense immédiatement à une API REST, grossièrement du JSON dans du HTTP. Le sigle API signifie Application Programmation Interface. Cela regroupe les convention et méthodes d’appel de code externe à l’application. Par exemple la lib OpenSSL expose une API afin que les programmes écrit en C puisse accéder à ses fonctions de crypto.

On va donc avoir des API de tous languages, et certaines inter-langages. Par exemple:

  • les languages compilĂ© et parfois des choses hybrides comme du java utilisent l’ABI (Application Binary Interface) comme API. Il s’agit des conventions d’appel de code au niveau binaire. Ainsi du code C peut appeller du code C++, Go (sous conditions), rust ou autre.

  • les langages compilĂ©, avant compilation tel que le C vont dĂ©finir leur API dans les fichier “.h” qui fixent les conventions d’appel des fonctions exposĂ©s. Soit tout est compilĂ© en mĂŞme temps et le compilateur fait ce qu’il veut, soit l’API exposĂ© dans le “.h” est deja compilĂ© (c’est une lib telle que OpenSSL) et le compilateur utilise l’ABI pour gĂ©nĂ©rer le code d’appel.

  • dans les langages object, on va trouver des API dĂ©finies par des objets. En java, on inclus des lib toutes faite et parfois fournies compilĂ©es. Les dĂ©finitions des objects sont exposĂ©s et une appellant peut les utiliser.

  • On trouve des API au dessus de connexion TCP ou de socket avec des conventions d’appel dĂ©finis par du ASN.1/DER, du XDR ou du protobuf. On est Ă  un niveau d’interfaçage plus Ă©levĂ© puisque il ne s’agit plus en appel direct, mais d’appel a travers une couche de communication.

  • On trouve des API au dessus de HTTP(S) comme le REST, le SOAP au autres. On est dans un niveau d’interface bien plus haut niveau puisque on traverse deux a trois couche protocolaires.

:point_right: C’est quoi un microservice ?

Quelques définitions que j’ai trouvé, c’est bien sur non exhaustif, ce sont les premières réponse d’une recherche Google en français (definition de microservice - Recherche Google):

Que signifie Microservices? - Definition IT de Whatis.fr

Comprendre ce que sont les microservices

Microservices — Wikipédia

https://www.talend.com/fr/resources/guide-microservices/

Je note que le concept de microservices est très ouvert, il n’y a aucune taille indicative.

  • Il s’agit de faire des services “simples”. C’est quoi simple ?
  • Qui prennent en charge un “objectif mĂ©tier”. C’est quoi un objectif mĂ©tier ?
  • Faire des services faiblement couplĂ©s. A partir de quand un couplage est faible ?

Je note également que l’utilisation de protocoles de communication réseau n’est évoquée dans aucune définition.

Je note la quatrième définition qui évoque le déploiement de manière indépendante, ceci me parait clair.

Je considère pour la suite que les microservices utilisent la couche réseau pour communiquer. c’est noté nulle part, mais cela me semble sous entendu tout au long du podcast. Je pense également que le microservice adresse des briques d’un application unique. Donc un microservice pris hors application ne sert a rien.

Bref, difficile de tirer des conclusions ou d’expliquer un concept aussi flou et mal défini

:point_right: les problèmes adressés par les microservices

J’ai noté et reformulé les problèmes que vous annoncez être résolus par les microservices. Je me permet des commentaires. Evidement si j’ai mal reformulé ou mal compris, mes commentaires sont sans intérêt.

Pour moi lorsque l’on adresse un problème d’organisation avec une réponse technique, on n’est pas sur la bonne voie. Un problème d’organisation s’adresse en revoyant l’organisation. Ce sont les problèmes techniques qui s’adressent avec une réponse technique.

Si par exemple la société travaille sur un load balancer très performant et se retrouve avec des développeur qui communiquent mal en france et aux etat-unis, va-ton sacrifier les performances du load balancer en le transformant en application microservices ?

L’autre point est que les services discutent entre eux avec un contrat. C’est déjà le cas dans n’importe quelle définition d’API, un contrat lie les services, qu’il soit sous forme de microservice ou sous forme de bibliothèque de fonctions. Ce n’est donc pas un point adressé par les microservices vu que cela fonctionne comme ça depuis très longtemps.

Je part du principe qu’un service qui à besoin d’être mis à l’échelle est une service qui sature une resource sur une machine (CPU / Réseau / disque / mémoire). Si ce n’est pas le cas, on a simplement un problème d’attribution des resources (ou du code pourri). Si il sature un container, il a simplement besoin d’une modif des CGROUP. Donc un service qui à besoin d’être mis à l’échelle nécessite impérativement du matériel physique (ou VM si on est chez un cloud provider) supplémentaire.

Admettons que l’application soit composée de deux microservices. Un module I qui s’occupe d’interface et un module D qui s’occupe des data. On sépare I et D car I est plus gourmand que D. Pour un service exceptionnel (soldes) I sature 2 machines, D sature 4 machines. On peut coupler I et D dans un monolithe qu’on l’installe sur les 6 machines, le monolithe dispose des même resources, aussi je ne voit pas en quoi une architecture microservice résout un problème de mise à l’échelle.

A la limite, cela peut être vrai si les 2 et 4 machines n’ont pas les meme specifications. Dans ce cas l’equation devient fausse, mais elle peut être rééquilibrée. Cela dit, si un architecte decide de dépenser de grosses sommes dans la complexification de l’application dans le but de faire une économie de quelques petit bouts de machines, je pense qu’il fait fausse route.

A l’inverse, je dirais que si D ne peut pas être mis à l’échelle car il fait des operations statefull non parralellisables (j’entends par la qu’il ne supporte pas la scalabilité horizontale, mais uniquement la scalabilité verticale), on aurait un bonne justification pour un service dédiée. On sous-traite un maximum de compute sur des services parrallelisables et on laisse faire ses operations à D sur sa machine unique.

“Les monolithes sont rarement scalable” me parait être une affirmation hasardeuse, en tous cas, si vous avez des sources, je suis preneur. Pour ma part (sans plus de sources) ces 10 dernières années le seul monolithe non scalable (or application bureautique) que j’ai vu est une application de support qui s’appelle “Zammad”. Même wordpress est scalable ! J’ai envie de dire que si le monolithe n’est pas scalable c’est à cause de l’architecte, la solution n’est pas un microservice, mais un architecte qui prends en compte le besoin de scalabilité.

je suppose que par faire monter une DB en performances tu entends plutot “utiliser des DB dédiées à un service” ? Si c’est le cas je pense qu’un monolithe peut très bien s’adresser à plusieurs DB différentes afin de dédier des DB a certaines taches (enfin, pour peut qu’on ne soit pas contraint par un merveilleux framework).

L’application peut très bien être découpée en bibliothèques de fonctions (classes, …). Chaque bibliothèque est versionnée séparément des autres, et les modalités d’accès à ces fonctions sont définies. Cela simplifie le cycle de vie des parties de l’application et sans microservices.

L’application peut très bien être découpée sans pour autant mettre les morceau dans des microservices. L’application être découpée en bibliothèques de fonctions et cela ferra le job. C’est d’ailleurs ce que l’on fait dans certains monolithes. En tous cas, chez moi les applications sont structurées en packages.

Par ailleurs si l’application de vient trop complexe pour être comprise, il est temps de prendre une architecte logiciel.

Pour moi une partie d’un monolithe qui ne fonctionne pas à le même effet qu’un appel à service qui ne fonctionne pas. Dans le premier cas, on a une erreur et l’appelant peut la gérer. Dans le second cas on à une erreur et l’appelant peut la gérer.

Je note que dans des monolithes comme Prestashop, certains modules peuvent être désactivés dans le but d’encaisser un pic de charge (passage TV, …). Ce n’est donc pas quelque chose apporté par l’architecture microservices.

Je pense que c’est un cas qui justifie un microservice. Je souligne toutefois que c’est une motivation financière: un langage de programmation turing-complet permet de tout faire, on peut donc écrire toute l’application dans un même langage. Si on choisi de ne pas le faire c’est probablement pour aller plus vite, et donc une motivation financière:

  • il est plus rapide et moins cher d’utiliser une bibliothèque toute faite dans un autre langage que de re-dĂ©velopper le concept.
  • il est plus judicieux d’utiliser du node.js pour un système Ă©vĂ©nementiel qui gère des web-socket et du PHP pour de la gĂ©nĂ©ration de page en mode thread.

Je pense que cela peut justifier des microservices, mais cela soulève des questions: Si on ne veut pas assurer la haute disponibilité d’un composant, c’est probablement pour des raisons de coût, alors pourquoi choisir un développement en microservice qui est plus complexe et donc plus couteux ? Probablement une équation à poser.

:warning:Citation de mémoire car je n’ai pas retrouvé/cherché le passage:

Je suis entièrement d’accord, mais parle-t-on encore de micro services ? N’est-ce pas un service interne ? La limite est très floue.

:point_right: Remarques en vrac

J’ai bien noté que c’est une corrélation et non une causalité. Par ailleurs, je ne suis pas sur que l’adoption d’un truc aussi compliqué et indébuggable que kubernetes soit lié à de la maturité.

A mon avis la causalité est inversée par rapport à l’énoncé de la corrélation : les équipes qui ont prévu de livrer souvent on choisi d’adopter kubernetes car le marketing de Google fait du bourrage de crâne dans ce sens.

Je trouve cette corrélation un peu fallacieuse.

:warning:Citation de mémoire car je n’ai pas retrouvé/cherché le passage:

Quelle preuve que ce soit vrai ? Les microservices sont à la mode, Amazon annonce qu’il en à 150. A coté de ça, tous les salariés signent des clauses de confidentialité, et aucun de leur partenaire ne connait la nature exacte de leur soft (en revanche, tous pensent le savoir, mais aucun ne dit la meme chose - experience perso vécue sur la nature de ELB auprès de 3 partenaires AWS).

Je ne crois pas qu’il soit bon de se comparer aux annonces marketing de AWS (ni de Goole, Facebook, …). Je suis sur que si on va visiter leur infra, on va trouver du legacy bien dégueulasse partout, comme chez presque tout le monde en fait.

:point_right: Un microservice c’est très consommateur de resources

Je n’ai pas entendu l’évocation de ce point (j’en suis a 46 minutes)

Après avoir cité en préambule quelques examples d’API et leur fonctionnement, on peut se douter que le coût (CPU/temps) d’utilisation entre un modèle d’API et un autre ne va pas être le même. La proportion entre l’appel le plus rapide et l’appel le plus lent va être de l’ordre de 1 000 000, voire plus.

Pour un appel entre fonctions dans un langage compilé, l’ordre de calcul sera donné et décodé en quelques nanosecondes, soit quelques instruction CPU. Les données sont directement exploitables sans aucune transformation. Pour un appel de type web-service REST on sera sur un ordre de grandeur de quelques millisecondes, on a donc un facteur 1 000 000 entre les extremes de ces cas généraux.

Pour un appel via le réseau, en assurant la haute disponibilité, on va avoir:

  • La mise en forme des donnĂ©es (transformation XDR, protobuf, JSON, XML, …) C’est très lourd, encore plus pour JSON ou XML.
  • L’utilisation d’un ou plusieurs protocoles sous-jacent (TCP/SSL/HTTP/…). C’est très lourd les stack TCP ne sont pas très light, SSL est très couteux. HTTP nĂ©cessite du parsing/dĂ©codage.
  • La traversĂ©es du rĂ©seau (kernel, carte rĂ©seau, switch, routeurs, load-balancers, …) est couteuse, sans oublier qu’en fonction des load balancer le flux va ĂŞtre au moins proxifiĂ©, donc dĂ©codage TCP / encodage TCP.
  • On retrouve ces mĂŞmes transformations, mais inversĂ©es Ă  l’autre bout de la chaine.

Donc un appel API via le réseau est très très couteux comparé à un appel à une bibliothèque de fonctions.

:point_right: Un microservice c’est très très complexe à débugger

Mettre des log centralisés et des traces c’est bien, mais parfois c’est la capture réseau qui va trouver le problème. Les microservices à base de kubernetes sont d’un complexité incroyable en terme de réseau. J’ai l’impression que beaucoup d’amateur de k8s croisent les doigts pour que le réseau fonctionne car ils n’ont pas les compétences pour comprendre ce qui se passe.

Entre le service de loadbalancing plus ou moins explicites, les dizaine/centaines de règles iptables, les bridge, les namespaces, les vxlan, … on à le droit de ne rien comprendre.

Ensuite, on à toute la stack de communication, tcp/ssl/http/h2/json/protobuf/messagebus ou chaque protocole et chaque composant (load-balancer, message-queue, …) ajoute une couche de complexité à analyser dans un processus qui fonctionne mal.

Donc, dans 99% des cas, ca fonctionne tout seul, puis lorsque le bug arrive, il faut appeler quelqu’un qui sait ce qu’est un système et un réseau, et qui va devoir composer avec ces empilage de couches hasardeuses (si il est disponible).

Je suis intervenu trois fois chez des clients chez qui ca se passait mal. Du kubernetes, du swarm et pour le dernier, je n’ai pas su. Dans les trois cas, j’ai du torturer un bon moment les Ops afin de comprendre le cheminement du réseau et comprendre les pannes:

  • perte sur le rĂ©seau, requĂŞte DNS Ă©chouĂ©s, service back quelconque pas rĂ©solu, erreur 500 sur le front. L’erreur Ă©tait logguĂ©e, mais il fallait Ă©tablir la causalitĂ©. J’ai Ă©galement notĂ© un “etcd” complètement a la ramasse, composant qui n’est pas nĂ©cessaire sans kubernetes ni microservices.

  • 300 containers haproxy dĂ©marrĂ©es sur une meme machine physique (?!), les OPS pensais qu’il y avait plusieurs machines. Au delĂ  de l’evidence des 300 process, les loadbalancer Ă©tait eux meme load balancĂ© par un LB totalement obscur fourni par swarm. Le problème Ă©tait donc liĂ© a l’OS qui passe sont temps a faire du context switch entre des composant qui sont fait pour ĂŞtre en mesure d’utiliser la totalitĂ© des resources de la machine pour le mieux.

  • SPOF dans l’application, donc un “truc” pas scalable au milieu de tout le bazar. Bien sĂ»r, les ops pensait que tout scale bien. Pour le coup, c’est l’appli qu’il a fallu regarder, et pas la couche du dessous.

Les decisions microservices ont couté cher à ces trois clients. Cela dit, je note que le calcul de rentabilité mérite d’etre fait. Si dans 99% des cas, tout va bien, pourquoi pas ?

Contre les architectures microservices

Le consensus du podcast semble ĂŞtre de dire que le choix du microservice implique:

  • :no_entry: une architecture plus complexe
  • :no_entry: plus de dev
  • :no_entry: plus de composants techinque qui augmentent la complexitĂ© globale de l’infra
  • :no_entry: plus d’ops

J’ajouterai:

  • :no_entry: un gouffre Ă©nergĂ©tique
  • :no_entry: une probabilitĂ© Ă©levĂ©e d’avoir un problème complexe
  • :no_entry: un concept totalement flou

Pour les architectures microservices

  • :+1: incompatibilitĂ© des langages
  • :+1: isoler un composant qui ne beneficie pas de scalabilitĂ© horizontale
  • :+1: mutualiser un service
  • :+1: moduler la disponibilitĂ© des composants

Mon point de vue

Pour ma part ce qui justifie l’utilisation de microservice c’est:

  • Le couplage de langages incompatibles (JS / PHP). De mon cotĂ© j’utilise une lib mjml en javascript pour gĂ©nĂ©rer des emails, j’appelle cette lib depuis du Go. j’aurai pu faire un fork/exec, mais j’ai choisi un microservice car cette merveilleuse lib JS parse tellement de code JS au dĂ©marrage qu’elle met un temps non nĂ©gligeable Ă  dĂ©marrer.

  • Un composant ne pas bĂ©nĂ©ficier de scalabilitĂ© horizontale, il faut lui reserver des resources verticales, il peut ĂŞtre pertinent de le passer en microservices. je n’ai pas d’exemple.

  • Mutualiser une service qui peut ĂŞtre commun Ă  plusieurs Ă©lĂ©ments d’une infra. Cela dit, parle-ton encore de microservices ? J’ai envie de parler de service interne. Chez moi, c’est le système d’envoie d’email (et quelques autres) qui est comma ça.

  • Livrer des services indĂ©pendamment les uns des autres. C’est une option qui semble sympathique, mais dans le fond, est ce que ca justifie vraiment toutes ces contraintes ?

Un autre cas me viennent en tête comme un migration progressive de langage pour l’application. Mais est-ce qu’une migration justifie l’adoption d’un architecture ?

Mon opinion : ca coute très cher pour pas grand chose en retour. Ca ressemble plus à une mode hype-driven qu’a quelque chose d’utile

Il y a un TL;DR ? :rofl:

Qui ne s’est pas retrouvé devant une application qui fait plusieurs centaines de milliers de ligne de code, avec 50% de code à ne pas prendre comme exemple et 20% de code inutilisé, dans une équipe de plusieurs dizaines de développeur avec une XP différente.

Et un développeur, ça vit, c’est un humain. Quand on regarde le code que l’on a fait il y a 2 ans, on sait qu’on le referait en mieux, avec moins de lignes de code, moins de couplage, moins de temps de travail.

Le micro service est une approche qui permet de ramener une application (en l’occurrence, le micro service) à une échelle plus humaine avec un code assimilable et donc maintenable sans risquer de casser ce que l’on ne connait pas (encore). Ainsi, le développeur a plus facilement la connaissance du cycle de vie de son service de bout en bout, et donc d’être dans le DevOps.