Prometheus jako serce nowoczesnego systemu monitoringu

Monitoring Prometheus

Zajmiemy się dziś dość gorącym ostatnio tematem monitoringu rozbudowanych aplikacji z wykorzystaniem Prometheus, Alertmanager oraz Grafana. W kontekście coraz bardziej rozpowszechnionego podejścia DevOps, microservices oraz Kubernetes zdecydowanie już teraz warto zainteresować się tym tematem. Cały materiał ukaże się w formie minicyklu składającego się z trzech części (linki poniżej). Opowiemy sobie najpierw o zmianach, jakie zaszły w architekturze aplikacji i jakie wymusiły nowe podejście do monitoringu. Następnie przyjrzymy się bliżej jednemu z najpopularniejszych darmowych rozwiązań open source do monitoringu aplikacji online – Prometheus. W kolejnych wpisach natomiast omówię sposoby automatyzacji monitoringu, korzystając z alarmów, oraz przyjrzymy się możliwościom wizualizacji metryk w Grafana.

  1. Prometheus jako serce nowoczesnego systemu monitoringu
  2. Automatyzacja monitoringu dzięki alarmom
  3. Wizualizacja metryk w Grafana

Dlaczego w dzisiejszych czasach potrzebujemy dobrego monitoringu?

Jeszcze nie tak dawno większość nawet dużych projektów była realizowana z wykorzystaniem statycznych serwerów, do których można było podłączyć się za pomocą statycznego adresu IP. Odrobinę sytuację skomplikowało wprowadzenie różnego rodzaju maszyn wirtualnych oraz kolejnej warstwy wirtualizacji pod postacią obrazów Docker.

Mimo wszystko taka architektura była cały czas raczej statyczna i dość rzadko zmieniała swoją strukturę. W tak stabilnej konfiguracji sprzętowej był wdrażany również statyczny zbiór aplikacji. Z góry wiedzieliśmy, gdzie nasza aplikacja zostanie zdeployowana oraz co dokładnie znajduje się na którym serwerze.

To wszystko spowodowało, że stosunkowo niewielkim wysiłkiem można było się podłączyć do takiego serwera i zwyczajnie sprawdzić, co na nim się dzieje. Podstawowa znajomość Linuxa, komenda htop, przegląd logów i wiemy już, co dzieje się w naszym systemie.

Skalowanie systemu vs słabe wykorzystanie zasobów

To teraz spróbujmy trochę skomplikować sytuację, w jakiej działa nasz system. Załóżmy, że przy pomocy naszej aplikacji sprzedajemy bilety na różnego rodzaju koncerty. Zazwyczaj ruch jest umiarkowany, jednak od czasu do czasu trafia nam się wielka gwiazda typu Metallica czy Justin Bieber 😉 Ludzie wariują, a wraz z nimi statystyki naszej strony i oczywiście nasze serwery. Przypuśćmy, że ruch w takim okresie jest około 10 razy większy niż przeciętnie, a nawet 20–30 razy większy niż w środku nocy lub w niedzielę rano – czyli w okresie, gdy mało kto decyduje się na zakup biletów.

Jednym ze sposobów poradzenia sobie z takimi problemami jest utrzymywanie cały czas architektury gotowej do obsługi maksymalnego ruchu. O ile w przypadku niewielkiego projektu nie będzie to stanowiło wygórowanej ceny, o tyle w przypadku bardziej popularnych rozwiązań koszt takiej nadmiarowości może być ogromny!

A co gdybyśmy tak byli w stanie dynamicznie dodawać nowe maszyny do naszego klastra? A następnie bez uszczerbku na działaniu aplikacji ze strony naszych klientów przenieść bardziej obciążającą część aplikacji na nowe maszyny? I dodatkowo to wszystko działoby się całkowicie automatycznie, bez naszej ręcznej ingerencji?

Brzmi rewelacyjnie i do tego jest to realne. Z pomocą w podobnych problemach przychodzi nam Kubernetes. Jednak, jak za chwilę się przekonamy, w IT – jak w życiu – rzadko coś jest całkiem za darmo.

Jak Kubernetes zmienił stopnień skomplikowania architektury?

Wykorzystanie Kubernetes w projekcie daje niewątpliwie bardzo dużo dodatkowych korzyści, nie można jednak zapominać również o kosztach. Dodatkowa warstwa abstrakcji drastycznie podnosi poziom skomplikowania architektury systemu. Bardzo dużo rzeczy się zmienia, a wiele innych zwyczajnie podlega dynamizacji. Nawet ilość serwerów w klastrze obsługującym nasz system może się zmienić. Dodatkowo nie możemy założyć, gdzie nasza aplikacja zostanie wdrożona – to również może się zmienić podczas działania systemu. Wystarczy bowiem, że obciążenie na pierwotnym nodzie będzie zbyt duże i część podów z naszą aplikacją zostanie przeniesiona gdzie indziej.

Jest to tylko część problemów, z którymi trzeba się zmierzyć w nowej architekturze. Nie zrozum mnie źle – nie mam zamiaru nikogo zniechęcać do tego rozwiązania. Wręcz przeciwnie – jestem jego ogromnym zwolennikiem. Trzeba jedynie pamiętać, że w IT nie ma idealnych narzędzi, które rozwiążą wszystkie nasze problemy w każdej możliwej sytuacji. Dodatkowo należy pamiętać, że nowe technologie zazwyczaj wprowadzają nowe problemy, do których rozwiązania będziemy potrzebowali nowych narzędzi. Tak samo jest i w tym wypadku – standardowe podejście do monitoringu oraz istniejące narzędzia bardzo słabo sprawdzają się w środowisku skontenerowanym, przez co monitoring z ich wykorzystaniem często jest niewydajny lub nawet praktycznie niemożliwy.

Czy Prometheus warto stosować tylko z Kubernetes?

Zdecydowanie nie tylko. Kubernetes jest świetnym sposobem na skomplikowanie architektury w projekcie, jednak nie jest to jedyny sposób 🙂 Dobrze ogarnięty monitoring przyda się w większości trochę bardziej rozbudowanych projektów. Przygotowując się do tego wpisu, poukładałem trochę swoje aplikacje i przygotowałem monitoring oparty o Prometheus do tego bloga. Mimo iż jego architektura jest stosunkowo prosta, to i tutaj udało mi się skorzystać z wielu dobrodziejstw Prometheus.

Prometheus i WordPress

Nie jest to zbyt popularne połączenie, jednak zdecydowałem się to zrobić głównie z dwóch powodów. Po pierwsze od pewnego czasu już zbierałem się do automatyzacji monitoringu moich projektów, a po drugie chciałem zademonstrować, że monitorować można prawie wszystko – nawet aplikacje, które pierwotnie nie były do tego przystosowane.

Moja wersja monitoringu udostępnia kilka podstawowych metryk, które udało mi się zebrać z poziomu WordPress: ilość użytkowników, stron i postów oraz kilka podstawowych informacji z samego PHP.

Największe trudności, na jakie trafiłem, były związane z tym, że blog działa na współdzielonym hostingu, gdzie są dość mocne ograniczenia na instalowanie nowych rzeczy. Dlatego musiałem zdecydować się na ograniczoną wersję metryk i napisać je ręcznie. Ciężko się jednak temu dziwić, raczej mało kto chce w ten sposób monitorować aplikacje na współdzielonych hostingach.

Architektura systemu monitoringu opartego o Prometheus

Prometheus architektura

Prometheus architektura

Powyższy obrazek przedstawia ogólny schemat nowoczesnego systemu monitoringu opartego o Prometheus. W samym sercu układu znajduje się oczywiście Prometheus, który odpowiedzialny jest za zbieranie, gromadzenie oraz zarządzanie wszystkimi informacjami statystycznymi. Poszczególne metryki mogą być zbierane z różnych systemów, np. z silnika bazy danych, Kubernetes, AWS, Kafka, Docker Engine itp. W celu automatyzacji monitoringu wykorzystywane są alerty, za które odpowiedzialny jest Alertmanager.

Alertmanager to niezależna aplikacja, która dostarczana jest w pakiecie Prometheus. Za jego pomocą można zarządzać wszelkimi automatycznymi zadaniami w monitoringu, np. wyślij maila do zespołu operations w przypadku zwiększonego zużycia pamięci lub w przypadku wykorzystania 90% przestrzeni dyskowej itp. Alertmanager daje również możliwość grupowania podobnych ostrzeżeń, wyciszania ich, przekierowywania do odpowiednich osób oraz powstrzymywania duplikatów.

Pushgateway to również niezależny komponent pozwalający integrować zewnętrzne systemy z Prometheus. Za jego pomocą można dostarczyć metryki.

Jednym ze sposobów na wizualizację metryk zebranych w systemie Prometheus jest wykorzystanie dashboardów w Grafana.

Prometheus – instalacja

Wszystkie niezbędne pliki możemy znaleźć i pobrać ze strony download projektu lub bezpośrednio z github.

Do wyboru mamy wiele sposobów na instalację aplikacji: gotowe prekompilowane pliki (Windows, Linux…), budowanie wszystkiego ręcznie ze źródeł czy – ostatecznie – uruchomienie gotowych obrazów Docker.

Ja zdecydowałem się na rozwiązanie z wykorzystaniem Docker, wcześniej odpowiednio modyfikując plik Dockerfile, dostosowując go do swoich potrzeb.

W podstawowej wersji wystarczy uruchomić powyższą komendę i po chwili Prometheus powinien być dostępny pod adresem: http://localhost:9090/.

Czym jest metryka?

Większość nowoczesnych systemów monitoringu działa w oparciu o metryki. Metrykę możemy rozumieć jako swego rodzaju charakterystykę, która opisuje naszą aplikację, np. czas odpowiedzi, ilość błędów HTTP, czy bardziej biznesowe przypadki, jak ilość założonych kont lub zarejestrowanych użytkowników.

W ogólności możemy mierzyć prawie wszystko w naszych aplikacjach i nawet powinniśmy, jeżeli tylko stanowi to dla nas jakąś przydatną informację.

Wymiana informacji PULL vs PUSH

System monitoringu oparty o Prometheus może zbierać metryki na dwa główne sposoby: model push oraz pull.

  1. Model push.
    W tym scenariuszu nasze aplikacje są aktywne i to one są odpowiedzialne za wysłanie zgromadzonych metryk do Prometheus przez Pushgateway. Taki model najlepiej sprawdza się do gromadzenia informacji, np. z wynikami testów, lub innych cyklicznych zadań, które mogą być wykonywane nieregularnie i przez dłuższy okres.
  2. Model pull.
    W tej sytuacji aplikacja jest bierna i tylko przygotowuje swoje metryki w formie endpointu. Natomiast to Prometheus podejmuje decyzję, kiedy je pobrać. To podejście jest rekomendowane przez twórców aplikacji i powinno być wykorzystywane w większości przypadków.

W naszym systemie możemy oczywiście łączyć oba modele i część aplikacji obsłużyć jednym sposobem, a część – drugim.

Przygotowanie i wystawienie metryk dla Prometheus

Prometheus jest bardzo popularnym rozwiązaniem, co zaowocowało powstaniem bardzo rozbudowanego ekosystemu wokół niego. Dla nas jako programistów chcących skorzystać z tego rozwiązania jest to bardzo dobra wiadomość. W bardzo wielu przypadkach nie będziemy musieli sami przygotowywać eksportów z metrykami z zewnętrznych systemów, ale skorzystamy z gotowych rozwiązań. Listę najpopularniejszych dostępnych bibliotek znajdziemy w dokumentacji exportów, znajdują się tam gotowce, między innymi dla PostgreSQL, AWS, Kafka, JVM, Docker oraz wielu innych.

Własne customowe metryki

Od czasu do czasu nie obejdzie się jednak bez przygotowania własnych metryk, specyficznych dla naszego konkretnego rozwiązania. Możemy napisać je całkowicie ręcznie, np. korzystając z modelu pull, w którym wystawiany jest endpoint z metrykami. Wynikowe metryki to przecież tylko zwykły kawałek tekstu. Warto jednak rozważyć wykorzystanie jednej z bibliotek klientów. Osobiście miałem okazję wykorzystać dwie z nich dla Javy oraz PHP. W obu przypadkach byłem bardzo zadowolony z tego rozwiązania i obeszło się bez większych problemów.

Wbudowane typy metryk w Prometheus

Biblioteki klienckie dla Prometheus oferują nam zazwyczaj cztery główne typy metryk, dzięki którym możemy obsłużyć nasze dane. Jednak Prometheus nie wykorzystuje jeszcze informacji o typie i spłaszcza wszystkie dane do prostych szeregów czasowych (ang. time series).

  1. Counter
    Ten typ odpowiedzialny jest za przechowywanie danych liczbowych, które mogą tylko rosnąć lub – zostać zminimalizowane do zera podczas restartu systemu. Counter może być wykorzystany np. do zbierania informacji o ilości HTTP requestów lub zarejestrowanych błędów itp.
  2. Gauge
    Metryki tego typu również przechowują wartości numeryczne, jednak tym razem mogą one rosnąć lub maleć w czasie, np. ilość zarejestrowanych data source w aplikacji lub obiektów w kolejce.
  3. Histogram
    Z wykorzystaniem histogramów najczęściej monitoruje się metryki, takie jak czas odpowiedzi. Przed rozpoczęciem pomiarów musimy najpierw zdefiniować możliwe przedziały wyników. W przypadku pomiaru czasu odpowiedzi może to być: poniżej jednej sekundy, między 1 sekundą a 2 sekundami, między 2 a 5 i powyżej 5. Następnie zaobserwowaną wartość przypisujemy do pasującego przedziału. W późniejszych obliczeniach posługujemy się już tylko informacją o ilości elementów w poszczególnych przedziałach, a nie konkretnymi wartościami.
  4. Summary
    Typ Summary działa bardzo podobnie do histogramu, jednak jest odrobinę bardziej rozbudowany, np. przechowuje informacje o łącznej ilości obserwacji.

System zadań w Prometheus

Wspomniany wcześniej model pobierania metryk w Prometheus pull wewnętrznie działa z wykorzystaniem zadań. W poszczególnych zadaniach możemy zdefiniować, gdzie Prometheus powinien szukać metryk, jak często, z wykorzystaniem jakiej autoryzacji itp., np. przeszukaj wszystkie pody z Kubernetes z etykietą X o wartości Y lub sprawdź konkretny adres URL itp.

Poszczególne joby dodajemy w pliku konfiguracyjny prometheus.yml.

Zamieszczony przykład co 30 sekund sprawdzi adres http://localhost:9090/metrics  w poszukiwaniu metryk.

Możemy wyróżnić dwie główne kategorie zadań:

  1. Dla zdefiniowanego adresu URL lub stałej listy adresów, jak przykładowy job: job_name: prometheus.
  2. Dynamiczne zadania, w których określamy jedynie warunki, ale jeszcze nie znamy konkretnych adresów serwerów. Przykład poniżej działa z wykorzystaniem Kubernetes i dodaje wszystkie pody z labelką scrape_job == kubernetes-common-pods.

Prometheus – znalezione endpointy (ang. targets)

Zadania w Prometheus są wyjątkowo pomocne nie tylko dlatego, że pozwalają w wygodny sposób gromadzić metryki z wielu różnorodnych miejsc, ale również pozwalają w tym samym czasie w łatwy sposób zweryfikować stan naszego systemu.

Na stronie Status/Targets możemy sprawdzić, jakie endpointy z metrykami zostały odnalezione oraz czy ostatnia synchronizacja przebiegła pomyślnie. W przypadku niepowodzenia zobaczymy stosowny komunikat z przechwyconym błędnym kodem odpowiedzi.

Prometheus targets

Prometheus targets

Prometheus – znajdowanie usług (ang. service discovery)

W przypadku bardziej rozbudowanych definicji zadań przydatna może okazać się strona Status/Service Discovery. Zawiera ona dość szczegółowe informacje, w jaki sposób przebiegało konkretne odnajdowanie endpointu z metrykami, jakie labele były brane pod uwagę przy filtrowaniu, jakie endpointy zostały odrzucone itp.

Prometheus service discovery

Prometheus service discovery

Prometheus – przegląd metryk

Zebrane przez nas metryki możemy podejrzeć, korzystając z widoku Graph w Prometheus.

Prometheus metryki

Prometheus metryki

Pojedyncza metryka składa się z unikatowej nazwy, zbioru etykiet oraz przechowywanej wartości:

  • nazwa – powinna być unikatowa oraz zawierać wymowny prefix, który niejako zastępuje przestrzeń nazw (ang. namespace), w celu rozróżnienia różnych metryk.
  • etykiety – dopiero nazwa i unikatowy zbiór wartości etykiet określa konkretną metrykę. Dzięki etykietom można filtrować poszczególne wartości, grupować je, sumować itp.
  • wartość – liczba, którą widzimy w przykładzie, to najnowsza zaobserwowana wartość dla danej metryki, jednak Prometheus przechowuje wartość metryk jako pary wartości oraz czasu obserwacji. Jest to dużo lepiej widoczne, gdy na końcu metryki dodamy   [1h]  wymuszający pobranie wszystkich wartości z ostatniej godziny lub przejdziemy do zakładki Graph.
Prometheus metryki czas

Prometheus metryki czas

Prometheus pozwala nam również na wywołanie różnorodnych funkcji na przechowywanych metrykach, takich jak: abs (wartość absolutna), ceil (zaokrąglenie do góry), sort (sortowanie) oraz wielu innych. Więcej przykładów można znaleźć w dokumentacji na temat funkcji.

Prometheus, czy to wszystko?

Opowiedzieliśmy sobie dzisiaj o bardzo wielu rzeczach: jakie zmiany w architekturze systemów spowodowało wykorzystanie Kubernetes, jak zaprojektować i wdrożyć nowoczesny system monitoringu oraz – ostatecznie – jak skonfigurować i korzystać z Prometheus. Uzbrojony w taką wiedzę z pewnością możesz zacząć eksperymenty z własnym monitoringiem swoich mikrousług.

Nie ma jednak wątpliwości, że nie wyczerpaliśmy jeszcze całego tematu, dlatego w kolejnych tekstach postaram się przybliżyć temat automatyzacji monitoringu z wykorzystaniem alertów oraz wizualizacji metryk w Grafana.

PS. W strefie znajdziecie też slajdy z prezentacji, którą miałem niedawno okazję przeprowadzić właśnie na ten temat.

Programista – Pytania rekrutacyjne

Lista pytań rekrutacyjnych, które pozwolą przygotować Ci się na rozmowę kwalifikacyjną.

No comments
Share:

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *