Service mesh avec Linkerd
2019-08-31 par Badre BSAILA
Linkerd est un service mesh pour les plate-formes de µ-service tels que Kubernetes, Mesos, DC/OS… etc (Linkerd 1.x supporte toutes ces plateformes tandis que les versions 2.x supportent juste K8S à l’heure actuelle), Il ajoute les fonctionnalités d’observabilité (Etude de l’état interne d’un système à partir de ses outputs), monitoring, fiabilité et sécurité à vos conteneurs sans nécessiter de changement de code. Pour simplifier nous allons parler que des versions 2.x.
Projet Linkerd
Le projet est open-source, licensé sous Apache 2.0 et soutenu par Cloud Native Computing Foundation (CNCS) (à l’image de Linux, Kubernetes, Prometheus, …). Il était créé à l’origine par Buoyant Inc
Fonctionnement
Linkerd fonctionne en ajoutant des proxies transparents et très légers sur chaque µ-service: ils vont gérer le trafic réseau entrant de et sortant depuis le µ-service et envoyer des métriques au control plane et recevoir depuis des signaux. Ce schéma de fonctionnement permet de mesurer et manipuler le trafic des µ-services avec une charge négligeable.
Architecture
Linkerd comprend deux parties: le control plane et la data plane.
- Le control plane est un ensemble de service qui vont s’exécuter dans un namespace séparé (linkerd par défaut). Ils permettent d’agréger les métriques, exposer une api utilisateur, envoyer les données de contrôle aux proxies.
- La data plane consiste en un ensemble de proxies qui s’exécutent en face des instances µ-service.
Le control plane comprend:
- Controller: composé de plusieurs conteneurs (public-api, destination,… etc) qui offrent des fonctionnalités de contrôle.
- Grafana: Linkerd vient avec plusieurs dashboards de métriques pré-implémentées. Grafana est utilisé pour afficher ces dashboards.
- Prometheus: Toutes les métriques sont stockées dans Prometheus. Ils sont fournit par les proxies de la data plane sous le format native Prometheus. Le Prometheus de Linkerd est configuré pour travailler spécifiquement avec les données de Linkerd. Si vous avez déjà investit dans l’installation d’une infrastructure Prometheus et que vous voulez qu’elle s’intègre avec celle de Linkerd, veuillez suivre ce guide.
- Identity: ce composant est une autorité de certification qui va accepter des demandes CSR (Demande de certification des requêtes) depuis les proxies et va retourner des certificats signés avec une identité valable.
-
Proxy injector: c’est un contrôleur d’admission K8S qui va recevoir une requête à chaque fois qu’un pod est créé. L’injecteur va vérifier si le pod contient l’annotation
linkerd.io/inject: enabled
et si oui il va y installer un proxy. - Tap: reçoit des requêtes depuis la CLI Linkerd et le dashboard pour écouter les requêtes et les réponses des pods en temps réel.
- Web: application web pour accéder au dashboard Linkerd.
La data plane comprend un ensemble de proxies déployés en tant que conteneur à côté de chaque instance de vos µ-service métiers
-
Proxies: des composants ultra-légers (un proxy consomme 2Mb de mémoire et a une latence de moins d’un ms benchmark Linkerd vs Istio) développés en Rust et Go. Voici une liste non exhaustive des fonctionnalités d’un proxy:
- Transparent, le proxying ne nécessite pas de configuration et supporte HTTP, HTTP/2, WebSocket et plein d’autres protocoles TCP.
- Export automatique des métriques du trafic HTTP et TCP vers Prometheus.
- Support automatique du TLS.
- Support de l’équilibrage de charge.
Linkerd vient aussi avec une ligne de commande qui peut être installée dans une machine locale et qui permet de:
- Intéragir avec la data plane et le control plane.
- Voir les statistiques de trafic.
- Déboguer des issues en production.
- Installer et mettre à jour les data planes et control plane.
Le dashboard Linkerd est un outil graphique pour voir:
- L’état de vos µ-services en temps réel.
- Métriques de type: taux de requêtes en succès, requêtes servies par seconde, latence…etc.
- Voir le graphe des dépendances entre µ-service.
- Consulter l’état de santé de routes spécifiques.
Installation de Linkerd
Assurez-vous d’abord que vous avez accès à un cluster K8S. Si vous êtes sur une machine de dév locale, installez Docker Desktop (Windows 10 uniquement), et accédez à Settings > Kubernetes > Cochez “Enable Kubernetes”. Vérifiez aussi que vous avez une version K8S > 1.12
Installer la ligne de commande Linkerd
Téléchargez l’exécutable de Windows depuis le lien. Déplacez le dans un répertoire utilisateur de votre partition principale. Dans PC (clique droit) > Propriétés > Paramètres de système avancés > Variables d’environnement : Ajoutez le lien vers le dossier contenant l’exécutable dans la variable d’utilisateur Path. Si tout se passe bien, vous devez voir la version de la CLI en jouant la commande suivantes:
Si vous voyez l’information suivante “Server version: unavailable” ne vous inquiétez pas, c’est juste parce que vous n’avez pas encore installer le control plane.
Vérification de l’état du cluster K8S et installation
Pour vérifier que votre cluster K8S est configuré correctement :
Si tout est Ok, lancez l’installation du control plane:
A noter que linkerd install
génère un manifeste K8S avec un nouveau namespace (par défaut linkerd) et ses services associés.
Finalement, on vérifie que l’installation s’est bien terminé en lançant:
Prise en main de Linkerd
Accédez au dashboard en exécutant la commande suivante:
La commande installe un port de transfert depuis votre machine locale au pod linkerd-web (aka composant Web du control plane).
Dans le navigateur, vous allez avoir l’aperçu suivant:
Sur le menu gauche, le bouton Overview vous fait accéder aux différents namespaces du cluster K8S, un tableau récapitulatif des différents pods de chaque namespace avec comme informations: est ce que le pod est en proxy (meshé), taux de requêtes en succès, requêtes servies par seconde, latence et un lien vers le dashboard grafana du pod.
Si vous sélectionnez un pod spécifique, vous allez avoir son graphe de dépendances et les listes des appels HTTP faîtes depuis et vers ce dernier groupées par route avec des statistiques sur le nombre total des appels, la meilleure latence, la plus mauvaise et le taux de requêtes en succès.
La documentation officielle de Linkerd propose le manifeste d’un namespace de démonstration pour jouer avec Linkerd (les pods de ce namespace contiennent intentionnellement des bogues).
Exécutez la commande suivante afin de créer un namespace (emojivoto) avec plusieurs pods (dont web-svc qui est une application web en Node.JS):
Pour vérifier que le namespace emojivoto est OK, on va faire un forward sur le pod web-svc pour accéder à l’application web depuis notre machine locale sur l’adresse http://localhost
Pour ajouter les proxies aux pods du namespace emojivoto:
L’instruction dessous va récupérer tous les manifestes de déploiement des pods emojivoto, va leur appliquer la commande linkerd inject
qui enrichit les manifestes pour configurer le proxying, finalement nous passons les manifestes enrichis à kubectl apply -f -
pour les appliquer au cluster K8S.
Si vous avez fait les choses correctement, vous devrez avoir l’icône verte meshed sur la ligne du namespace emojivoto à l’extrême droite (Dashboard Linkerd > Overview (menu gauche)):
Vous pouvez aussi vérifier que le namespace est bien meshé en exécutant la commande:
Pour tester le composant Tap du control plane et avoir un aperçu en temps réel des requêtes d’un pod ou même de tout le namespace:
En accédant au grafana d’un pod, vous allez visualiser les dashboards des métriques collectés par les proxies:
Applications
Sécuriser le trafic entre les pods
Par défaut, Linkerd active le mTLS (mutual Transport Layer Security) pour la majorité du trafic HTTP entre les pods meshés. Étant donnée que le namespace du control plane (aka linkerd par défaut) sur K8S est meshé aussi. Alors les communications entre ses composants sont sécurisées.
En installant Linkerd, un certificat et une clé privée pour une entité racine de confiance sont générés par défaut, et ils sont stockés en tant que ConfigMap sur K8S. Ils seront utilisés par la suite pour vérifier les identités de tous les proxies du data plane. Vous avez aussi la main pour utiliser une racine de confiance autre que celle par défaut en fournissant certaines paramètres à l’appel linkerd install
. Il est important que le certificat et la clé privée restent privés et que les autres comptes de service K8S n’y ont accès. Par défaut ces secrets sont stockés dans le namespace du control plane (aka linkerd par défaut) et seul le composant identity y est accès en lecture.
Au démarrage du proxy, ce dernier générera une clé privée pour soi en mémoire, le proxy se connecte au composant du control plane identity qui est en fait une autorité de certification TLS (CA) pour obtenir un certificat signé valide. Ce dernier réponds par un certificat signé que le proxy utilise pour sécuriser tout le trafic entrant et sortant du pod. Le certificat a une durée de 24h et il est rafraîchit avec le même mécanisme.
Tout ceci est réalisé sans modifier une seule ligne dans le code des µ-services.
Injection du chaos
Injection du chaos est un concept issue de l’ingénierie du chaos et est basé sur l’augmentation des taux de requêtes en erreurs pour certains services afin d’analyser l’impact sur toute l’infrastructure et les applicatifs du système. Normalement pour effectuer ce genre de test, il fallait modifier le code des services en ajoutant une certaine configuration sur chaque composant qui permet d’activer le génération de réponses Ko.
Avec Linkerd l’injection du chaos est réalisé avec Traffic Split API de la Service Mesh Interface. TrafficSplit permet de rediriger un pourcentage du trafic HTTP vers un backend spécifique qui peut retourner des réponses 5xx, timeouts et même des réponses 2xx avec des contenus non valides.
Création du backend
Le plus simple schéma d’utilisation est de créer un nouveau pod est configurer nginx le serveur HTTP pour qu’il retourne systématiquement la réponse 500. Pour ce faire, appliquez la commande kubectl apply -f -
sur un manifeste K8S de type:
Rediriger une partie du trafic vers le backend Ko:
Il faudra rediriger une partie du trafic du pod sain vers notre backend Ko. Appliquer kubectl apply -f -
sur un manifeste de type:
Ainsi 1/10 du trafic va être redirigé vers le backend Ko.
La gestion des retries et timeouts
Les retries automatiques sont supportés par les service mesh de Linkerd. Ils permettent de gérer de manière souple les applicatifs touchés par des incidents.
Le problème est que la majorité des implémentations de retry cause des dérives et des fois ils amplifient de petites détérioration de services en panne générale du système (les fameux avalanche de retry).
Dés qu’une requête est rejoué un certain nombre de fois et qu’elle n’est pas en succès, Linkerd va la mettre en timeout.
Linkerd propose de définir non un maximum nombre de retry mais un budget de retry. Au lieu de spécifier qu’on peut au maximum faire 10 essaies, Linkerd va suivre l’évolution du ratio entre les requêtes normales et celles en retry et va le laisser au dessous d’une certaine limite par exemple les requêtes en retry doivent au plus ajouter 20% de requêtes en plus.
Les timeouts et retries sont définis toujours sur le pod client.
Pour définir qu’une route idempotente (n’a pas de body) est rejouable:
Pour définir le budget de retry:
Pour définir le timeout:
Équilibrage de charge
Pour les connections HTTP, HTTP/2 et gRPC, Linkerd balance automatiquement les requêtes entre les mêmes instance de service et utilise pour celà l’algorithme EWMA (Exponentially weighted moving average) qui permet d’envoyer en priorité les requêtes vers les endpoints les plus performants.
Traffic split (Déploiements canary et blue/green)
Linkerd expose cette fonctionnalité à l’aide de SMI (Service Mesh Interface) Traffic Split API. En créant une ressource K8S comme décrit dans les spécifications Traffic Split. Linkerd permet d’implémenter par défaut les déploiements canary et blue/green: voir Références.
Conclusion
Linkerd permet de créer des service mesh pour implémenter les fonctionnalités:
- Observabilité et Monitoring.
- Sécuriser le trafic TCP.
- Déploiements Canary et blue/green
- Équilibrage de charge par défaut sur le trafic HTTP, HTTP/2 et gRPC.
- Ingénierie du chaos.
C’est mon premier blog, n’hésitez pas à me faire part de vos remarques, corrections et suggestions dans une PR. Bon dév.
Références
-
Le site de documentation officielle de Linkerd.
-
Chaîne Youtube de Microsoft Developer, série Open Source Show - épisode All About Rust in Real Life: Linkerd 2.0
Badre BSAILA, Ingénieur d'étude et développement .NET sénior