Normaliser la télémétrie

le jeudi 17 septembre 2020

Bearstech | Dernière mise à jour : jeudi 17 septembre 2020

Pour fournir un service de qualité, il est indispensable de s'assurer de ses performances, grâce à la télémétrie. Ça tombe bien, c'est en cours de normalisation.

Notre prochain webinar

Télémétrie

D'abord ça marche, ensuite ça marche vite

La télémétrie fournit les informations nécessaires pour quantifier le comportement d'un service et donner des indices pour le réparer si ça ne marche pas, ou pas assez vite.

Salle de contôle durant l'ère soviétique

Normalisation

L'innovation en informatique fonctionne comme ça : un truc apparaît, devient indispensable, puis devient une norme (si tout se passe bien) et on peut enfin l'utiliser sereinement en choisissant l'implémentation qui nous sied le mieux.

Les processus de normalisation peuvent être extrêmement vicieux et les lobbyistes, peuvent faire des merveilles en cassant tout (coucou IPSEC), mais ça peut aussi bien se passer (coucou HTML5).

Le CNCF, l'association officielle des prosélytes du cloud, lutte contre la balkanisation des services bas niveaux de l'hébergement dans les nuages. Le cloud, malgré ses promesses, continue d'avoir une existence physique, et reste de l'hébergement. Une partie des services recommandés par le CNCF reste accessible pour les projets de toutes tailles, et leur protocole deviennent des standards de fait permettant une agréable compatibilité pour composer un hébergement de choix. On notera par exemple Containerd (la couche basse de Docker), Fluentd (pour router les logs), Jaeger (pour les traces), Prometheus (pour exposer des métriques)… et il y a une file d'attente pour de nouveaux projets.

Grafana

Grafana est devenu le standard de fait pour visualiser la télémétrie.

Créer une interface utilisateur est complexe et chronophage, pas mal s'y sont cassé les dents. Si en plus, elle sert de point central pour regrouper des mesures issues de tout horizon, le produit devient incontournable. Grafana est maintenant tellement incontournable, qu'il est attendu qu'un fournisseur de mesures (propriétaire ou non), mette à disposition le module Grafana (en opensource) pour interroger et visualiser ses données.

Grafana est le hub de la télémétrie.

D'abord spécialisé dans l'affichage des points, les fameuses timeseries, Grafana étend maintenant son horizon et a créé un outil pour gérer les journaux systèmes, de manières similaires à sa gestion de points, avec Loki. Il gère aussi les traces, avec une visualisation pour Jaeger. Grafana est tellement incontournable que la nouveauté d'InfluxDB, le très prometteur Flux qui permet de déclarer des flux de traitements de mesures (requêtes, aggrégations, alertes…), a été annoncé via le module Flux pour Grafana.

Grafana est la réponse, c'est quoi la question déjà ?

Opentelemetry

Statsd a été une première norme (avec des multiples implémentations), pour émettre et consolider des métriques, qui a quand même servi de point de départ à Datadog (qui a ajouté la notion de tag). Fort pratique pour les langages synchrones, il nécessite un agent qui va assurer les agrégations puis confier les mesures à un service de stockage adapté. Statsd normalise l'émission des points, mais pas le stockage et les requêtes associées.

Prometheus, un produit exfiltré des SRE de chez Google, propose une norme fort pratique, avec une approche inverse : ce n'est pas l'application qui pousse les mesures, mais le serveur de stockage qui va venir les tirer. Une discussion sur les vertus du push face à celles du pull peut occuper des journées entières, un peu comme les discussions entre petits boutistes et gros boutiens. Techniquement, une terminaison Prometheus est une URL HTTP qui va afficher du texte commenté, facilement parsable, et de manière optionnelle, une version binaire (en protobuf, parce que Google). Si votre service est codé avec un langage asynchrone (golang, nodejs, python-aio…), il va maintenir des compteurs, et les exposer en HTTP. C'est trivial d'exposer des mesures pour Prometheus, et cela n'exige rien de spécifique pour le déploiement. Prometheus est une des solutions de stockage de points, une parmi une offre diverse et légitime. C'est bien d'avoir une norme, mais c'est important d'avoir le choix dans les implémentations, qu'elles puissent être libres, auto hébergées ou "comme un service".

InfluxDB sait discuter avec son propre protocole, mais aussi utiliser les terminaisons Prometheus et même Statsd.

Google n'a pas une position hégémonique (éh ouais, pas à chaque fois) dans l'hébergement Cloud. ne peut donc pas imposer un Cloudwatch comme AWS, et globalement, il n'a pas envie, lui, de noyer ses utilisateurs sous les buzzwords en proposant un acronyme par question. Google a donc réfléchi à proposer/imposer une norme pour pouvoir fournir cette offre homogène et à terme permettre de mixer les mesures des services écrits par l'utilisateur ou ses services infogérés.

Il y a d'abord eu OpenCensus qui a fusionné avec Opentracing pour devenir Opentelemetry, plus fédérateur et ambitieux. Opentelemetry, c'est pour l'instant une norme spécifiant le format texte des terminaisons Prometheus, discutée par un consortium regroupant les gros fournisseurs de services de télémétrie. Pour commencer, ils ont les points, les traces vont suivre, et les logs sont dans le pipe, pour après. Il y a déjà aussi du code de disponible.

Mesurer quoi

De base, on mesure les ressources physiques des machines, pour voir s'il en reste, mais surtout qui les mange. On mesure ce que fournissent les services (débit, taille des files d'attente, temps de réponse…) via leur protocole, ou maintenant via une terminaison HTTP, tous les services exposant leurs mesures. Ensuite on mesure depuis l'extérieur, et les travaux récents du kernel vont très loin dans cette direction, les cgroups, puis tout ce que peut fournir le noyau Linux avec perf puis ebpf. Les applications peuvent utiliser des apm pour fournir des métriques et Sentry pour justifier ses incidents. Les mesures peuvent être en amont de l'application, avec l'analyse statique (dont le mythique code coverage), et en aval, avec des mesures vu du côté du client, comme l'API performance, ou des agents distants comme le Blackbox exporter. Les mesures distantes seront bruitées par les soucis de connexions Internet, mais il existe des technologies pour améliorer ça, comme le combo HTTP/2+TLS 1.3 avec une courbe elliptique, pour diminuer le coût d'établissement d'une connexion réseau, l'usage des CDN pour les clients lointains, et surtout un usage parcimonieux de la bande passante.

Mesurer comment

La base du timeseries, c'est une date, une clef, une valeur. Bon, ça, c'est la définition d'avant. Maintenant, on a la notion de "une ou plusieurs valeurs" et la valeur n'est pas forcément numérique, ainsi que la notion de tag, une clef et une valeur (en texte). Les tags permettent de filtrer et les valeurs permettent de faire des agrégations. C'est trivial de récupérer des points comme la consommation des ressources matérielles, ou même des temps de réponse aux services, les cgroups permettent de bien border ses métriques à des services précis, mais c'est aussi important d'avoir des métriques métiers. Les points, c'est chouette. On peut choisir une fréquence de collecte fixe, comme ça on a un volume de points prévisibles, on échantillonne à nouveau sur une fréquence moindre pour le passé, et hop, pas de surprise sur le volume de stockage. Par contre, on ne sait pas de quelle connexion on parle, ce qui a été fait pour manger tant de ressources, ni le détail de ce qui a pris du temps.

Traces

Pour savoir qui a mangé quoi, il faut utiliser une trace. Le plus tôt possible, on colle un identifiant à la requête (à base de random et de timestamp), donc à priori au niveau du point d'accès HTTP, et l'on confiera cet identifiant aux services/actions qui suivent. Le cas le plus traditionnel étant la requête HTTP qui va discuter avec une base de données, mais maintenant, ces appels pourront être parallélisés (avec un pool de connexions) et complété par des services distants (comme un moteur de recherche, un serveur de cache, ou le tant redouté service distant). Hors débug, on ne va pas s'amuser à tout tracer, par ce que ça prend de la place et ça peut être un peu coûteux si votre application répond vite. On va donc soit tracer de manière explicite (en déclenchant la trace via un header spécifique ou un bidouillage dans l'URL), soit de manière statistique, une requête sur mille, ce qui permettra d'avoir des tendances et de voir comment certaines urls se comportent au fil des versions ou de la charge globale du service.

Les offres clouds ont tout intérêt à permettre une visibilité entre les traces issues du code de son client, et des services qu'il va consommer. Pour les offres serverless, qui vont chaîner des bouts de code métier, les traces sont indispensables pour comprendre l'exécution d'une requête et ses latences.

Journaux

Les journaux, les logs quoi, vont raconter ce qu'il se passe, que ce soit des choses attendues ou des incidents. Il est important d'avoir des logs qualifiés, pour pouvoir reconstruire une chaîne d'incident. Les loggers modernes permettent de bien qualifier ses logs, et sinon, bah, ce sera à coups de grok que l'on qualifiera ses journaux. Si l'on arrive à avoir dans une ligne de log l'identifiant de la trace qui l'a déclenché, c'est le jackpot.

Elasticsearch et Logstash considèrent que les logs sont des textes qu'il faut qualifier, puis indexer. Loki a une approche orthogonale où les logs sont des suites d'évènements avec bien sûr un timestamp, mais surtout des tags (le nom de la machine, du service, la sévérité…) ce qui permet simplement d'avoir des filtres compatibles avec des mesures et de faire des corrélations et autres analyses visuelles directement dans Grafana.

Le monde du suivi publicitaire (et celui de la sécurité) a lancé une nouvelle approche pour gérer les logs avec une faible latence : le stockage dans des bases de données orientées colonnes. Popularisé par Cassandra, le flambeau est maintenant repris par Postgresql Timescale et Clickhouse qui nous vient de chez le russe Yandex.

Mesurer pourquoi

Mesurer permet d'associer un débit avec une latence et une consommation de ressources. Si la latence est trop grande pour un débit donné, on va soit améliorer le code (en donnant plus d'amour aux algorithmes, ou en mettant du cache), soit augmenter les ressources disponibles jusqu'au prochain palier technique.

Mesurer permet aussi de surveiller ce qui est cassé : techniquement, une mesure nulle (pas 0, null) indique une absence de mesure, et donc un truc éteint, que ce soit une machine ou un service. Cet incident (enfin la répétition de l'incident sur une période courte), va déclencher une alerte ou une action corrective (promotion d'un serveur secondaire, remplacement d'un nœud d'un clusteur).

Les temps d'indisponibilité sont aussi mesurés, que ce soit en interne ou via un service tiers (et neutre) comme Site24.

De manière automatique, en se basant sur les mesures, il sera possible d'adapter le nombre de nœuds en fonction de la sollicitation du service, en gardant un œil sur la mesure de qualité du service. Pour accompagner un pic de fréquentation, on ajoutera des nœuds, c'est le fameux autoscale. Si ajouter de la puissance n'améliore pas la qualité du service, il faut lever une alerte et diminuer la violence. Une fois le pic passé, on pourra éteindre le surplus de ressources pour ne pas faire flamber la facture.

Moarr power

Avec tous ces chiffres, on va pouvoir travailler sur la qualité et les prévisions de croissance, le célèbre capacity planning en se méfiant des paliers techniques. Pour avoir une idée plus précise du comportement avec des débits plus conséquents, il faudra faire des tests de charge.

L'approche SRE recommande de gérer tout ça comme des budgets, avec la vélocité (le temps pour développer et livrer une nouvelle fonctionnalité) pour arbitrer entre ces points contradictoires. Ils considèrent qu'une machine qui n'a pas consommé son budget interruption est considérée comme du gâchis pour la vélocité, ce qui peut surprendre les habitants du vieux monde.

Pour que cette notion de débit et de qualité soit parlante, il est nécessaire d'avoir des mesures métiers, ce qui est assez évident pour du e-commerce : le chiffre d'affaires ou le taux de conversion sont compréhensibles par tout le monde, mais pertinents pour n'importe quel type de sites. Ces mesures sont telles que les utilisateurs les perçoivent, sans trop distinguer ce qu'il se passe dans le navigateur web et coté serveur. Et donc leurs améliorations seront âprement négociées entre le développement front et back ainsi que l'UX, avec des essais d'ergonomie, des simulations de connexions 3G pourries, des services workers et autres HTTP/2 : toute la pile est en jeu pour améliorer l'expérience utilisateur.

Avoir des mesures précises et métiers est indispensable pour proposer un autoscale qui ne soit pas décevant. L'approche naïve d'ajouter des nœuds dès qu'un nœud dépasse 80% CPU ou que le temps de réponse dépasse un seuil risque d'avoir un résultat chaotique, avec une grosse latence, voire des effets de clignotement (allumé, éteint, allumé…). Si par malheur l'ajout de nœuds n'améliore rien (on a atteint un palier évoqué technique), il risque même d'ajouter du bruit et de la fureur. Un peu de finesse, comme enlever ou restreindre le débit d'un service bruyant (technique dite de la boite à fusible), ou de n'ajouter des nœuds supplémentaires que si la qualité (comme le temps de réponse) est améliorée après le premier ajout de ressources matérielles, sera bien plus efficace pour gérer un pic d'utilisation.

Si les fournisseurs clouds ont très envie que vous mesuriez finement vos applis, ce n'est pas que pour faire croître votre niveau d'exigence, mais surtout pour vous proposer de l'autoscaling qui fonctionne correctement.

Pour des pics prévisibles, comme la diffusion d'une pub à la télé, il est possible d'anticiper l'ajout de ressources sans attendre les actions du robot, après avoir vérifié que la demande lors du pic reste dans le même palier technique. Ajouter des workers web sur une base de données à genoux ne sera jamais beau à voir. Attention, le serveur n'est pas tenu de suivre aveuglément une demande énorme de ressources, ce qui peut être considéré comme une attaque et remédié de manière expéditive. Les exemples classiques sont la bande passante d'un gros DDOS ou l'enchaînement de 401 d'une attaque par dictionnaire.

Les calculs statistiques et maintenant l'apprentissage machine promettent de belles choses comme la détection d'anomalies ou les prévisions (comme la météo), mais sont à surveiller de près. Il peut être difficile de distinguer la charge induite par la citation depuis un site prestigieux (l'effet Slashdot pour les anciens) d'une bête attaque (ou un test de charge non planifié).

Grafana reste le point central pour visualiser les mesures étonnantes, décider s'il faut y remédier et si ça a bien fonctionné.

You get telemetry

Service Audit de Performance web gitlab

Bearstech vous propose ses services Audit de Performance web gitlab

Découvrir ce service

Partager cet article

Flux RSS

flux rss

Partager cet article :