Stockage des métriques : comment nous sommes passés de Graphite+Whisper à Graphite+ClickHouse

Bonjour à tous ! Dans mon Dans notre précédent article, je parlais de l'organisation d'un système de surveillance modulaire pour une architecture microservices. Rien ne reste immobile, notre projet est en constante expansion, tout comme le nombre de métriques stockées. Comment nous avons organisé la transition de Graphite+Whisper à Graphite+ClickHouse dans des conditions de forte charge, nos attentes à cet égard et les résultats de la migration se lisent ci-dessous.

Stockage des métriques : comment nous sommes passés de Graphite+Whisper à Graphite+ClickHouse

Avant de vous expliquer comment nous avons organisé la transition du stockage des métriques de Graphite+Whisper à Graphite+ClickHouse, je voudrais donner des informations sur les raisons qui ont conduit à une telle décision et sur les inconvénients de Whisper avec lesquels nous avons vécu pendant une longue période.

Problèmes avec Graphite+Whisper

1. Charge élevée sur le système de disque

Au moment de la transition, nous recevions environ 1,5 million de métriques par minute. Avec ce flux, l'utilisation des disques sur les serveurs était d'environ 30 %. Dans l'ensemble, c'était tout à fait acceptable — tout fonctionnait de manière stable, les écritures étaient rapides, les lectures aussi… Jusqu'à ce qu'une des équipes de développement ne déploie une nouvelle fonctionnalité et ne commence à nous envoyer 10 millions de métriques par minute. C'est à ce moment-là que le système de disque a commencé à s'engorger, et nous avons vu une utilisation à 100 %. Le problème a pu être résolu rapidement, mais la mauvaise expérience est restée.

2. Absence de réplication et de cohérence

Comme beaucoup de ceux qui utilisent/ont utilisé Graphite+Whisper, nous envoyions le même flux de métriques à plusieurs serveurs Graphite pour créer de la redondance. Cela ne posait pas de problèmes majeurs — jusqu'à ce qu'un des serveurs tombe pour une raison quelconque. Parfois, nous parvenions à redémarrer le serveur tombé assez rapidement, et carbon-c-relay pouvait lui envoyer les métriques de son cache, parfois non. Et à ce moment-là, il y avait un trou dans les métriques, que nous remplissions avec rsync. La procédure était assez longue. La seule chose qui nous sauvait, c'est que ces incidents étaient très rares. De plus, nous prenions périodiquement un ensemble aléatoire de métriques et les comparions avec d'autres similaires sur les nœuds voisins du cluster. Environ 5 % des cas révélaient des différences, ce qui ne nous réjouissait pas.

3. Grand volume d'espace occupé

Étant donné que nous écrivons dans Graphite non seulement des métriques d'infrastructure, mais aussi des métriques commerciales (et maintenant des métriques provenant de Kubernetes), nous nous trouvons souvent dans une situation où la métrique ne contient que quelques valeurs, et le fichier .wsp est créé en tenant compte de toute la période de rétention, occupant ainsi un espace prédéfini qui était d'environ 2 Mo. Le problème est aggravé par le fait que de tels fichiers apparaissent en grande quantité avec le temps, et lors de la génération de rapports basés sur eux, le temps et les ressources nécessaires pour lire les points vides sont considérables.

Il convient de noter dès le départ que les problèmes décrits ci-dessus peuvent être combattus par divers moyens et avec des degrés d'efficacité variés, mais plus vous recevez de données, plus ils s'aggravent.

Ayant tout ce qui précède (en tenant compte de précédents article), ainsi que la croissance constante du nombre de métriques reçues, le désir de réduire l'intervalle de conservation de toutes les métriques à 30 secondes (et si nécessaire, à 10 secondes), nous avons décidé d'essayer Graphite+ClickHouse comme alternative prometteuse à Whisper.

Graphite+ClickHouse. Attentes

Après avoir assisté à plusieurs meetups des gars de Yandex, lu quelques articles sur Habré, fouillé la documentation et trouvé des composants raisonnables pour intégrer ClickHouse à Graphite, nous avons décidé de passer à l'action !

Nous voulions obtenir ce qui suit :

  • réduire l'utilisation du sous-système de disque de 30% à 5%;
  • réduire l'espace occupé de 1 To à 100 Go;
  • avoir la capacité d'accepter 100 millions de métriques par minute sur le serveur;
  • réplication des données et tolérance aux pannes par défaut;
  • ne pas passer une année sur ce projet et effectuer la transition dans un délai raisonnable;
  • changer sans temps d'arrêt.

Assez ambitieux, n'est-ce pas ?

Graphite+ClickHouse. Composants

Pour recevoir des données via le protocole Graphite et les enregistrer par la suite dans ClickHouse, le choix s'est porté sur carbon-clickhouse (golang).

Comme base de données pour le stockage des séries temporelles, la dernière version stable de ClickHouse à ce moment-là, la version 1.1.54253, a été choisie. Lors de son utilisation, des problèmes ont surgi : une multitude d'erreurs étaient générées dans les journaux, et il n'était pas tout à fait clair comment y faire face. Dans une discussion avec Roman Lomonosov (auteur de carbon-clickhouse, graphite-clickhouse et bien d'autres), une version plus ancienne la version 1.1.54236. Les erreurs ont disparu – tout a commencé à fonctionner à merveille.

Pour lire les données à partir de ClickHouse, nous avons choisi graphite-slickhouse (golang). En tant qu'interface API pour Graphite – carbonapi (golang). Pour organiser la réplication entre les tables ClickHouse, nous avons utilisé zookeeper. Pour le routage des métriques, nous avons gardé notre cher carbon-c-relay (C) (voir l'article précédent).

Graphite+ClickHouse. Structure des tables

«graphite» — une base de données que nous avons créée pour les tables de surveillance.

«graphite.metrics» — table avec le moteur ReplicatedReplacingMergeTree (répliqué ReplacingMergeTree). Dans cette table, sont stockés les noms des métriques et les chemins vers celles-ci.

CREATE TABLE graphite.metrics ( Date Date, Level UInt32, Path String, Deleted UInt8, Version UInt32 ) ENGINE = ReplicatedReplacingMergeTree('\/clickhouse\/tables\/replicator\/graphite.metrics', 'r1', Date, (Level, Path), 8192, Version);

«graphite.data» — table avec le moteur ReplicatedGraphiteMergeTree (répliqué GraphiteMergeTree). Dans cette table, sont stockées les valeurs des métriques.

CREATE TABLE graphite.data ( Path String, Value Float64, Time UInt32, Date Date, Timestamp UInt32 ) ENGINE = ReplicatedGraphiteMergeTree('\/clickhouse\/tables\/replicator\/graphite.data', 'r1', Date, (Path, Time), 8192, 'graphite_rollup')

«graphite.date_metrics» — table remplie selon condition, avec le moteur ReplicatedReplacingMergeTree. Dans cette table, sont enregistrés les noms de toutes les métriques rencontrées au cours de la journée. Les raisons de sa création sont décrites dans la section «Problèmes» à la fin de cet article.

CREATE MATERIALIZED VIEW graphite.date_metrics ( Path String, Level UInt32, Date Date) ENGINE = ReplicatedReplacingMergeTree('\/clickhouse\/tables\/replicator\/graphite.date_metrics', 'r1', Date, (Level, Path, Date), 8192) AS SELECT toUInt32(length(splitByChar('.', Path))) AS Level, Date, Path FROM graphite.data

«graphite.data_stat» — table remplie selon condition, avec le moteur ReplicatedAggregatingMergeTree (répliqué AggregatingMergeTree). Dans cette table, est enregistré le nombre de métriques entrantes, avec une répartition jusqu'au 4e niveau de profondeur.

CREATE MATERIALIZED VIEW graphite.data_stat ( Date Date, Prefix String, Timestamp UInt32, Count AggregateFunction(count)) ENGINE = ReplicatedAggregatingMergeTree('\/clickhouse\/tables\/replicator\/graphite.data_stat', 'r1', Date, (Timestamp, Prefix), 8192) AS SELECT toStartOfMonth(now()) AS Date, replaceRegexpOne(Path, '^([^.]+.[^.]+.[^.]+).*$', '1') AS Prefix, toUInt32(toStartOfMinute(toDateTime(Timestamp))) AS Timestamp, countState() AS Count FROM graphite.data GROUP BY Timestamp, Prefix

Graphite+ClickHouse. Schéma d'interaction des composants

Stockage des métriques : comment nous sommes passés de Graphite+Whisper à Graphite+ClickHouse

Graphite+ClickHouse. Migration des données

Comme nous nous en souvenons des attentes pour ce projet, la transition vers ClickHouse doit se faire sans temps d'arrêt, par conséquent, nous devions en quelque sorte basculer tout notre système de surveillance vers le nouveau stockage de manière aussi transparente que possible pour nos utilisateurs.
Nous l'avons fait de cette façon.

  • Dans carbon-c-relay, nous avons ajouté une règle pour envoyer un flux supplémentaire de métriques à carbon-clickhouse l'un des serveurs participant à la réplication des tables ClickHouse.

  • Nous avons écrit un petit script en Python qui, à l'aide de la bibliothèque whisper-dump, a lu tous les fichiers .wsp de notre stockage et a envoyé ces données au carbon-clickhouse décrit ci-dessus en 24 flux. Le nombre de valeurs métriques acceptées dans carbon-clickhouse atteignait 125 millions par minute, et ClickHouse n'a même pas transpiré.

  • Nous avons créé une source de données distincte dans Grafana pour déboguer les fonctions utilisées dans les tableaux de bord existants. Nous avons identifié une liste de fonctions que nous avons utilisées, mais qui n'étaient pas implémentées dans le carbonapi. Nous avons écrit ces fonctions et envoyé des PR aux auteurs de carbonapi (un grand merci à eux).

  • Pour basculer la charge de lecture, nous avons modifié les points d'extrémité dans la configuration des équilibreurs de charge, passant de graphite-api (interface API pour Graphite+Whisper) à carbonapi.

Graphite+ClickHouse. Résultats

  • nous avons réduit l'utilisation du système de disque de 30% à 1%;

    Stockage des métriques : comment nous sommes passés de Graphite+Whisper à Graphite+ClickHouse

  • nous avons réduit l'espace occupé de 1 To à 300 Go;
  • nous avons la capacité d'accepter 125 millions de métriques par minute sur le serveur (pics lors de la migration);
  • nous avons transféré toutes les métriques à un intervalle de stockage de 30 secondes;
  • nous avons obtenu la réplication des données et la tolérance aux pannes;
  • nous avons basculé sans temps d'arrêt;
  • nous avons dépensé environ 7 semaines au total.

Graphite+ClickHouse. Problèmes

Dans notre cas, nous avons également rencontré des écueils. Voici ce à quoi nous avons été confrontés après la migration.

  1. ClickHouse ne relit pas toujours les configurations à la volée, il faut parfois le redémarrer. Par exemple, pour la description du cluster zookeeper dans la configuration de ClickHouse — elle n'était pas appliquée avant le redémarrage de clickhouse-server.
  2. Les grandes requêtes ClickHouse ne passaient donc pas, ce qui fait que notre connexion graphite-clickhouse à ClickHouse ressemble à ceci :
    url = "http://localhost:8123/?max_query_size=268435456&max_ast_elements=1000000"
  3. De nouvelles versions stables de ClickHouse sortent assez souvent, et elles peuvent apporter des surprises : restez vigilant.
  4. Les conteneurs créés dynamiquement dans Kubernetes envoient un grand nombre de métriques avec une durée de vie courte et aléatoire. Il n'y a pas beaucoup de points pour ces métriques, et il n'y a pas de problème d'espace. Toutefois, lors de la construction des requêtes, ClickHouse récupère un énorme volume de ces métriques de la table ‘metrics’. Dans 90 % des cas, les données pour celles-ci sont absentes sur la période (24 heures). La recherche de ces données dans la table ‘data’ prend néanmoins du temps et finit par atteindre un timeout. Pour résoudre ce problème, nous avons commencé à tenir une vue distincte avec des informations sur les métriques rencontrées au cours de la journée. Ainsi, lors de l'élaboration de rapports (graphes) sur les conteneurs créés dynamiquement, nous interrogeons uniquement les métriques qui ont été rencontrées dans la fenêtre spécifiée, et non pas pendant toute la durée, ce qui a accéléré considérablement la création des rapports à leur sujet. Pour la solution décrite ci-dessus, nous avons développé graphite-clickhouse (fork), incluant la mise en œuvre du travail avec la table date_metrics.

Graphite+ClickHouse. Tags

Depuis la version 1.1.0, Graphite a officiellement pris en charge les tags. Et nous réfléchissons activement à ce qu'il faut faire pour soutenir cette initiative dans la pile graphite+clickhouse.

Graphite+ClickHouse. Détecteur d'anomalies

Sur la base de l'infrastructure décrite ci-dessus, nous avons réalisé un prototype de détecteur d'anomalies, et il fonctionne ! Mais nous en parlerons dans le prochain article.

Abonnez-vous, cliquez sur la flèche vers le haut et soyez heureux !

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster