Tłumaczenie artykułu zostało przygotowane specjalnie dla studentów kursu .
jest programistą, entuzjastą języka Go i miłośnikiem rozwiązywania złożonych problemów. Jest również opiekunem Prometheusa i współzałożycielem instrumentacji Kubernetes SIG. W przeszłości był inżynierem produkcji w SoundCloud i kierował zespołem monitorującym w CoreOS. Obecnie pracuje w Google.
— Inżynier infrastruktury w Improbable. Pasjonat nowych technologii i problemów z systemami rozproszonymi. Ma doświadczenie w programowaniu niskiego poziomu w firmie Intel, doświadczenie jako współpracownik w Mesos i światowej klasy doświadczenie w produkcji SRE w Improbable. Pracuje nad udoskonaleniem świata mikrousług. Jego trzy miłości: Golang, open source i siatkówka.
Patrząc na nasz flagowy produkt SpatialOS, można by się domyślić, że Improbable wymaga wysoce dynamicznej, globalnej infrastruktury chmurowej z dziesiątkami klastrów Kubernetes. Byliśmy jednymi z pierwszych, którzy użyli systemu monitorowania Prometheus jest w stanie monitorować miliony wskaźników w czasie rzeczywistym i oferuje zaawansowany język zapytań pozwalający na wyodrębnienie potrzebnych informacji.
Prostota i niezawodność Prometheusa to jedna z jego głównych zalet. Jednak po przejściu przez pewną skalę napotkaliśmy kilka wad. Aby rozwiązać te problemy, opracowaliśmy — projekt typu open source stworzony przez Improbable w celu płynnej transformacji istniejących klastrów Prometheus w pojedynczy system monitorowania z nieograniczonym magazynem danych historycznych. Thanos jest dostępny na Github .
Nasze cele z Thanosem
W pewnej skali istnieją wyzwania wykraczające poza możliwości zwykłego Prometheusa. Jak możemy przechowywać petabajty danych historycznych niezawodnie i ekonomicznie? Czy możemy to zrobić bez poświęcania czasu odpowiedzi na zapytanie? Czy możemy uzyskać dostęp do wszystkich metryk znajdujących się na różnych serwerach Prometheusa za pomocą jednego żądania API? Czy istnieje sposób na scalenie zreplikowanych danych zebranych za pomocą Prometheusa HA?
Aby rozwiązać te problemy, stworzyliśmy Thanosa. Poniższe sekcje opisują, jak podeszliśmy do tych problemów i wyjaśniają cele, które realizowaliśmy.
Zapytanie o dane z wielu instancji Prometheusa (zapytanie globalne)
Prometheus oferuje funkcjonalne podejście do shardingu. Nawet pojedynczy serwer Prometheus zapewnia wystarczającą skalowalność, aby uwolnić użytkowników od złożoności shardingu poziomego w niemal wszystkich przypadkach użycia.
Chociaż jest to świetny model wdrożenia, często zachodzi potrzeba dostępu do danych na wielu serwerach Prometheus za pośrednictwem jednego interfejsu API lub interfejsu użytkownika — widoku globalnego. Oczywiście możliwe jest wyświetlanie wielu zapytań na jednym pulpicie Grafana, ale każde zapytanie można uruchomić tylko na jednym serwerze Prometheus. Z drugiej strony, dzięki Thanos możesz wyszukiwać i agregować dane z wielu serwerów Prometheus, ponieważ wszystkie są dostępne z jednego punktu końcowego.
Wcześniej, aby uzyskać globalny widok na Improbable, organizowaliśmy nasze wystąpienia Prometheusa w warstwowy Oznaczało to utworzenie jednego metaserwera Prometheus, który zbierałby podzbiór metryk z każdego serwera „liściastego”.

To podejście okazało się problematyczne. Skutkowało bardziej złożoną konfiguracją, dodatkowym potencjalnym punktem awarii i złożonymi regułami, aby zapewnić, że tylko potrzebne dane były dostarczane do federacyjnego punktu końcowego. Ponadto federacja tego rodzaju nie zapewnia prawdziwego globalnego widoku, ponieważ nie wszystkie dane są dostępne z pojedynczego żądania API.
Blisko z tym związany jest ujednolicony widok danych zebranych na serwerach Prometheus o wysokiej dostępności (HA). Model HA Prometheusa zbiera dane dwa razy niezależnie, co jest tak proste, jak to tylko możliwe. Jednak połączony i zdeduplikowany widok obu strumieni byłby znacznie wygodniejszy.
Oczywiście, istnieje potrzeba wysoce dostępnych serwerów Prometheus. W Improbable poważnie traktujemy monitorowanie danych minuta po minucie, ale posiadanie jednej instancji Prometheus na klaster to pojedynczy punkt awarii. Każdy błąd konfiguracji lub awaria sprzętu może potencjalnie doprowadzić do utraty ważnych danych. Nawet proste wdrożenie może prowadzić do niewielkich zakłóceń w zbieraniu metryk, ponieważ ponowne uruchomienia mogą być znacznie dłuższe niż interwał scrapowania.
Niezawodne przechowywanie danych historycznych
Tanie, szybkie i długoterminowe przechowywanie metryk to nasze marzenie (podzielane przez większość użytkowników Prometheusa). W Improbable byliśmy zmuszeni ustawić okres przechowywania metryk na dziewięć dni (dla Prometheusa 1.8). Dodaje to oczywiste ograniczenia co do tego, jak daleko wstecz możemy zajrzeć.
W Prometheusie 2.0 wprowadzono ulepszenia w tym zakresie, ponieważ liczba szeregów czasowych nie wpływa już na ogólną wydajność serwera (patrz ). Jednak Prometheus przechowuje dane na dysku lokalnym. Chociaż wysoce wydajna kompresja danych może znacznie zmniejszyć wykorzystanie lokalnego dysku SSD, istnieje ostatecznie limit ilości danych historycznych, które można przechowywać.
W Improbable dbamy również o niezawodność, prostotę i koszty. Duże dyski lokalne są trudniejsze w obsłudze i tworzeniu kopii zapasowych. Są droższe i wymagają więcej narzędzi do tworzenia kopii zapasowych, co dodaje niepotrzebnej złożoności.
Próbkowanie w dół
Gdy zaczęliśmy pracować z danymi historycznymi, zdaliśmy sobie sprawę, że algorytm Big-O ma podstawowe trudności, które sprawiają, że zapytania są coraz wolniejsze, im dłużej pracujemy na danych obejmujących tygodnie, miesiące i lata.
Standardowym rozwiązaniem tego problemu byłoby (downsampling) — zmniejszenie częstotliwości próbkowania sygnału. Poprzez downsampling możemy „oddalić” obraz do większego zakresu czasu i zachować tę samą liczbę próbek, co sprawi, że zapytania będą responsywne.
Próbkowanie w dół starych danych jest nieuniknionym wymogiem każdego rozwiązania do długoterminowego przechowywania danych i wykracza poza możliwości zwykłego Prometheusa.
Dodatkowe cele
Jednym z początkowych celów projektu Thanos była bezproblemowa integracja z dowolną istniejącą instalacją Prometheus. Drugim celem było ułatwienie obsługi przy minimalnej barierze wejścia. Wszelkie zależności powinny być łatwe do spełnienia zarówno dla małych, jak i dużych użytkowników, co oznacza również niski koszt bazowy.
Architektura Thanosa
Teraz, gdy w poprzedniej sekcji wymieniliśmy nasze cele, przystąpmy do ich realizacji i zobaczmy, jak Thanos rozwiązuje te problemy.
Widok globalny
Aby uzyskać globalny widok istniejących instancji Prometheus, musimy powiązać pojedynczy punkt wejścia zapytania ze wszystkimi serwerami. To właśnie robi komponent Thanos. Jest on wdrażany obok każdego serwera Prometheus i działa jako serwer proxy, udostępniając lokalne dane Prometheus za pośrednictwem interfejsu API sklepu gRPC, umożliwiając pobieranie danych szeregów czasowych według etykiety i zakresu czasu.
Po drugiej stronie znajduje się skalowalny poziomo, bezstanowy komponent Querier, który nie robi nic więcej poza odpowiadaniem na zapytania PromQL za pośrednictwem standardowego interfejsu API HTTP Prometheus. Querier, Sidecar i inne komponenty Thanos komunikują się za pośrednictwem .

- Po otrzymaniu żądania Querier łączy się z odpowiednim serwerem API sklepu, tj. naszymi Sidecarami, i odbiera dane szeregów czasowych z odpowiednich serwerów Prometheus.
- Następnie łączy odpowiedzi i wykonuje na nich zapytanie PromQL. Querier może łączyć zarówno dane rozłączne, jak i zduplikowane dane z serwerów Prometheus HA.
To rozwiązuje główną część naszej zagadki: łączenie danych z odizolowanych serwerów Prometheus w jednym widoku. W rzeczywistości Thanos może być używany tylko do tej funkcji. Nie są wymagane żadne zmiany w istniejących serwerach Prometheus!
Nieograniczony okres przydatności do spożycia!
Jednak prędzej czy później będziemy chcieli przechowywać dane wykraczające poza normalny czas retencji Prometheusa. Do przechowywania danych historycznych wybraliśmy przechowywanie obiektów. Jest ono szeroko dostępne w każdej chmurze, jak również w lokalnych centrach danych i jest bardzo opłacalne. Ponadto, niemal każde przechowywanie obiektów jest dostępne za pośrednictwem dobrze znanego interfejsu API S3.
Prometheus zapisuje dane z pamięci RAM na dysk co około dwie godziny. Trwały blok danych zawiera wszystkie dane dla ustalonego przedziału czasu i jest niezmienny. Jest to bardzo wygodne, ponieważ Thanos Sidecar może po prostu obserwować katalog danych Prometheusa i, gdy pojawią się nowe bloki, ładować je do kontenerów pamięci masowej obiektów.

Ładowanie do pamięci masowej obiektów bezpośrednio po zapisaniu na dysku umożliwia również prostotę „scrapera” (Prometheus i Thanos Sidecar). Upraszcza to wsparcie, koszty i projektowanie systemu.
Jak widać, tworzenie kopii zapasowych danych jest bardzo proste. Ale co z wyszukiwaniem danych w pamięci obiektowej?
Komponent Thanos Store działa jako proxy do pobierania danych z pamięci obiektów. Podobnie jak Thanos Sidecar, uczestniczy w klastrze gossip i implementuje Store API. W ten sposób istniejący Queriers mogą traktować go jako Sidecar, jako kolejne źródło danych szeregów czasowych — nie jest wymagana żadna specjalna konfiguracja.

Bloki danych szeregów czasowych składają się z kilku dużych plików. Ładowanie ich na żądanie byłoby dość nieefektywne, a lokalne buforowanie wymagałoby ogromnej ilości pamięci i miejsca na dysku.
Zamiast tego Store Gateway wie, jak obsługiwać format pamięci masowej Prometheus. Dzięki użyciu inteligentnego planera zapytań i buforowaniu tylko niezbędnych części indeksów bloków możliwe jest zredukowanie złożonych zapytań do minimalnej liczby żądań HTTP do plików pamięci masowej obiektów. Zmniejsza to liczbę żądań o cztery do sześciu rzędów wielkości i osiąga czasy odpowiedzi, które są na ogół trudne do odróżnienia od zapytań do danych na lokalnym dysku SSD.

Jak pokazano na powyższym diagramie, Thanos Querier znacznie zmniejsza koszt pojedynczego zapytania do danych pamięci masowej obiektów, wykorzystując format pamięci masowej Prometheus i przechowując powiązane dane blisko siebie. Korzystając z tego podejścia, możemy połączyć wiele pojedynczych zapytań w minimalną liczbę operacji zbiorczych.
Kompaktowanie i próbkowanie w dół
Po pomyślnym załadowaniu nowego bloku danych szeregów czasowych do pamięci masowej obiektów traktujemy go jako dane „historyczne”, do których natychmiast uzyskujemy dostęp za pośrednictwem Store Gateway.
Jednak po pewnym czasie bloki z jednego źródła (Prometheus z Sidecar) kumulują się i nie wykorzystują już pełnego potencjału indeksowania. Aby rozwiązać ten problem, wprowadziliśmy kolejny komponent o nazwie Compactor. Po prostu stosuje lokalny mechanizm kompresji Prometheusa do danych historycznych w pamięci masowej obiektów i może być uruchamiany jako proste okresowe zadanie wsadowe.

Dzięki wydajnej kompresji, zapytania do pamięci masowej przez długi okres czasu nie stanowią problemu pod względem rozmiaru danych. Jednak potencjalny koszt rozpakowania miliarda wartości i przepuszczenia ich przez procesor zapytań nieuchronnie doprowadzi do gwałtownego wzrostu czasu wykonywania zapytania. Z drugiej strony, ponieważ na ekranie znajdują się setki punktów danych na piksel, staje się niemożliwe nawet zwizualizowanie danych w pełnej rozdzielczości. Tak więc downsampling jest nie tylko możliwy, ale nie spowoduje zauważalnej utraty dokładności.

Aby zmniejszyć próbkowanie danych, Compactor stale agreguje dane w rozdzielczościach pięciominutowej i godzinnej. Dla każdego surowego fragmentu, zakodowanego kompresją TSDB XOR, przechowywane są różne typy danych agregowanych, takie jak min, max lub suma dla jednego fragmentu. Pozwala to Querierowi automatycznie wybrać agregat odpowiedni dla danego zapytania PromQL.
Użytkownik nie musi konfigurować danych o niskiej precyzji. Querier automatycznie przełącza się między różnymi rozdzielczościami i surowymi danymi, gdy użytkownik powiększa i pomniejsza obraz. W razie potrzeby użytkownik może kontrolować to bezpośrednio za pomocą parametru „step” w zapytaniu.
Ponieważ koszt przechowywania jednego GB jest niewielki, Thanos domyślnie przechowuje oryginalne dane, dane o rozdzielczości pięciominutowej i godzinnej. Nie ma potrzeby usuwania oryginalnych danych.
Zasady nagrywania
Nawet w przypadku Thanosa reguły nagrywania są istotną częścią stosu monitorowania. Zmniejszają złożoność, opóźnienia i koszty zapytań. Są również wygodne dla użytkowników, którzy chcą uzyskać zagregowane dane dotyczące metryk. Thanos opiera się na zwykłych instancjach Prometheusa, więc przechowywanie reguł nagrywania i reguł alertów na istniejącym serwerze Prometheusa jest całkowicie dopuszczalne. Jednak w niektórych przypadkach może to nie wystarczyć:
- Globalny alert i reguła (np. alert, gdy usługa nie działa w więcej niż dwóch z trzech klastrów).
- Reguła dotycząca danych znajdujących się poza pamięcią lokalną.
- Chęć przechowywania wszystkich reguł i alertów w jednym miejscu.

We wszystkich tych przypadkach Thanos obejmuje oddzielny komponent o nazwie Ruler, który ocenia reguły i alerty za pośrednictwem Thanos Queries. Poprzez udostępnienie dobrze znanego StoreAPI węzeł Query może uzyskać dostęp do świeżo obliczonych metryk. Są one również później przechowywane w pamięci obiektów i udostępniane za pośrednictwem Store Gateway.
Moc Thanosa
Thanos jest wystarczająco elastyczny, aby dostosować go do swoich potrzeb. Jest to szczególnie przydatne podczas migracji z prostego Prometheusa. Szybko przejrzyjmy to, czego dowiedzieliśmy się o komponentach Thanosa, na małym przykładzie. Oto, jak przenieść swojego zwykłego Prometheusa do świata „nieograniczonej pamięci metryk”:

- Dodaj Thanos Sidecar do swoich serwerów Prometheus — na przykład sąsiedni kontener w podzie Kubernetes.
- Wdróż wiele replik Thanos Querier, aby móc przeglądać dane. W tym momencie łatwo jest skonfigurować plotki między Scraperem i Querierem. Użyj metryki „thanos_cluster_members”, aby zweryfikować interakcje komponentów.
Tylko te dwa kroki wystarczą, aby zapewnić globalną widoczność i bezproblemową deduplikację danych z potencjalnych replik Prometheus HA! Po prostu podłącz swoje pulpity nawigacyjne do punktu końcowego HTTP Querier lub użyj bezpośrednio interfejsu użytkownika Thanos.
Jeśli jednak potrzebujesz kopii zapasowej danych metrycznych i ich długoterminowego przechowywania, konieczne będzie wykonanie trzech dodatkowych kroków:
- Utwórz kontener AWS S3 lub GCS. Skonfiguruj Sidecar, aby kopiować dane do tych kontenerów. Teraz możesz zminimalizować pamięć lokalną.
- Wdróż Store Gateway i połącz go z istniejącym klastrem gossip. Teraz możesz zapytać o dane kopii zapasowej!
- Wdróż Compactor, aby poprawić wydajność zapytań na przestrzeni długich okresów czasu, stosując kompresję i próbkowanie w dół.
Jeśli chcesz dowiedzieć się więcej, zajrzyj na naszą stronę и !
W zaledwie pięciu krokach przekształciliśmy Prometheusa w niezawodny system monitorowania z globalnym widokiem, nieograniczonym przechowywaniem danych i potencjalnie wysoką dostępnością metryk.
Pull request: potrzebujemy Cię!
jest projektem typu open source od samego początku. Bezproblemowa integracja z Prometheus i możliwość korzystania tylko z części Thanos sprawiają, że jest to świetny wybór do skalowania systemu monitorowania bez dodatkowego wysiłku.
Zawsze chętnie przyjmujemy żądania ściągnięcia i problemy z GitHub. W międzyczasie możesz się z nami skontaktować za pośrednictwem Github Issues lub Slack, jeśli masz jakieś pytania lub uwagi, lub chcesz podzielić się swoimi doświadczeniami z korzystania z niego! Jeśli podoba Ci się to, co robimy w Improbable, nie wahaj się z nami skontaktować — !
Źródło: www.habr.com
