Monitoring als Dienst: Modulsystem für mikroservice Architektur

Heute funktionieren in unserem Projekt neben dem monolithischen Code Dutzende von Mikrodiensten. Jeder von ihnen erfordert eine Überwachung. Es ist problematisch, dies in solch einem Umfang von DevOps-Ingenieuren durchführen zu lassen. Wir haben ein Überwachungssystem entwickelt, das als Dienst für Entwickler fungiert. Sie können selbstständig Metriken in das Überwachungssystem schreiben, sie nutzen, Dashboards auf deren Grundlage erstellen und Alarme integrieren, die bei Erreichen von Grenzwerten ausgelöst werden. Von den DevOps-Ingenieuren bleibt nur die Infrastruktur und Dokumentation übrig.

Dieser Beitrag ist eine Transkription meines Vortrags von unserer Sektion auf RIT++. Viele hatten uns gebeten, schriftliche Versionen der Vorträge dort zu machen. Wenn Sie auf der Konferenz waren oder das Video angeschaut haben, werden Sie nichts Neues finden. Allen anderen – herzlich willkommen unter dem Beitrag. Ich werde erzählen, wie wir zu diesem System gekommen sind, wie es funktioniert und wie wir planen, es zu aktualisieren.

Monitoring als Dienst: Modulsystem für mikroservice Architektur

Die Vergangenheit: Schemas und Pläne

Wie sind wir zu dem bestehenden Überwachungssystem gekommen? Um diese Frage zu beantworten, müssen wir ins Jahr 2015 zurückblicken. So sah es damals aus:

Monitoring als Dienst: Modulsystem für mikroservice Architektur

Wir hatten etwa 24 Knoten, die für die Überwachung verantwortlich waren. Es gibt eine ganze Menge verschiedener Cronjobs, Skripte, Daemons, die irgendetwas irgendwo in irgendeiner Weise überwachen, Nachrichten senden und Funktionen ausführen. Wir dachten, dass eine solche Systematik mit der Zeit weniger tragfähig sein wird. Es hat keinen Sinn, sie weiterzuentwickeln: sie ist zu schwerfällig.
Wir haben beschlossen, die Überwachungselemente auszuwählen, die wir behalten und weiterentwickeln wollen, und diejenigen, von denen wir uns trennen. Es waren 19, die übrig blieben. Nur Graphite, Aggregatoren und Grafana als Dashboard blieben übrig. Aber wie wird das neue System aussehen? So:

Monitoring als Dienst: Modulsystem für mikroservice Architektur

Wir haben ein Metrik-Speicher: dies sind Graphite, die auf schnellen SSDs basieren, plus bestimmte Aggregatoren für die Metriken. Außerdem Grafana zur Darstellung der Dashboards und Moira als Alerting-System. Zudem wollten wir ein System zur Erkennung von Anomalien entwickeln.

Standard: Monitoring 2.0

So sah der Plan im Jahr 2015 aus. Wir mussten nicht nur die Infrastruktur und den Dienst selbst vorbereiten, sondern auch die Dokumentation dafür. Wir haben einen Unternehmensstandard entwickelt, den wir Monitoring 2.0 genannt haben. Welche Anforderungen gab es an das System?

  • ständige Verfügbarkeit;
  • Intervall für die Speicherung von Metriken = 10 Sekunden;
  • strukturierte Speicherung von Metriken und Dashboards;
  • SLA > 99,99%
  • Sammlung von Ereignismetriken über UDP (!).

Wir benötigten UDP, da wir einen hohen Verkehrs- und Ereignisfluss haben, der Metriken generiert. Wenn wir alles gleichzeitig in Graphite schreiben würden, würde das Speicheraggregat überlastet. Zudem haben wir erste Stufenpräfixe für alle Metriken gewählt.

Monitoring als Dienst: Modulsystem für mikroservice Architektur

Jeder Präfix hat eine bestimmte Eigenschaft. Es gibt Metriken zu Servern, Netzwerken, Containern, Ressourcen, Anwendungen und so weiter. Es wurde eine klare, strenge, typisierte Filterung implementiert, bei der wir Metriken der ersten Ebene akzeptieren und die anderen einfach fallen lassen. So haben wir dieses System im Jahr 2015 geplant. Wie sieht die Realität heute aus?

Gegenwart: Schema der Interaktion der Überwachungsbestandteile

Zunächst überwachen wir Anwendungen: unseren PHP-Code, Anwendungen und Mikrodienste – kurz, alles, was unsere Entwickler erstellen. Alle Anwendungen senden über UDP Metriken an den Brubeck-Aggregator (statsd, umgeschrieben in C). Er hat sich in synthetischen Tests als der schnellste herausgestellt. Und er sendet bereits aggregierte Metriken über TCP an Graphite.

Er hat eine Art von Metrik, die Timer genannt wird. Das ist eine sehr praktische Sache. Zum Beispiel senden Sie für jede Benutzerverbindung zum Dienst eine Metrik mit der Antwortzeit an Brubeck. Eine Million Antworten sind eingegangen, und der Aggregator hat nur 10 Metriken ausgegeben. Sie haben die Anzahl der eingegangenen Nutzer, die maximale, minimale und durchschnittliche Antwortzeit, die Median und 4 Perzentile. Danach werden die Daten an Graphite weitergegeben und wir sehen sie alle live.

Wir haben auch eine Aggregation für Metriken zu Hardware, Software, Systemmetriken und unser altes Überwachungssystem Munin (das bis 2015 bei uns in Betrieb war). All dies sammeln wir über den C-basierten Daemon CollectD (in ihn sind verschiedene Plugins integriert, er kann alle Ressourcen des Hostsystems abfragen, auf dem er installiert ist, geben Sie einfach in der Konfiguration an, wohin die Daten geschrieben werden sollen) und schreiben die Daten über ihn nach Graphite. Außerdem unterstützt er Python- und Shell-Skripte, sodass Sie Ihre eigenen benutzerdefinierten Lösungen erstellen können: CollectD sammelt diese Daten von einem lokalen oder entfernten Host (nehmen wir an, es gibt Curl) und sendet sie an Graphite.

Alle gesammelten Metriken senden wir dann an Carbon-c-relay. Dies ist die Carbon Relay-Lösung von Graphite, die in C erweitert wurde. Es handelt sich um einen Router, der alle Metriken in sich sammelt, die wir von unseren Aggregatoren senden, und sie an die Knoten weiterleitet. Auch während der Weiterleitung überprüft er die Gültigkeit der Metriken. Erstens müssen sie dem früher gezeigten Schema mit Präfixen entsprechen und zweitens gültig für Graphite sein. Andernfalls werden sie verworfen.

Dann sendet Carbon-c-relay die Metriken an den Graphite-Cluster. Wir verwenden Carbon-cache als primären Metrik-Speicher, das in Go neu geschrieben wurde. Go-carbon übertrifft Carbon-cache aufgrund seiner Multithreading-Fähigkeiten erheblich in der Leistung. Es nimmt die Daten entgegen und schreibt sie mit dem Whisper-Paket (standardmäßig, auf Python geschrieben) auf Platten. Um Daten aus unseren Speichern zu lesen, verwenden wir die Graphite-API. Diese arbeitet wesentlich schneller als das standardmäßige Graphite WEB. Was passiert dann mit den Daten?

Sie gehen zu Grafana. Als Hauptdatenquelle verwenden wir unsere Grafit-Cluster, zusätzlich haben wir Grafana als Web-Interface, um Metriken anzuzeigen und Dashboards zu erstellen. Für jeden Dienst erstellen die Entwickler ihr eigenes Dashboard. Danach erstellen sie Diagramme, auf denen die Metriken angezeigt werden, die sie aus ihren Anwendungen schreiben. Neben Grafana haben wir auch SLAM. Das ist ein Python-Daemon, der SLA auf Basis von Daten aus Grafit berechnet. Wie ich bereits erwähnt habe, haben wir mehrere Dutzend Mikrodienste, von denen jeder seine eigenen Anforderungen hat. Mit SLAM prüfen wir die Dokumentation und vergleichen sie mit dem, was in Graphite vorhanden ist, und stellen fest, inwieweit die Anforderungen mit der Verfügbarkeit unserer Dienste übereinstimmen.

Gehen wir weiter: das Alerting. Es wird durch ein starkes System — Moira — organisiert. Es ist unabhängig, weil es ein eigenes Graphite im Hintergrund hat. Entwickelt von den Jungs aus SKB "Kontur" und in Python und Go geschrieben, ist es vollständig Open Source. Moira erhält den gleichen Datenstrom, der in die Grafiten fließt. Wenn aus irgendeinem Grund Ihr Speicher ausfällt, funktioniert Ihr Alerting weiterhin.

Moira haben wir in Kubernetes bereitgestellt, als Hauptdatenbank nutzt es einen Cluster von Redis-Servern. So entstand ein ausfallsicheres System. Es vergleicht den Datenstrom der Metriken mit der Liste der Trigger: wenn keine Erwähnungen vorhanden sind, wird die Metrik verworfen. Auf diese Weise kann es Gigabytes von Metriken pro Minute verarbeiten.

Wir haben auch die Unternehmens-LDAP angebunden, mit dessen Hilfe jeder Benutzer des Unternehmenssystems Benachrichtigungen zu bestehenden (oder neu erstellten) Triggern erstellen kann. Da Moira Graphite enthält, unterstützt es alle seine Funktionen. Zuerst nehmen Sie die Zeile und kopieren sie nach Grafana. Sehen Sie sich an, wie die Daten in den Grafiken angezeigt werden. Dann nehmen Sie dieselbe Zeile und kopieren sie nach Moira. Sie versehen sie mit Limits und erhalten ein Alerting. Um all dies zu tun, benötigen Sie keine speziellen Kenntnisse. Moira kann per SMS, E-Mail, in Jira, Slack… alarmieren. Außerdem unterstützt es die Ausführung benutzerdefinierter Skripte. Wenn ein Trigger eintritt und es auf ein benutzerdefiniertes Skript oder Binärprogramm abonniert ist, führt es dieses aus und übergibt diesem Binärprogramm JSON über stdin. Ihre Anwendung sollte es entsprechend parsen. Was Sie mit diesem JSON machen, entscheiden Sie selbst. Wenn Sie möchten, schicken Sie es an Telegram, wenn nicht, öffnen Sie Aufgaben in Jira, machen Sie, was Sie wollen.

Für das Alerting verwenden wir auch unsere eigene Entwicklung – Imagotag. Wir haben das Panel, das normalerweise für elektronische Preisschilder in Geschäften verwendet wird, an unsere Bedürfnisse angepasst. Wir haben die Trigger von Moira darauf ausgegeben. Dort wird angezeigt, in welchem Zustand sie sich befinden, wann sie aufgetreten sind. Einige Entwickler haben auf Benachrichtigungen in Slack und E-Mail zugunsten dieses Panels verzichtet.

Monitoring als Dienst: Modulsystem für mikroservice Architektur

Und da wir ein fortschrittliches Unternehmen sind, haben wir auch Kubernetes in dieses System überwacht. Wir haben es über Heapster in das System integriert, das wir im Cluster installiert haben, es sammelt Daten und sendet sie an Graphite. Das Schema sieht folgendermaßen aus:

Monitoring als Dienst: Modulsystem für mikroservice Architektur

Überwachungs-Komponenten

Hier ist eine Liste der Links zu den Komponenten, die wir für diese Aufgabe verwendet haben. Alle sind Open Source.

Graphite:

Carbon-c-relay:

github.com/grobian/carbon-c-relay

Brubeck:

github.com/github/brubeck

Collectd:

collectd.org

Moira:

github.com/moira-alert

Grafana:

grafana.com

Heapster:

github.com/kubernetes/heapster

Statistik

Und hier sind einige Zahlen darüber, wie das System bei uns funktioniert.

Aggregator (brubeck)

Anzahl der Metriken: ~ 300.000 / sec
Intervall zur Übertragung von Metriken an Graphite: 30 sec
Ressourcennutzung des Servers: ~ 6% CPU (bei vollwertigen Servern); ~ 1 Gb RAM; ~ 3 Mbps LAN

Graphite (go-carbon)

Anzahl der Metriken: ~ 1.600.000 / min
Intervall zur Aktualisierung von Metriken: 30 sec
Die Metrik-Speicherstrategie: 30sek 35d, 5min 90d, 10min 365d (gibt Einblick, was mit dem Service über längere Zeiträume passiert)
Serverressourcennutzung: ~ 10% CPU; ~ 20Gb RAM; ~ 30 Mbps LAN

Flexibilität

Bei Avito schätzen wir die Flexibilität unseres Überwachungsdienstes sehr. Warum ist er eigentlich so geworden? Erstens, seine Komponenten sind austauschbar: sowohl die Komponenten selbst als auch ihre Versionen. Zweitens — Wartbarkeit. Da das gesamte Projekt auf Open Source basiert, können Sie den Code selbst anpassen, Änderungen vornehmen und Funktionen implementieren, die nicht standardmäßig verfügbar sind. Es werden gängige Stacks verwendet, hauptsächlich Go und Python, sodass dies relativ einfach möglich ist.

Hier ist ein Beispiel für ein tatsächlich aufgetretenes Problem. Eine Metrik in Graphite ist eine Datei. Sie hat einen Namen. Der Dateiname = Metrikname. Und es gibt einen Pfad zu ihr. Dateinamen in Linux sind auf 255 Zeichen begrenzt. Und wir haben (als „internen Auftraggeber“) Leute aus der Datenbankabteilung. Sie sagen zu uns: „Wir möchten unsere SQL-Abfragen überwachen. Und die sind nicht 255 Zeichen, sondern jeweils 8 MB groß. Wir möchten sie in Grafana anzeigen, die Parameter dieser Abfrage sehen, und noch besser, wir möchten die Spitze solcher Abfragen sehen. Es wäre großartig, wenn das in Echtzeit angezeigt wird. Und es wäre wirklich toll, wenn wir sie in das Alerting integrieren könnten.“

Monitoring als Dienst: Modulsystem für mikroservice Architektur
Beispiel eines SQL-Abfrage aus der Seite postgrespro.ru

Wir starten einen Redis-Server und mit unseren Collectd-Plugins, die in Postgres gehen und dort alle Daten abholen, senden wir die Metriken an Graphite. Aber wir ersetzen den Metriknamen durch Hashes. Und diesen Hash senden wir gleichzeitig als Schlüssel an Redis und die gesamte SQL-Abfrage als Wert. Wir müssen nur sicherstellen, dass Grafana in der Lage ist, auf Redis zuzugreifen und diese Informationen abzurufen. Wir öffnen die Graphite-API, da dies die Hauptschnittstelle für die Interaktion aller Überwachungsbestandteile mit Graphite ist, und fügen eine neue Funktion hinzu, die aliasByHash() heißt — wir erhalten den Metriknamen von Grafana und verwenden ihn als Schlüssel in der Abfrage an Redis, als Antwort erhalten wir den Wert des Schlüssels, der unsere „SQL-Abfrage“ ist. So haben wir die SQL-Abfrage in Grafana angezeigt, die dort eigentlich nicht angezeigt werden konnte, zusammen mit der Statistik darüber (calls, rows, total_time, …).

Ergebnisse

Verfügbarkeit. Unser Monitoring-Service ist 24/7 aus jeder Anwendung und jedem Code verfügbar. Wenn Sie Zugriff auf die Speicher haben, können Sie Daten in den Service schreiben. Die Sprache spielt keine Rolle, die Lösungen sind unwichtig. Sie müssen nur wissen, wie man einen Socket öffnet, eine Metrik hineinwirft und den Socket schließt.

Zuverlässigkeit. Alle Komponenten sind ausfallsicher und bewältigen unsere Lasten gut.

Niedrige Eintrittsbarriere. Um dieses System zu nutzen, müssen Sie keine Programmiersprachen und Abfragen in Grafana lernen. Öffnen Sie einfach Ihre Anwendung, geben Sie den Socket an, der Metriken an Graphite sendet, schließen Sie ihn, öffnen Sie Grafana, erstellen Sie dort Dashboards und sehen Sie sich das Verhalten Ihrer Metriken an, während Sie über Moira Benachrichtigungen erhalten.

Selbstständigkeit. All dies kann selbstständig gemacht werden, ohne die Hilfe von DevOps-Ingenieuren. Und das ist Overkill, denn Sie können Ihr Projekt jetzt sofort überwachen, ohne jemanden um Hilfe bitten zu müssen - weder für den Start noch für Änderungen.

Worauf streben wir zu?

Alles, was unten aufgeführt ist, sind keine bloßen abstrakten Gedanken, sondern die Punkte, zu denen bereits erste Schritte unternommen wurden.

  1. Anomalie-Detektor. Wir möchten einen Service entwickeln, der in unsere Graphite-Speicher geht und jede Metrik anhand verschiedener Algorithmen überprüft. Wir haben bereits Algorithmen, die wir betrachten möchten, und wir haben Daten, mit denen wir arbeiten können.
  2. Metadaten. Wir haben viele Dienste, die sich im Laufe der Zeit ändern, ebenso wie die Personen, die mit ihnen arbeiten. Es ist keine Option, die Dokumentation ständig manuell zu führen. Daher werden jetzt Metadaten in unsere Mikrodienste integriert. Dort steht, wer sie entwickelt hat, welche Sprachen sie verwenden, die SLA-Anforderungen und wohin und an wen Benachrichtigungen gesendet werden sollen. Bei der Bereitstellung des Dienstes werden alle Entitätsdaten automatisch erstellt. Am Ende erhalten Sie zwei Links - einen zu den Triggern, den anderen zu den Dashboards in Grafana.
  3. Monitoring für jedes Zuhause. Wir glauben, dass alle Entwickler ein solches System nutzen sollten. In diesem Fall verstehen Sie immer, wo sich Ihr Traffic befindet, was damit passiert, wo er abbricht und wo seine Schwachstellen liegen. Wenn also beispielsweise etwas kommt und Ihren Service überlastet, erfahren Sie nicht während eines Anrufs vom Manager, sondern über einen Alert und können sofort die neuesten Logs öffnen und sehen, was dort passiert ist.
  4. Hohe Leistung. Unser Projekt wächst kontinuierlich, und heute werden etwa 2.000.000 Metrikwerte pro Minute verarbeitet. Vor einem Jahr lag dieser Wert bei 500.000. Und das Wachstum geht weiter, was bedeutet, dass Graphite (Whisper) bald die Festplattensysteme stark belasten wird. Wie bereits erwähnt, ist dieses Überwachungssystem aufgrund der Austauschbarkeit der Komponenten ziemlich vielseitig. Einige betreuen und erweitern ihre Infrastruktur speziell für Graphite, aber wir haben uns entschieden, einen anderen Weg zu gehen: verwenden ClickHouse es als Speicher für unsere Metriken. Dieser Übergang ist nahezu abgeschlossen, und bald werde ich detaillierter berichten, wie dies umgesetzt wurde: welche Schwierigkeiten auftraten, wie sie überwunden wurden, wie der Migrationsprozess ablief, ich werde die gewählten Komponenten und ihre Konfigurationen beschreiben.

Vielen Dank für Ihre Aufmerksamkeit! Stellen Sie Ihre Fragen zu dem Thema; ich werde versuchen, hier oder in den nächsten Beiträgen zu antworten. Möglicherweise hat jemand Erfahrungen im Aufbau eines ähnlichen Überwachungssystems oder im Übergang zu ClickHouse in einer ähnlichen Situation – teilen Sie diese bitte in den Kommentaren.

Quelle: habr.com

60GB SSD 8Gb DDR4