Bonjour à tous ! Dans mon 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.

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 ), 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 , 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 (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 (auteur de carbon-clickhouse, graphite-clickhouse et bien d'autres), une version plus ancienne . Les erreurs ont disparu â tout a commencĂ© Ă fonctionner Ă merveille.
Pour lire les donnĂ©es Ă partir de ClickHouse, nous avons choisi (golang). En tant qu'interface API pour Graphite â (golang). Pour organiser la rĂ©plication entre les tables ClickHouse, nous avons utilisĂ© . Pour le routage des mĂ©triques, nous avons gardĂ© notre cher (C) .
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Ă© ). 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Ă© ). 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 Ă 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Ă© ). 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, PrefixGraphite+ClickHouse. Schéma d'interaction des composants

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%;

- 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.
- 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.
- 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" - De nouvelles versions stables de ClickHouse sortent assez souvent, et elles peuvent apporter des surprises : restez vigilant.
- 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Ă© , incluant la mise en Ćuvre du travail avec la table date_metrics.
Graphite+ClickHouse. Tags
Depuis la version 1.1.0, Graphite a officiellement . 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

