Monitoring jako usługa: modułowy system w architekturze mikroserwisowej

Dziś oprócz kodu monolitycznego nasz projekt zawiera kilkadziesiąt mikroserwisów. Każdy z nich wymaga monitorowania. Robienie tego na taką skalę przy pomocy inżynierów DevOps jest problematyczne. Opracowaliśmy system monitorowania, który działa jako usługa dla programistów. Potrafią samodzielnie zapisywać metryki do systemu monitorowania, wykorzystywać je, budować na ich podstawie dashboardy i dołączać do nich alerty, które będą uruchamiane po osiągnięciu wartości progowych. Dla inżynierów DevOps tylko infrastruktura i dokumentacja.

Ten post jest zapisem mojej wypowiedzi z naszymi sekcje w RIT++. Wiele osób prosiło nas o wykonanie wersji tekstowych raportów stamtąd. Jeśli byłeś na konferencji lub oglądałeś wideo, nie dowiesz się niczego nowego. I wszyscy inni - witajcie w kocie. Opowiem jak doszliśmy do takiego systemu, jak działa i jak planujemy go aktualizować.

Monitoring jako usługa: modułowy system w architekturze mikroserwisowej

Przeszłość: schematy i plany

Jak dotarliśmy do obecnego systemu monitorowania? Aby odpowiedzieć na to pytanie należy cofnąć się do roku 2015. Tak to wtedy wyglądało:

Monitoring jako usługa: modułowy system w architekturze mikroserwisowej

Za monitorowanie odpowiadało około 24 węzłów. Istnieje cała paczka różnych koron, skryptów, demonów, które w jakiś sposób coś monitorują, wysyłają wiadomości i wykonują funkcje. Uważaliśmy, że im dalej zajdziemy, tym mniej opłacalny będzie taki system. Nie ma sensu tego rozwijać: jest to zbyt kłopotliwe.
Zdecydowaliśmy się wybrać te elementy monitorowania, które będziemy utrzymywać i rozwijać, oraz te, z których porzucimy. Było ich 19. Pozostały jedynie grafity, agregatory i Grafana jako dashboard. Ale jak będzie wyglądał nowy system? Lubię to:

Monitoring jako usługa: modułowy system w architekturze mikroserwisowej

Mamy magazyn metryk: są to grafity, które będą oparte na szybkich dyskach SSD, to pewne agregatory metryk. Dalej - Grafana do wyświetlania dashboardów i Moira do alertów. Chcieliśmy także opracować system wyszukiwania anomalii.

Standard: Monitoring 2.0

Tak wyglądały plany w 2015 roku. Musieliśmy jednak przygotować nie tylko infrastrukturę i samą usługę, ale także dokumentację do niej. Wypracowaliśmy dla siebie korporacyjny standard, który nazywamy monitoringiem 2.0. Jakie były wymagania wobec systemu?

  • stała dostępność;
  • interwał przechowywania metryk = 10 sekund;
  • zorganizowane przechowywanie metryk i dashboardów;
  • Umowa SLA > 99,99%
  • zbieranie metryk zdarzeń poprzez UDP (!).

Potrzebowaliśmy protokołu UDP, ponieważ mamy duży przepływ ruchu i zdarzeń generujących metryki. Jeśli zapiszesz je wszystkie na raz na graficie, pamięć się zawali. Wybraliśmy także przedrostki pierwszego poziomu dla wszystkich metryk.

Monitoring jako usługa: modułowy system w architekturze mikroserwisowej

Każdy z przedrostków ma jakąś właściwość. Istnieją metryki dotyczące serwerów, sieci, kontenerów, zasobów, aplikacji i tak dalej. Zaimplementowano jasne, ścisłe filtrowanie oparte na typach, w którym akceptujemy metryki pierwszego poziomu, a resztę po prostu odrzucamy. Tak planowaliśmy ten system w 2015 roku. Co jest w teraźniejszości?

Prezentacja: schemat współdziałania elementów monitoringu

Przede wszystkim monitorujemy aplikacje: nasz kod PHP, aplikacje i mikroserwisy - w skrócie wszystko, co piszą nasi programiści. Wszystkie aplikacje wysyłają metryki poprzez UDP do agregatora Brubecka (statsd, przepisane w C). W testach syntetycznych okazała się najszybsza. Wysyła już zagregowane metryki do Graphite za pośrednictwem protokołu TCP.

Zawiera rodzaj wskaźników zwanych licznikami czasu. Jest to bardzo wygodna rzecz. Na przykład dla każdego połączenia użytkownika z usługą wysyłasz do Brubecka metrykę z czasem odpowiedzi. Otrzymano milion odpowiedzi, ale agregator zwrócił tylko 10 wskaźników. Masz liczbę osób, które przyszły, maksymalny, minimalny i średni czas reakcji, medianę i 4 percentyle. Następnie dane przesyłane są do Graphite i widzimy to wszystko na żywo.

Mamy również agregację metryk dotyczących sprzętu, oprogramowania, metryk systemowych i naszego starego systemu monitorowania Munin (działał dla nas do 2015 roku). Zbieramy to wszystko za pośrednictwem demona C CollectD (ma wbudowaną całą masę różnych wtyczek, potrafi odpytywać wszystkie zasoby systemu hosta, na którym jest zainstalowany, wystarczy określić w konfiguracji, gdzie zapisać dane) i zapisz przez niego dane do Graphite. Obsługuje także wtyczki Pythona i skrypty powłoki, dzięki czemu możesz pisać własne, niestandardowe rozwiązania: CollectD zbierze te dane z lokalnego lub zdalnego hosta (zakładając, że Curl) i wyśle ​​je do Graphite.

Następnie wysyłamy wszystkie zebrane dane do przekaźnika Carbon-c. To rozwiązanie Carbon Relay firmy Graphite, zmodyfikowane w C. Jest to router, który zbiera wszystkie metryki, które wysyłamy z naszych agregatorów i kieruje je do węzłów. Również na etapie routingu sprawdza ważność metryk. Po pierwsze muszą odpowiadać schematowi przedrostków, który pokazałem wcześniej, a po drugie obowiązują dla grafitu. Inaczej spadną.

Następnie przekaźnik Carbon-c wysyła dane do klastra grafitowego. Używamy pamięci podręcznej Carbon, przepisanej w Go, jako głównego magazynu metryk. Go-carbon, ze względu na swoją wielowątkowość, znacznie przewyższa pamięć podręczną Carbon. Odbiera dane i zapisuje je na dyski za pomocą pakietu szeptanego (standardowego, napisanego w Pythonie). W celu odczytania danych z naszych magazynów wykorzystujemy Graphite API. Jest znacznie szybszy niż standardowy Graphite WEB. Co dalej dzieje się z danymi?

Jadą do Grafany. Używamy naszych klastrów grafitowych jako głównego źródła danych, a ponadto mamy Grafanę jako interfejs sieciowy do wyświetlania metryk i tworzenia dashboardów. Dla każdej ze swoich usług programiści tworzą własny pulpit nawigacyjny. Następnie na ich podstawie budują wykresy, które przedstawiają metryki, które zapisują ze swoich aplikacji. Oprócz Grafany mamy też SLAM. To demon Pythona, który oblicza SLA na podstawie danych z grafitu. Jak już mówiłem, mamy kilkadziesiąt mikroserwisów, z których każdy ma swoje wymagania. Korzystając z SLAM, przechodzimy do dokumentacji i porównujemy ją z tym, co jest w Graphite i porównujemy, jak wymagania odpowiadają dostępności naszych usług.

Pójdźmy dalej: alarmowanie. Zorganizowany jest w oparciu o mocny system – Moira. Jest niezależny, bo ma pod maską własny Grafit. Opracowany przez chłopaków z SKB „Kontur”, napisany w Pythonie i Go, całkowicie open source. Moira otrzymuje ten sam przepływ, który trafia do grafitu. Jeśli z jakiegoś powodu pamięć zostanie wyczerpana, alerty będą nadal działać.

Wdrożyliśmy Moirę w Kubernetesie, która jako główną bazę danych wykorzystuje klaster serwerów Redis. W rezultacie powstał system odporny na awarie. Porównuje strumień metryk z listą wyzwalaczy: jeśli nie ma w nim wzmianek, to usuwa metrykę. Dzięki temu jest w stanie przetrawić gigabajty danych na minutę.

Dołączyliśmy do niego również korporacyjny LDAP, za pomocą którego każdy użytkownik korporacyjnego systemu może tworzyć dla siebie powiadomienia na podstawie istniejących (lub nowo utworzonych) wyzwalaczy. Ponieważ Moira zawiera grafit, obsługuje wszystkie jego funkcje. Więc najpierw bierzesz linię i kopiujesz ją do Grafany. Zobacz, jak dane prezentują się na wykresach. A potem bierzesz tę samą linię i kopiujesz ją do Moiry. Zawieszasz go z limitami i otrzymujesz alert na wyjściu. Aby to wszystko zrobić, nie potrzebujesz żadnej specjalistycznej wiedzy. Moira może ostrzegać za pomocą wiadomości SMS, e-mail, Jira, Slack... Obsługuje również wykonywanie niestandardowych skryptów. Gdy przydarzy się jej wyzwalacz i subskrybuje niestandardowy skrypt lub plik binarny, uruchamia go i wysyła JSON na standardowe wejście dla tego pliku binarnego. W związku z tym Twój program musi go przeanalizować. To, co zrobisz z tym JSONem, zależy od Ciebie. Jeśli chcesz, wyślij to na Telegram, jeśli chcesz, otwórz zadania w Jira, rób co chcesz.

Do alertów wykorzystujemy także własne opracowanie - Imagotag. Do naszych potrzeb dostosowaliśmy panel, który najczęściej stosowany jest w elektronicznych metkach z cenami w sklepach. Sprowadziliśmy do niego wyzwalacze od Moiry. Wskazuje, w jakim stanie się znajdują i kiedy wystąpiły. Niektórzy programiści porzucili powiadomienia na Slacku i e-mailach na rzecz tego panelu.

Monitoring jako usługa: modułowy system w architekturze mikroserwisowej

Cóż, ponieważ jesteśmy firmą postępową, monitorowaliśmy także Kubernetesa w tym systemie. Włączyliśmy go do systemu za pomocą Heapstera, który zainstalowaliśmy w klastrze, zbiera on dane i przesyła je do Graphite. W rezultacie schemat wygląda następująco:

Monitoring jako usługa: modułowy system w architekturze mikroserwisowej

Komponenty monitorujące

Poniżej znajduje się lista linków do komponentów, których użyliśmy do tego zadania. Wszystkie są open source.

Grafit:

Przekaźnik węglowy-c:

github.com/grobian/carbon-c-relay

Brubecka:

github.com/github/brubeck

Zebrane:

Collectd.org

Mojra:

github.com/moira-alert

Grafana:

grafana.com

Sterta:

github.com/kubernetes/heapster

Statystyki

A oto kilka liczb pokazujących, jak system działa w naszym przypadku.

Agregator (brubeck)

Liczba metryk: ~300 000/sek
Interwał wysyłania metryk do Graphite: 30 sek
Zużycie zasobów serwera: ~ 6% procesora (mówimy o pełnoprawnych serwerach); ~ 1 GB RAM; Sieć LAN ~3 Mb/s

Grafit (go-węglowy)

Ilość metryk: ~ 1 600 000/min
Interwał aktualizacji metryk: 30 sek
Schemat przechowywania metryk: 30 sekund 35 dni, 5 minut 90 dni, 10 minut 365 dni (pozwala zrozumieć, co dzieje się z usługą przez długi okres czasu)
Użycie zasobów serwera: ~10% procesora; ~ 20 GB RAM; Sieć LAN ~30 Mb/s

Гибкость

W Avito naprawdę cenimy elastyczność w naszej usłudze monitorowania. Dlaczego właściwie tak się zachował? Po pierwsze, jego komponenty są wymienne: zarówno same komponenty, jak i ich wersje. Po drugie, wsparcie. Ponieważ cały projekt jest open source, możesz samodzielnie edytować kod, wprowadzać zmiany i implementować funkcje, które nie są dostępne od razu po wyjęciu z pudełka. Używane są dość popularne stosy, głównie Go i Python, więc robi się to po prostu.

Oto przykład prawdziwego problemu. Metryka w Graphite jest plikiem. To ma swoją nazwę. Nazwa pliku = nazwa metryki. I jest sposób, żeby się tam dostać. Nazwy plików w systemie Linux są ograniczone do 255 znaków. Mamy też pracowników (jako „klientów wewnętrznych”) z działu baz danych. Mówią nam: „Chcemy monitorować nasze zapytania SQL. I nie mają one 255 znaków, ale 8 MB każdy. Chcemy je wyświetlić w Grafanie, zobaczyć parametry tego żądania, a jeszcze lepiej, chcemy zobaczyć górę takich żądań. Będzie świetnie, jeśli będzie wyświetlany w czasie rzeczywistym. Byłoby naprawdę fajnie, gdyby ich zaalarmowano”.

Monitoring jako usługa: modułowy system w architekturze mikroserwisowej
Przykładowe zapytanie SQL zostało wzięte jako przykład z strona postgrespro.ru

Konfigurujemy serwer Redis i korzystamy z naszych wtyczek Collectd, które trafiają do Postgres i pobierają stamtąd wszystkie dane, wysyłając metryki do Graphite. Ale zastępujemy nazwę metryki skrótami. Jednocześnie wysyłamy ten sam hash do Redis jako klucz, a całe zapytanie SQL jako wartość. Jedyne, co musimy zrobić, to upewnić się, że Grafana będzie mogła udać się do Redis i zabrać tę informację. Otwieramy Graphite API, ponieważ... jest to główny interfejs interakcji wszystkich komponentów monitorujących z grafitem i tam wprowadzamy nową funkcję o nazwie aliasByHash() - z Grafany pobieramy nazwę metryki i wykorzystujemy ją w żądaniu do Redis jako klucz, w odpowiedzi otrzymujemy wartość klucza, czyli nasze „zapytanie SQL”” Tym samym pokazaliśmy w Grafanie wyświetlacz zapytania SQL, którego teoretycznie nie dało się tam wyświetlić, wraz ze statystykami na jego temat (wywołania, wiersze, całkowity_czas, ...).

Wyniki

Dostępność. Nasza usługa monitorowania jest dostępna 24 godziny na dobę, 7 dni w tygodniu z dowolnej aplikacji i dowolnego kodu. Jeśli masz dostęp do magazynów, możesz zapisywać dane do usługi. Język nie jest ważny, decyzje nie są ważne. Wystarczy wiedzieć jak otworzyć gniazdo, umieścić tam metrykę i zamknąć gniazdo.

Niezawodność. Wszystkie komponenty są odporne na awarie i dobrze radzą sobie z naszymi obciążeniami.

Niski próg wejścia. Aby korzystać z tego systemu nie musisz uczyć się języków programowania i zapytań w Grafanie. Wystarczy otworzyć swoją aplikację, wprowadzić do niej gniazdo, które będzie wysyłać metryki do Graphite, zamknąć ją, otworzyć Grafanę, utworzyć tam dashboardy i przyjrzeć się zachowaniu Twoich metryk, otrzymując powiadomienia poprzez Moirę.

Niezależność. Wszystko to możesz zrobić samodzielnie, bez pomocy inżynierów DevOps. I to jest zaleta, bo możesz od razu monitorować swój projekt, nie musisz nikogo prosić – ani o rozpoczęcie pracy, ani o wprowadzenie zmian.

Do czego dążymy?

Wszystko, co jest wymienione poniżej, to nie tylko abstrakcyjne myśli, ale coś, ku czemu poczyniono przynajmniej pierwsze kroki.

  1. Detektor anomalii. Chcemy stworzyć usługę, która trafi do naszych magazynów Graphite i sprawdzi każdą metrykę za pomocą różnych algorytmów. Istnieją już algorytmy, które chcemy przejrzeć, są dane, wiemy, jak z nimi pracować.
  2. Metadane. Mamy wiele usług, zmieniają się one z biegiem czasu, podobnie jak ludzie, którzy z nimi współpracują. Ciągłe ręczne utrzymywanie dokumentacji nie wchodzi w grę. Dlatego teraz osadzamy metadane w naszych mikrousługach. Podaje, kto go opracował, w jakich językach współpracuje, wymagania SLA, gdzie i do kogo należy wysyłać powiadomienia. Podczas wdrażania usługi wszystkie dane jednostki są tworzone niezależnie. W rezultacie otrzymujesz dwa linki - jeden do wyzwalaczy, drugi do dashboardów w Grafanie.
  3. Monitoring w każdym domu. Uważamy, że wszyscy programiści powinni korzystać z takiego systemu. W takim przypadku zawsze wiesz, gdzie znajduje się Twój ruch, co się z nim dzieje, gdzie spada, gdzie są jego słabe strony. Jeśli np. coś przyjdzie i zawiesi Twoją usługę, to dowiesz się o tym nie podczas rozmowy telefonicznej od menadżera, ale z alertu i będziesz mógł od razu otworzyć najnowsze logi i zobaczyć, co się tam wydarzyło.
  4. Wysoka wydajność. Nasz projekt stale się rozwija i dziś przetwarza około 2 000 000 wartości metrycznych na minutę. Rok temu liczba ta wynosiła 500 000. I wzrost trwa, a to oznacza, że ​​po pewnym czasie Graphite (szept) zacznie mocno obciążać podsystem dyskowy. Jak już mówiłem, ten system monitorowania jest dość uniwersalny ze względu na wymienność komponentów. Ktoś utrzymuje i stale rozwija swoją infrastrukturę specjalnie dla Graphite, ale my zdecydowaliśmy się pójść inną drogą: używać Kliknij Dom jako repozytorium naszych metryk. To przejście jest prawie ukończone i już wkrótce opowiem bardziej szczegółowo, jak tego dokonano: jakie były trudności i jak je przezwyciężono, jak przebiegł proces migracji, opiszę komponenty wybrane jako wiążące i ich konfiguracje.

Dziękuję za uwagę! Zadawajcie pytania w temacie, postaram się odpowiedzieć tutaj lub w kolejnych postach. Być może ktoś ma doświadczenie w budowie podobnego systemu monitorowania lub przejściu na Clickhouse w podobnej sytuacji – podziel się nim w komentarzach.

Źródło: www.habr.com

Dodaj komentarz