Published Date: March 1, 2020
Le traçage distribué, parfois appelé traçage des requêtes distribué, est une méthode de supervision destinée aux applications construites sur une architecture de microservices.
Les équipes IT et DevOps utilisent le traçage distribué pour suivre le parcours d’une requête ou d’une transaction tout au long de son passage dans l’application supervisée. Cela leur permet d’identifier les goulots d’étranglement, les bugs et autres problèmes ayant un impact sur les performances de l’application.
Le traçage est un processus fondamental en génie logiciel ; il est utilisé par les programmeurs avec d’autres formes de journalisation pour recueillir des informations sur le comportement d’une application. Mais le traçage traditionnel atteint ses limites lorsqu’il est utilisé pour dépanner des applications basées sur une architecture logicielle distribuée. Comme les microservices évoluent de manière indépendante, il est fréquent que plusieurs itérations d’un même service s’exécutent simultanément sur différents serveurs, emplacements et environnements, créant ainsi une toile complexe que chaque requête doit parcourir. Ces requêtes sont presque impossibles à suivre avec les techniques traditionnelles conçues pour les applications à un service.
Les solutions de traçage distribuées résolvent ce problème, et bien d’autres problèmes de performances, car elles suivent les requêtes à travers chaque service ou module et offrent un compte-rendu narratif intégral de cette requête. Les analystes, les SRE, les développeurs et autres peuvent observer chaque itération d’une fonction et ainsi superviser les performances en sachant quelle instance de cette fonction entraîne le ralentissement ou l’échec de l’application, et comment le résoudre.
Dans les pages qui suivent, nous allons approfondir le traçage distribué et les technologies utilisées pour le mettre en place dans votre entreprise.
Pour comprendre rapidement comment fonctionne le traçage distribué, le mieux est de regarder comment il gère une requête unique. Le traçage commence au moment où un utilisateur final interagit avec une application. Lorsque l’utilisateur envoie une requête initiale (une requête HTTP, pour prendre un exemple courant), un ID de trace unique lui est attribué. Au fur et à mesure que la requête parcourt le système hôte, chaque opération effectuée sur celle-ci (appelée « unité logique » ou « unité enfant ») reçoit des tags correspondants à l’ID de trace de la requête d’origine, à son propre ID unique, et à l’ID de l’opération qui a généré à l’origine la requête actuelle (appelée « unité parente »).
Chaque unité logique est une étape unique du parcours de la requête et embarque des données importantes relatives au processus de microservice qui exécute cette opération. Ces informations sont les suivantes :
- le nom du service et l’adresse du processus traitant la requête ;
- les logs et événements qui apportent un contexte sur l’activité du processus ;
- les tags permettant d’interroger et de filtrer les requêtes par ID de session, hôte de base de données, méthode HTTP et autres identifiants ;
- les traces détaillées de la pile et les messages d’erreur en cas d’échec.
Un outil de traçage distribué comme Zipkin ou Jaeger (que nous verrons tous deux plus en détail dans un instant) peut corréler les données de toutes les unités logiques et les présenter sous la forme de visualisations disponibles sur demande via une interface web.
Pensez maintenant à un jeu vidéo en ligne populaire, comptant des millions d’utilisateurs, autrement dit, la quintessence d’une application moderne basée sur des microservices. Il faut suivre l’emplacement de chaque utilisateur final, chaque interaction avec les autres joueurs et l’environnement, chaque objet acquis par le joueur, l’heure de fin de session et une foule d’autres données de jeu. Maintenir le bon fonctionnement du jeu serait impensable avec les méthodes de traçage traditionnelles. Mais c’est possible grâce au traçage des requêtes distribué.
Le principal atout du traçage distribué réside dans sa capacité à apporter de la cohérence aux systèmes distribués, ce qui entraîne une myriade d’avantages supplémentaires, parmi lesquels :
- une productivité accrue. La nature disjointe des architectures de microservices rend les fonctions de supervision des performances (suivi et résolution des problèmes, notamment) chronophages et coûteuses par rapport aux applications monolithiques. De plus, la forme sous laquelle les données d’échec sont fournies dans les microservices n’est pas toujours claire et oblige souvent les développeurs à interpréter les problèmes à partir d’obscurs messages d’erreur et codes d’état. Le traçage distribué offre une vue plus globale des systèmes distribués et réduit le temps passé par les développeurs à diagnostiquer et à déboguer les échecs des requêtes. La localisation et la correction des sources d’erreurs deviennent également plus efficaces ;
- une meilleure collaboration entre les équipes. Dans un environnement de microservice, chaque processus est développé par une équipe spécialisée, pour la technologie utilisée dans ce service. Identifier le point où une erreur s’est produite et la personne chargée de la corriger devient un véritable défi. Le traçage distribué permet d’éliminer ces silos de données ainsi que les goulots d’étranglement de productivité et autres problèmes de performances qu’ils génèrent, tout en réduisant le temps de réponse et en permettant aux équipes de travailler ensemble plus efficacement ;
- une mise en œuvre flexible. Les outils de traçage distribués fonctionnent avec une grande variété d’applications et de langages de programmation, si bien que les développeurs peuvent les incorporer dans tous les systèmes de microservices ou presque et afficher les données via une même application de traçage.
- Traçage du code : le traçage du code désigne l’interprétation, par un programmeur, des résultats de chaque ligne de code d’une application et l’enregistrement de son effet à la main plutôt qu’à l’aide d’un outil de débogage automatisé, dans le but de tracer l’exécution d’un programme. Le traçage manuel de petits blocs de code peut être plus efficace car le programmeur n’a pas besoin d’exécuter l’intégralité du programme pour identifier les effets de modifications mineures.
- Traçage des données : le traçage des données permet de vérifier l’exactitude et la qualité des données des éléments de données critiques (CDE), de remonter leur trace jusqu’à leurs systèmes sources, et de les superviser et les gérer à l’aide de méthodes statistiques. En règle générale, la meilleure façon d’effectuer des contrôles d’exactitude consiste à retracer les opérations jusqu’à leur origine et à les comparer aux données sources. Mais historiquement, cette approche n’est pas rentable dans les grands processus opérationnels. On utilise plutôt le contrôle statistique des processus (SPC) pour hiérarchiser, tracer, superviser et contrôler les CDE.
- Trace de programme (ptrace) : une trace de programme est un index des instructions exécutées et des données référencées lors de l’exécution d’une application. Les informations contenues dans une trace de programme incluent le nom du programme, le langage et l’instruction source qui a été exécutée, entre autres données, et sont utilisées dans le processus de débogage d’une application.
Dans ce contexte, la journalisation centralisée fait référence à l’agrégation des données des différents microservices au sein d’un emplacement central pour en faciliter l’accès et l’analyse.
L’une des tâches les plus fastidieuses (mais essentielle) pour les développeurs consiste à parcourir les logs d’une application pour trouver les erreurs qui causent un problème ou y contribuent. Et cette tâche peut devenir particulièrement ardue dans un environnement de microservices.
Comme on l’a vu précédemment, les méthodes de supervision traditionnelles fonctionnent bien avec les applications monolithiques parce qu’il n’y a qu’une seule base de code à suivre. On aurait tendance à appliquer les mêmes méthodes à une architecture de microservices, en traitant chaque microservice comme un petit monolithe et en s’appuyant sur ses données d’application et de log système pour diagnostiquer les problèmes. Le problème de cette approche est qu’elle ne capture que les données d’un seul service à la fois et ne permet de résoudre que les problèmes de ce processus particulier, ce qui ralentit la réponse.
La journalisation centralisée collecte et agrège les logs de plusieurs services dans un emplacement central où ils sont indexés dans une base de données. Dans le logiciel de gestion des logs, les données de log peuvent être interrogées, filtrées et regroupées en fonction de champs tels que l’état, l’hôte, la gravité, l’origine et l’horodatage.
La journalisation centralisée présente un certain nombre d’avantages dans un système distribué. Rassembler tous les logs utiles au même endroit réduit considérablement le temps et l’énergie nécessaires à la recherche de la cause profonde d’un problème d’application. En organisant les logs sous la forme de données significatives plutôt que de texte, cette approche permet des requêtes plus raffinées et sophistiquées, et apporte également une perspective plus claire sur les performances du système dans son ensemble.
La journalisation distribuée est la pratique consistant à maintenir la décentralisation des logs, et elle peut être préférable à la journalisation centralisée pour plusieurs raisons.
D’une part, l’envoi de logs vers un emplacement central peut consommer beaucoup de bande passante. En fonction de votre réseau mais aussi du nombre et de la fréquence des journaux générés, la journalisation centralisée pourrait entrer en concurrence avec des applications et des processus plus critiques. Certains systèmes de stockage des logs fonctionnent également de façon plus fiable lorsqu’ils sont plus proches de la machine générant les journaux.
La journalisation distribuée peut aussi être un avantage pour les systèmes à grande échelle. Les applications comprenant de nombreux microservices génèrent par nature d’innombrables messages de log, ce qui rend la journalisation centralisée plus lourde et moins rentable.
La journalisation des microservices est guidée par un ensemble de bonnes pratiques prenant en compte la nature modulaire et souplement connectée de l’architecture de microservices. L’objectif est d’apporter de la cohérence au système pour rendre le dépannage et le débogage plus efficaces et plus précis.
La journalisation des microservices intègre généralement les pratiques suivantes :
- la corrélation des requêtes. Chaque service d’un système de microservices interagit avec les autres pour exécuter une requête. En attribuant à la requête initiale un tag correspondant à un identifiant unique, vous pouvez facilement la suivre dans le système, identifier les erreurs potentielles et révéler si elles ont été causées par la requête de service précédente ou la suivante. Un développeur peut saisir cet identifiant unique dans le moteur de recherche de l’agrégateur de logs pour extraire les journaux de tous les services à des fins d’analyse ;
- la journalisation des informations. Des logs plus riches en informations offrent davantage de contexte au moment de comprendre un problème. Le nom du service générant le message de log, l’ID de corrélation, l’adresse IP du serveur et du client ayant émis la requête, ainsi que la date et l’heure auxquelles le message a été envoyé et reçu ne sont qu’une poignée des données à inclure ;
- la structuration des données de log. L’un des avantages d’une architecture de microservices est la possibilité d’utiliser différentes piles technologiques. Cela tend toutefois à multiplier les formats de log et donc à créer des difficultés dans l’analyse. Structurer les données dans un format standard, comme JavaScript Object Notation (JSON) par exemple, les rendra plus faciles à analyser et vous permettra de les interroger selon un large éventail de champs à partir d’un emplacement central ;
- la centralisation des journaux. La consultation et la corrélation de logs issus de différents serveurs consomment un temps et une énergie précieux qui augmentent de façon exponentielle avec le nombre de microsystèmes. La journalisation centralisée offre une solution à ce problème. N’oublions pas non plus que si un serveur ou un conteneur s’arrête sans avertissement, ses logs disparaissent également. Avec la journalisation centralisée, les logs sont envoyés à un dépôt central à intervalle régulier de quelques minutes, évitant ainsi les risques de perte irréparable.
OpenTracing et OpenCensus, auparavant deux projets de traçage distribué concurrents, ont récemment fusionné en un seul outil appelé Open Telemetry.
Hébergé par la Cloud Native Computing Foundation (CNCF), OpenTracing tente de proposer une API standardisée pour le traçage, pour permettre aux développeurs d’intégrer l’instrumentation dans des bibliothèques courantes ou dans leur propre code personnalisé en évitant toute dépendance vis-à-vis d’un fournisseur. Si cette approche offre une flexibilité très appréciable, l’API se focalise exclusivement sur le traçage, ce qui limite son usage et a créé des incohérences dans son implémentation par les développeurs et les fournisseurs.
OpenCensus a été développé chez Google sur la base de la plateforme de traçage interne de l’entreprise. Une fois la norme publiée en open source, Microsoft, avec d’autres fournisseurs et contributeurs, en a pris la direction. OpenCensus est un ensemble de bibliothèques multi-langages qui collecte des métriques sur le comportement des applications, puis transfère ces données vers n’importe quelle plateforme d’analyse en back-end choisie par le développeur. Cette norme peut également suivre les messages, les requêtes et les services de leur source à leur destination. En l’absence d’API disponible pour intégrer OpenCensus dans le code, les développeurs ont utilisé des agents d’instrumentation automatique créés par la communauté.
Open Telemetry, qui est géré par la CNCF, fusionne les bases de code d’OpenTracing et d’OpenCensus en s’appuyant sur les forces de chacun. Actuellement en version bêta, OpenTelemetry propose « un ensemble unique d’API, de bibliothèques, d’agents et de services de collecte » pour capturer les traces et les métriques distribuées d’une application. Celles-ci peuvent ensuite être analysées à l’aide d’outils d’observabilité populaires. Dans un avenir proche, OpenTelemetry ajoutera une capacité de journalisation à la capture de données.
Jaeger et Zipkin sont deux outils open source populaires pour le traçage des requêtes, chacun avec des composants similaires : un collecteur, une banque de données, une API de requête et une interface utilisateur web. Les requêtes sortantes sont tracées tout au long de l’application. Le collecteur enregistre puis corrèle les données entre différentes traces et les envoie à une base de données où elles peuvent être interrogées et analysées via l’interface utilisateur.
Jaeger et Zipkin se différencient par leur architecture et les langages de programmation qu’ils prennent en charge : Jaeger est implémenté en Go et Zipkin en Java. Zipkin prend en charge pratiquement tous les langages de programmation avec des bibliothèques dédiées pour Java, Javascript, C, C++, C#, Python, Go, Scala et autres. La liste des langages pris en charge par Jaeger est plus courte : C#, Java, Node.js, Python et Go.
AWS X-Ray est l’outil de traçage distribué natif d’Amazon Web Services (AWS). En tant que premier fournisseur de services cloud au monde, Amazon a été à l’avant-garde du passage des applications monolithiques aux microservices et, à ce titre, a développé son propre outil de traçage.
Comme des outils similaires, AWS X-Ray suit les requêtes des utilisateurs à travers une application, en collectant des données pouvant aider à identifier la cause des problèmes de latence, des erreurs et autres. Ces données de traces sont mises en forme au sein d’une carte des services que les développeurs peuvent analyser pour localiser et identifier les problèmes.
Naturellement, AWS X-Ray fonctionne bien avec d’autres services Amazon, comme AWS Lambda, Amazon EC2 (Elastic Compute Cloud), Amazon EC2 Container Service (Amazon ECS) et AWS Elastic Beanstalk. Cet outil est utile à la fois dans la phase de création et de test d’une application, mais aussi pour la maintenance de l’application une fois qu’elle est en production.
Kafka est une plateforme de diffusion distribuée à haut débit et à faible latence pour la gestion des flux de données en temps réel, souvent employée dans les architectures de microservices. Elle sert à traiter des flux d’enregistrements en temps réel, à publier ces flux d’enregistrements et à s’y abonner comme on le ferait avec une file de messages, et à les stocker de manière « durable et tolérante aux défaillances ».
Kafka utilise des « rubriques » (des catégories ou noms de flux sous lesquels les enregistrements sont publiés) pour abstraire les flux d’enregistrements. Pour chaque rubrique, Kafka gère un log partitionné, une séquence d’enregistrements ordonnée et augmentée en continu qui peut servir de journal de validation externe pour un système distribué.
Bien qu’il existe plusieurs bons outils d’agrégation des logs et de supervision sur le marché aujourd’hui, certains jouissent d’une popularité certaine.
Elastic (anciennement ELK : ElasticSearch, Logstash, Kibana) : Elastic combine trois outils essentiels et c’est l’une des piles les plus populaires pour les systèmes distribués. Logstash agrège les fichiers de log, ElasticSearch permet d’indexer et d’interroger les données, et Kibana fournit un tableau de bord de visualisation des données. Ces outils étant open source et gratuits, vous pouvez implémenter l’intégralité de la pile ou les utiliser individuellement.
Loggly : ce gestionnaire et analyseur de logs hébergé dans le cloud a été conçu par et pour les professionnels du DevOps. Il a été conçu pour gérer d’énormes volumes de données de log dans une interface facile à naviguer, et est principalement utilisé pour le dépannage et le support client. Il s’accompagne d’une API RESTful qui permet de l’intégrer à d’autres outils.
PaperTrail : PaperTrail n’agrège pas les logs mais donne plutôt à l’utilisateur final un moyen simple d’examiner ceux que vous collectez déjà. Il est facile à installer et possède une interface claire qui offre une vue consolidée des données, à l’aide du navigateur, de la ligne de commande ou d’une API.
Graylog : cet autre analyseur de journaux open source a été créé expressément pour aider les développeurs à localiser et à corriger les erreurs dans leurs applications. Il possède une interface utilisateur simple conçue pour la vitesse et gère un large éventail de formats de données.
Le traçage distribué est essentiel pour les applications distribuées
Les avantages des microservices pour la création d’applications basées dans le cloud sont bien documentés et leur adoption ne montre aucun signe de ralentissement. Face à la complexité croissante de ces systèmes, le traçage des requêtes distribué offre un énorme avantage par rapport à l’approche historique consistant à chercher les problèmes potentiels comme une aiguille dans une botte de foin. Si vous êtes responsable d’un système basé sur des microservices, vous pouvez transformer vos méthodes de travail en équipant votre entreprise de ce puissant outil.
Qu’est-ce que le traçage distribué ?
Comment fonctionne le traçage distribué ?
Quels sont les avantages du traçage distribué ?
Quels sont les différents types de traçage distribué ?
Qu’est-ce que la journalisation centralisée ?
Qu’est-ce que la journalisation distribuée ?
Comment fonctionne la journalisation des microservices ?
Que sont les normes ouvertes de traçage distribué Open Tracing, Open Census et Open Telemetry ?
Qu’est-ce que le traçage Jaeger ou Zipkin ?
Qu’est-ce qu’un log dans Kafka ?
Quels sont les meilleurs outils d’agrégation et de supervision des logs ?
Pour résumer : le traçage distribué est essentiel pour les applications distribuées
Les 5 pratiques fondamentales du DevOps
Qu’est-ce qui distingue les équipes DevOps performantes de celles qui échouent ? Ces 5 pratiques fondamentales.