Monitoring as a Service : un système modulaire pour l'architecture des microservices

Aujourd'hui, en plus du code monolithique, notre projet comprend des dizaines de microservices. Chacun d’eux nécessite d’être surveillé. Faire cela à une telle échelle en utilisant des ingénieurs DevOps est problématique. Nous avons développé un système de surveillance qui fonctionne comme un service pour les développeurs. Ils peuvent écrire indépendamment des métriques dans le système de surveillance, les utiliser, créer des tableaux de bord basés sur celles-ci et y joindre des alertes qui seront déclenchées lorsque les valeurs seuils seront atteintes. Pour les ingénieurs DevOps, uniquement l'infrastructure et la documentation.

Cet article est une transcription de mon discours avec notre section au RIT++. De nombreuses personnes nous ont demandé de créer des versions texte des rapports à partir de là. Si vous étiez à la conférence ou avez regardé la vidéo, vous ne trouverez rien de nouveau. Et à tous les autres, bienvenue chez le chat. Je vais vous expliquer comment nous sommes arrivés à un tel système, comment il fonctionne et comment nous prévoyons de le mettre à jour.

Monitoring as a Service : un système modulaire pour l'architecture des microservices

Le passé : schémas et plans

Comment en sommes-nous arrivés au système de surveillance actuel ? Pour répondre à cette question, il faut remonter à 2015. Voilà à quoi cela ressemblait alors :

Monitoring as a Service : un système modulaire pour l'architecture des microservices

Nous avions environ 24 nœuds chargés de la surveillance. Il existe tout un ensemble de couronnes, de scripts et de démons différents qui, d'une manière ou d'une autre, surveillent quelque chose, envoient des messages et exécutent des fonctions. Nous pensions que plus nous avancions, moins un tel système serait viable. Cela ne sert à rien de le développer : c’est trop lourd.
Nous avons décidé de choisir les éléments de suivi que nous conserverons et développerons, et ceux que nous abandonnerons. Il y en avait 19. Il ne restait que les graphites, les agrégateurs et le Grafana comme tableau de bord. Mais à quoi ressemblera le nouveau système ? Comme ça:

Monitoring as a Service : un système modulaire pour l'architecture des microservices

Nous avons un stockage de métriques : ce sont des graphites, qui seront basés sur des disques SSD rapides, ce sont certains agrégateurs de métriques. Suivant - Grafana pour l'affichage des tableaux de bord et Moira pour les alertes. Nous souhaitions également développer un système de recherche d'anomalies.

Norme : Surveillance 2.0

Voilà à quoi ressemblaient les plans en 2015. Mais nous avons dû préparer non seulement l'infrastructure et le service lui-même, mais aussi la documentation correspondante. Nous avons développé pour nous-mêmes une norme d’entreprise que nous appelons monitoring 2.0. Quelles étaient les exigences du système ?

  • disponibilité constante;
  • intervalle de stockage des métriques = 10 secondes ;
  • stockage structuré des métriques et des tableaux de bord ;
  • SLA > 99,99 %
  • collecte de métriques d'événements via UDP (!).

Nous avions besoin d'UDP car nous avons un flux important de trafic et d'événements qui génèrent des métriques. Si vous les écrivez tous en graphite en même temps, le stockage s'effondrera. Nous avons également choisi des préfixes de premier niveau pour toutes les métriques.

Monitoring as a Service : un système modulaire pour l'architecture des microservices

Chacun des préfixes a une propriété. Il existe des métriques pour les serveurs, les réseaux, les conteneurs, les ressources, les applications, etc. Un filtrage clair, strict et typé a été mis en œuvre, dans lequel nous acceptons les métriques de premier niveau et supprimons simplement le reste. C’est ainsi que nous avons planifié ce système en 2015. Qu'y a-t-il dans le présent ?

Présent : schéma d'interaction des composants de surveillance

Tout d'abord, nous surveillons les applications : notre code PHP, nos applications et microservices - bref, tout ce que nos développeurs écrivent. Toutes les applications envoient des métriques via UDP à l'agrégateur Brubeck (statsd, réécrit en C). Il s'est avéré être le plus rapide lors des tests synthétiques. Et il envoie les métriques déjà agrégées à Graphite via TCP.

Il dispose d'un type de métrique appelé minuterie. C'est une chose très pratique. Par exemple, pour chaque connexion utilisateur au service, vous envoyez une métrique avec temps de réponse à Brubeck. Un million de réponses ont été reçues, mais l'agrégateur n'a renvoyé que 10 mesures. Vous avez le nombre de personnes venues, le temps de réponse maximum, minimum et moyen, la médiane et les 4 centiles. Ensuite, les données sont transférées vers Graphite et nous voyons tout cela en direct.

Nous disposons également d'une agrégation de métriques sur le matériel, les logiciels, les métriques du système et notre ancien système de surveillance Munin (cela a fonctionné pour nous jusqu'en 2015). Nous collectons tout cela via le démon C CollectD (il contient tout un tas de plugins différents, il peut interroger toutes les ressources du système hôte sur lequel il est installé, il suffit de préciser dans la configuration où écrire les données) et écrivez les données sur Graphite à travers celui-ci. Il prend également en charge les plugins python et les scripts shell, vous pouvez donc écrire vos propres solutions personnalisées : CollectD collectera ces données à partir d'un hôte local ou distant (en supposant Curl) et les enverra à Graphite.

Ensuite, nous envoyons toutes les métriques que nous avons collectées à Carbon-c-relay. Il s'agit de la solution Carbon Relay de Graphite, modifiée en C. Il s'agit d'un routeur qui collecte toutes les métriques que nous envoyons depuis nos agrégateurs et les achemine vers les nœuds. Également au stade du routage, il vérifie la validité des métriques. Premièrement, ils doivent correspondre au schéma de préfixes que j'ai montré plus tôt et, deuxièmement, ils sont valables pour le graphite. Sinon ils tomberont.

Carbon-c-relay envoie ensuite les métriques au cluster Graphite. Nous utilisons Carbon-cache, réécrit en Go, comme stockage principal des métriques. Go-carbon, en raison de son multithreading, surpasse de loin Carbon-cache. Il reçoit des données et les écrit sur des disques à l'aide du package Whisper (standard, écrit en python). Afin de lire les données de nos stockages, nous utilisons l'API Graphite. Il est beaucoup plus rapide que le Graphite WEB standard. Qu’arrive-t-il ensuite aux données ?

Ils vont à Grafana. Nous utilisons nos clusters de graphite comme principale source de données, et nous avons Grafana comme interface Web pour afficher des métriques et créer des tableaux de bord. Pour chacun de leurs services, les développeurs créent leur propre tableau de bord. Ensuite, ils construisent des graphiques basés sur ceux-ci, qui affichent les métriques qu'ils écrivent à partir de leurs applications. En plus de Grafana, nous avons également SLAM. Il s'agit d'un démon python qui calcule le SLA sur la base des données du graphite. Comme je l'ai déjà dit, nous disposons de plusieurs dizaines de microservices, chacun ayant ses propres exigences. En utilisant SLAM, nous accédons à la documentation, la comparons avec ce qui se trouve dans Graphite et comparons dans quelle mesure les exigences correspondent à la disponibilité de nos services.

Allons plus loin : alerter. Il est organisé à l'aide d'un système solide - Moira. Elle est indépendante car elle possède son propre Graphite sous le capot. Développé par les gars de SKB "Kontur", écrit en python et Go, entièrement open source. Moira reçoit le même flux que celui qui entre dans les graphites. Si, pour une raison quelconque, votre espace de stockage tombe en panne, vos alertes fonctionneront toujours.

Nous avons déployé Moira dans Kubernetes ; il utilise un cluster de serveurs Redis comme base de données principale. Le résultat était un système tolérant aux pannes. Il compare le flux de métriques avec la liste des déclencheurs : s'il ne contient aucune mention, il supprime la métrique. Il est donc capable de digérer des gigaoctets de métriques par minute.

Nous y avons également attaché un LDAP d'entreprise, à l'aide duquel chaque utilisateur du système d'entreprise peut créer lui-même des notifications basées sur des déclencheurs existants (ou nouvellement créés). Étant donné que Moira contient du graphite, il prend en charge toutes ses fonctionnalités. Donc, vous prenez d'abord la ligne et la copiez dans Grafana. Voyez comment les données sont affichées sur les graphiques. Et puis vous prenez la même ligne et la copiez dans Moira. Vous l'accrochez avec des limites et recevez une alerte à la sortie. Pour faire tout cela, vous n’avez besoin d’aucune connaissance particulière. Moira peut alerter via SMS, email, Jira, Slack... Il prend également en charge l'exécution de scripts personnalisés. Lorsqu'un déclencheur lui arrive et qu'elle est abonnée à un script ou un binaire personnalisé, elle l'exécute et envoie JSON à stdin pour ce binaire. En conséquence, votre programme doit l'analyser. Ce que vous ferez avec ce JSON dépend de vous. Si vous le souhaitez, envoyez-le à Telegram, si vous le souhaitez, ouvrez des tâches dans Jira, faites ce que vous voulez.

Nous utilisons également notre propre développement pour les alertes - Imagotag. Nous avons adapté le panneau, habituellement utilisé pour les étiquettes de prix électroniques en magasin, à nos besoins. Nous y avons apporté des déclencheurs de Moira. Il indique dans quel état ils se trouvent et quand ils se sont produits. Certains développeurs ont abandonné les notifications dans Slack et les e-mails au profit de ce panneau.

Monitoring as a Service : un système modulaire pour l'architecture des microservices

Eh bien, puisque nous sommes une entreprise progressiste, nous avons également surveillé Kubernetes dans ce système. Nous l'avons inclus dans le système à l'aide de Heapster, que nous avons installé dans le cluster, il collecte les données et les envoie à Graphite. En conséquence, le schéma ressemble à ceci :

Monitoring as a Service : un système modulaire pour l'architecture des microservices

Composants de surveillance

Voici une liste de liens vers les composants que nous avons utilisés pour cette tâche. Tous sont open source.

Graphite:

Relais carbone-c :

github.com/grobian/carbon-c-relay

Brubeck :

github.com/github/brubeck

Collecté :

collectd.org

Moira :

github.com/moira-alert

Grafana :

grafana.com

Heapster :

github.com/kubernetes/heapster

Statistiques

Et voici quelques chiffres sur la façon dont le système fonctionne pour nous.

Agrégateur (Brubeck)

Nombre de métriques : ~300 000/sec
Intervalle d'envoi des métriques à Graphite : 30 s
Utilisation des ressources du serveur : ~ 6 % CPU (nous parlons de serveurs à part entière) ; ~ 1 Go de RAM ; ~3 Mbit/s de réseau local

Graphite (go-carbone)

Nombre de métriques : ~ 1 600 000/min
Intervalle de mise à jour des métriques : 30 secondes
Schéma de stockage des métriques : 30 sec 35j, 5min 90j, 10min 365j (vous permet de comprendre ce qui arrive au service sur une longue période)
Utilisation des ressources du serveur : ~10 % du processeur ; ~ 20 Go de RAM ; ~30 Mbit/s de réseau local

Flexibilité

Chez Avito, nous apprécions vraiment la flexibilité de notre service de surveillance. Pourquoi est-il devenu ainsi ? Premièrement, ses composants sont interchangeables : aussi bien les composants eux-mêmes que leurs versions. Deuxièmement, la supportabilité. Étant donné que l'ensemble du projet est open source, vous pouvez modifier le code vous-même, apporter des modifications et implémenter des fonctions qui ne sont pas disponibles directement. Des piles assez courantes sont utilisées, principalement Go et Python, cela se fait donc assez simplement.

Voici un exemple d'un problème réel. Une métrique dans Graphite est un fichier. Il a un nom. Nom du fichier = nom de la métrique. Et il existe un moyen d'y arriver. Les noms de fichiers sous Linux sont limités à 255 caractères. Et nous avons (en tant que « clients internes ») des gars du département de base de données. Ils nous disent : « Nous voulons surveiller nos requêtes SQL. Et ce ne sont pas 255 caractères, mais 8 Mo chacun. Nous voulons les afficher dans Grafana, voir les paramètres de cette requête, et mieux encore, nous voulons voir le haut de ces requêtes. Ce serait génial s'il était affiché en temps réel. Ce serait vraiment cool de les mettre en alerte.

Monitoring as a Service : un système modulaire pour l'architecture des microservices
L'exemple de requête SQL est pris comme exemple de site postgrespro.ru

Nous configurons un serveur Redis et utilisons nos plugins Collectd, qui vont vers Postgres et récupèrent toutes les données à partir de là, envoyant des métriques à Graphite. Mais nous remplaçons le nom de la métrique par des hachages. Nous envoyons simultanément le même hachage à Redis sous forme de clé et l'intégralité de la requête SQL sous forme de valeur. Tout ce que nous devons faire est de nous assurer que Grafana peut accéder à Redis et récupérer ces informations. Nous ouvrons l'API Graphite parce que... c'est l'interface principale pour l'interaction de tous les composants de surveillance avec graphite, et nous y entrons une nouvelle fonction appelée aliasByHash() - de Grafana, nous obtenons le nom de la métrique et l'utilisons dans une requête à Redis comme clé, dans réponse, nous obtenons la valeur de la clé, qui est notre « requête SQL » " Ainsi, nous avons affiché dans Grafana un affichage d'une requête SQL, qu'il était en théorie impossible d'y afficher, ainsi que des statistiques sur celle-ci (appels, lignes, total_time, ...).

Les résultats de

Disponibilité Notre service de surveillance est disponible 24h/7 et XNUMXj/XNUMX depuis n'importe quelle application et n'importe quel code. Si vous avez accès aux installations de stockage, vous pouvez écrire des données sur le service. La langue n’a pas d’importance, les décisions ne sont pas importantes. Il vous suffit de savoir comment ouvrir un socket, y mettre une métrique et fermer le socket.

Fiabilité. Tous les composants sont tolérants aux pannes et supportent bien nos charges.

Seuil d'entrée bas. Pour utiliser ce système, vous n'avez pas besoin d'apprendre les langages de programmation et les requêtes dans Grafana. Ouvrez simplement votre application, entrez-y un socket qui enverra des métriques à Graphite, fermez-la, ouvrez Grafana, créez-y des tableaux de bord et examinez le comportement de vos métriques, en recevant des notifications via Moira.

Indépendance. Vous pouvez faire tout cela vous-même, sans l'aide d'ingénieurs DevOps. Et c'est un avantage, car vous pouvez suivre votre projet dès maintenant, vous n'avez besoin de demander à personne - ni de commencer à travailler, ni d'apporter des modifications.

Que visons-nous?

Tout ce qui est énuméré ci-dessous n’est pas seulement des pensées abstraites, mais quelque chose vers lequel au moins les premiers pas ont été faits.

  1. Détecteur d'anomalies. Nous souhaitons créer un service qui accédera à nos stockages Graphite et vérifiera chaque métrique à l'aide de divers algorithmes. Il y a déjà des algorithmes que nous voulons visualiser, il y a des données, nous savons comment les utiliser.
  2. Métadonnées. Nous avons de nombreux services, ils évoluent avec le temps, tout comme les personnes qui travaillent avec eux. Maintenir constamment la documentation manuellement n’est pas une option. C'est pourquoi nous intégrons désormais des métadonnées dans nos microservices. Il indique qui l'a développé, les langues avec lesquelles il interagit, les exigences SLA, où et à qui les notifications doivent être envoyées. Lors du déploiement d'un service, toutes les données d'entité sont créées indépendamment. En conséquence, vous obtenez deux liens : l'un vers les déclencheurs, l'autre vers les tableaux de bord dans Grafana.
  3. Surveillance dans chaque maison. Nous pensons que tous les développeurs devraient utiliser un tel système. Dans ce cas, vous comprenez toujours où se trouve votre trafic, ce qui lui arrive, où il tombe, où se trouvent ses faiblesses. Si, par exemple, quelque chose arrive et fait planter votre service, vous en serez informé non pas lors d'un appel du responsable, mais à partir d'une alerte, et vous pourrez immédiatement ouvrir les derniers journaux et voir ce qui s'y est passé.
  4. Haute performance. Notre projet est en constante croissance et traite aujourd'hui environ 2 000 000 de valeurs métriques par minute. Il y a un an, ce chiffre était de 500 000. Et la croissance se poursuit, ce qui signifie qu'après un certain temps, Graphite (chuchotement) commencera à charger fortement le sous-système de disque. Comme je l'ai déjà dit, ce système de surveillance est assez universel en raison de l'interchangeabilité des composants. Quelqu'un maintient et développe constamment son infrastructure spécifiquement pour Graphite, mais nous avons décidé d'emprunter une voie différente : utiliser Cliquez Maison comme référentiel pour nos métriques. Cette transition est presque terminée, et très prochainement je vous raconterai plus en détail comment cela s'est fait : quelles difficultés il y a eu et comment elles ont été surmontées, comment s'est déroulé le processus de migration, je décrirai les composants choisis comme contraignants et leurs configurations.

Merci pour votre attention! Posez vos questions sur le sujet, j'essaierai d'y répondre ici ou dans les posts suivants. Peut-être que quelqu'un a de l'expérience dans la construction d'un système de surveillance similaire ou dans le passage à Clickhouse dans une situation similaire - partagez-le dans les commentaires.

Source: habr.com

Ajouter un commentaire