Publié par

Il y a 5 mois -

Temps de lecture 9 minutes

Écho des TOs n°5 : Service Mesh, comment en est-on arrivé là ?

photo
L’Echo des TOs #5

Service Mesh, comment en est-on arrivé là ?

 

Régulièrement, nous vous proposons l’écho des TO. Les Technical Officers de Xebia vous proposent un focus sur les sujets phares de 2019, retours d’experience, présentation de projets internes, etc. (Re) découvrez les précédents articles :

Bienvenue dans ce nouvel écho des TOs

La communication entre applications a été mise sous pression par l’émergence des architectures microservices, la conteneurisation et l’orchestration. Dans un tel contexte comment configurer, mesurer, fiabiliser, sécuriser et rendre les échanges entre applications performants ? Résumons ce qu’il s’est passé ces cinq dernières années pour mieux comprendre ce qui a fait émerger les outils de Service Mesh et détaillons ce en quoi ils consistent.


Microservices ?

La mouvance microservices vise à sortir des applications monolithiques considérées trop lourdes, trop dures et trop risquées à faire évoluer. Le but ? Livrer des correctifs de bugs et des évolutions plus rapidement. En somme, les monolithes ne tenaient pas le rythme de l’agilité. On a donc commencé à les découper : plus petit, c’est mieux. Conséquence de ce découpage les appels de fonctions internes ont été remplacés par des appels réseaux.

L’ère des conteneurs

A peu près en même temps a été démocratisée la conteneurisation avec une solution à très fort succès que nous connaissons tous : Docker. Fini les procédures d’installations avec description des pré-requis en termes de bibliothèques systèmes, versions de paquets ou de machines virtuelles. Il est désormais possible de livrer tout le contenu nécessaire à l’exécution d’un programme dans une image que l’on peut déployer à l’infini, de manière reproductible et répétable, sous la forme de conteneurs.

Livrer, déployer ne consiste donc plus à mettre à jour, patcher ou écraser tel binaire ou fichier de configuration, mais plutôt à supprimer un conteneur et à en créer un nouveau à partir de la dernière image disponible (cf. infrastructure immutable).

Bienvenue aux orchestrateurs

La guerre du déploiement vaincue pour le bonheur des devs et des ops, il restait toutefois un manque qui n’a pas mis très longtemps à être comblé. Nos micro applications conteneurisées étant nombreuses, il fallait un outil pour les déployer toutes et sur un parc de machines indifférenciées. Une application pouvant dans l’idéal être déployée sur n’importe quelle machine. Pour gérer le failover des conteneurs, les mises à jour ou l’adaptation aux besoins en capacité de calcul ou de mémoire, il était nécessaire de disposer d’un outil permettant de les créer simplement et surtout rapidement. Et l’orchestrateur était né.

Avec un orchestrateur, on exprime un état cible de déploiement, un niveau de service et c’est l’orchestrateur qui s’occupe de le réaliser pour nous, tout en optimisant l’usage des ressources (algorithmes de binpacking). Besoin de passer de 1 à 10 instances du même conteneur ? Besoin de maintenir ces 10 instances en vie quoi qu’il en coûte ? Pas de problème, l’orchestrateur fera au mieux avec les ressources disponibles.

 

Dans un tel contexte les applications n’arrêtent pas d’être déplacées en fonction des évènements de failover, de mises à jour, etc. Elles doivent toutefois toujours réussir à communiquer entre elles. La pression sur la bonne configuration de la communication entre applications est énorme et de nouveaux challenges ont émergés.

Communication inter-applications

Il faut, en effet, être capable de déterminer dynamiquement les adresses des applications en état de fonctionnement, parmi celles-ci, trouver lesquelles présentent la latence la plus faible, lesquelles sont dans la version adéquate et ensuite distribuer de manière équitable (round-robin ou autre) les requêtes. Une fois la requête émise, il faut gérer les erreurs, gérer le rejeu, protéger les applications vis à vis d’un client (rate limiting), empêcher la saturation d’un service distant (circuit breaker). Il faut également mesurer les échanges effectués sur la plateforme et assurer le chiffrement des données transportées. En résumé, comment gérer de manière fiable, sécurisée et performante les nombreux échanges et les mesurer, dans un contexte aussi dynamique ?

La nature ayant horreur du vide, ces nouveaux challenges ont été adressés et solutionnés par de nombreux outils. Ces outils nous les connaissons tous : annuaires de découverte de services (Consul, Etcd, Zookeeper, Eureka), load balancers (HAProxy, Nginx, Traefik), bibliothèques et outils de métrologie (metrics, Prometheus), de tracing (OpenTracing, Jaeger) et de résilience (Hystrix, Resilience4j, rate limiting, exponential backoff, back pressure, circuit breaker, timeouts, pools de connexions).

L’approche qui repose sur des éléments d’infrastructure (Load Balancer) a l’inconvénient de déporter une partie de la configuration de la communication des applications dans un élément externe. Cet élément externe est bien souvent mutualisé et les équipes applicatives n’ont pas forcément la main dessus.

L’approche qui repose sur des bibliothèques intégrées aux applications a, quant-à elle, l’inconvénient d’être spécifique au langage, au framework ou à la stack technique mise en place. Il est par ailleurs bien souvent complexe d’intégrer tous ces outils entre eux ou de modifier leur configuration à chaud. Pouvoir les configurer de manière homogène au sein de toute sa plateforme relève de l’utopie et s’assurer qu’ils sont correctement configurés ou mis en place, relève de la gageure.

L’ère du service Mesh ?

Les micro services, la conteneurisation et l’orchestration ont amené un outillage conséquent pour faciliter la communication entre services. Ce patchwork d’outils hétérogènes est complexe à intégrer et le manque d’homogénéité dans la configuration a donc favorisé l’émergence d’une solution ad-hoc.

Le service mesh est une solution dédiée à la gestion des problématiques de communication entre services. Ce “nouveau” concept adresse la problématique de la communication entre applications de manière centralisée et propose de remplacer la galaxie d’outils existants par un outillage unique.

Service Mesh : Concept

L’idée du Service Mesh consiste à placer un proxy devant chaque instance applicative.

Note : D’autres solutions mettent en avant la possibilité d’utiliser un proxy centralisé – un par machine par exemple – mais ces possibilités sont cependant minoritaires et ne sont pas en phase avec la tendance générale qui émerge du concept.

Ce proxy est le même pour toutes les applications et n’est donc pas dépendant de la stack applicative. Tout le trafic réseau de l’instance applicative est redirigé via le proxy de manière totalement transparente pour l’application. Les proxys de chaque application communiquent ensuite entre eux, aucune communication n’est effectuée en direct entre les applications !

Note: Dans un contexte Kubernetes, cette caractéristique est offerte par les PODs. Un POD est un ensemble de conteneurs : (dans notre cas : proxy + application) qui sont nécessairement déployés sur une même machine et qui bénéficient d’une isolation réseau. Au sein de ce réseau, le trafic est configuré par l’outil de service mesh qui force la redirection du trafic via le proxy.

Le proxy acquiert ainsi la vision et le contrôle de tous les échanges réseaux qui transitent entre chaque application et au sein de toute la plateforme.

Observabilité

Ce principe permet aux proxys de collecter les métriques concernant les échanges : temps de requêtes, volume de données échangé, statut de réponse et de les remonter dans une base de données appropriée (Prometheus, time series database, …). Une application, dès lors qu’elle est déployée dans le Mesh, bénéficie automatiquement de ces métriques techniques. Il n’est plus nécessaire de contrôler que chaque application a correctement intégré une bibliothèque permettant de le faire.

Il en va de même pour les logs des appels qui peuvent facilement être déversés dans un système de centralisation des logs et qui sont pertinemment étiquetés afin de bénéficier aux analyses des problèmes de production.

La mise en place de tracing est également facilitée. L’appel d’un service à un autre passe obligatoirement par le proxy qui remplit parfaitement son rôle de contrôleur et génère les traces (spans) automatiquement ou à moindre coût.

Contrôle intelligent du trafic

En plus des aspects observabilité, le service mesh permet de connecter les services entre eux. Pour y parvenir l’outil de service mesh (Istio, Linkerd) écoute les événements qui ont lieu sur l’orchestrateur : ajout, suppression, panne, disponibilité d’instances et propage en conséquence la configuration adéquate aux différents proxys qui peuvent décider, de manière intelligente, sur quelle instance diriger le trafic.

Bien sûr, ce trafic peut également faire l’objet de contrôles. Un opérateur de la plateforme ou un développeur d’une application peut configurer des règles (écrites sous forme de code – On peut parler de “communication as code”) qui permettent de définir des redirections, du partage de trafic entre versions, de la bascule de trafic pour des montées de versions, des règles permettant d’injecter des erreurs, autoriser ou interdire des requêtes, d’introduire de la latence, de faire du mirroring, du rejeu, de configurer du circuit breaking, des timeouts, … Ces règles sont bien sûr déployées sur les proxys qui se chargent ensuite de les appliquer.

Du chiffrement pour tous

Un aspect non négligeable consiste aussi à offrir le chiffrement des données transportées. Comme tous les échanges sont contrôlés par les proxys, tous les échanges entre proxys peuvent être chiffrés aisément. L’outil de service mesh s’occupe de déployer et renouveler les certificats au niveau de chaque proxy. Il n’est donc plus nécessaire de le faire au niveau de chaque application. Le mTLS devient la norme et se configure en quelques lignes de YAML.

Résumé : le Service Mesh en 2 paragraphes

Le Service Mesh se traduit finalement par un réseau de proxy applicatifs, qui est configuré et piloté de manière centralisée. Il s’agit donc avant tout d’un changement de localisation de fonctionnalités. Les fonctionnalités qui permettent de mesurer, fiabiliser, sécuriser et rendre les échanges performants sont déjà connues. Dans le cadre du service mesh elles sont simplement facilitées, découplées d’un élément d’infrastructure mutualisé (de type Load Balancer) et découplées de bibliothèques applicatives.

Ce changement de localisation impacte les développeurs, car il décharge l’application d’un outillage lourd, et “impose” une nouvelle responsabilité : garder un oeil attentif sur les propositions de modification de la configuration de la communication au sein de toute la plateforme.

Publié par

Publié par Sergio Dos Santos

Craft / DevOps / Back / Front / Cloud

Commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Xebian, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.