Tłumaczenie artykułu przygotowano specjalnie dla studentów kursu .
jest programistą, entuzjastą Go i miłośnikiem rozwiązywania skomplikowanych problemów. Jest również konserwatorem Prometheus i współzałożycielem Kubernetes SIG instrumentation. W przeszłości był inżynierem produkcji w SoundCloud i kierował zespołem monitorowania w CoreOS. Obecnie pracuje w Google.
jest inżynierem infrastruktury w Improbable. Interesuje się nowymi technologiami i problemami systemów rozproszonych. Ma doświadczenie w programowaniu niskopoziomowym w Intel, doświadczenie w roli kontrybutora w Mesos oraz globalne doświadczenie SRE w Improbable. Pracuje nad poprawą świata mikroserwisów. Jego trzy pasje to: Golang, open source i siatkówka.
Patrząc na nasz flagowy produkt SpatialOS, można się domyślić, że Improbable potrzebuje wysokowydajnej, globalnej infrastruktury chmurowej z dziesiątkami klastrów Kubernetes. Byliśmy jednymi z pierwszych, którzy zaczęli korzystać z systemu monitorowania . Prometheus jest w stanie śledzić miliony metryk w czasie rzeczywistym i dostarczany jest z potężnym językiem zapytań, umożliwiającym wydobycie potrzebnych informacji.
Prostota i niezawodność Prometheus jest jednym z jego głównych atutów. Jednak po osiągnięciu określonego rozmiaru napotkaliśmy kilka niedociągnięć. Aby rozwiązać te problemy, opracowaliśmy projekt open source stworzony przez firmę Improbable, mający na celu bezproblemową transformację istniejących klastrów Prometheus w jedną, zintegrowaną system monitorowania z nieograniczonym przechowywaniem danych historycznych. Thanos jest dostępny na Github .
Nasze cele z Thanos
W miarę rozwoju pojawiają się problemy wykraczające poza możliwości standardowego Prometheus. Jak pewnie i ekononomicznie przechowywać petabajty danych historycznych? Czy można to zrobić bez uszczerbku dla czasu odpowiedzi na zapytania? Czy można uzyskać dostęp do wszystkich metryk znajdujących się na różnych serwerach Prometheus za pomocą jednego zapytania API? Czy można jakoś połączyć zreplikowane dane zebrane przy użyciu Prometheus HA?
Aby odpowiedzieć na te pytania, stworzyliśmy Thanos. W kolejnych sekcjach opisujemy, jak podeszliśmy do rozwiązywania tych problemów oraz wyjaśniamy cele, które mieliśmy na myśli.
Zgłaszanie danych z kilku instancji Prometheus (globalne zapytanie)
Prometheus oferuje funkcjonalne podejście do shardingu. Nawet jeden serwer Prometheus zapewnia wystarczającą skalowalność, aby uwolnić użytkowników od złożoności poziomego shardingu w praktycznie wszystkich zastosowaniach.
Chociaż to doskonały model wdrożenia, często konieczny jest dostęp do danych z różnych serwerów Prometheus za pośrednictwem jednego API lub UI — globalny widok. Oczywiście istnieje możliwość przedstawienia wielu zapytań w jednym panelu Grafana, ale każde zapytanie może być wykonane tylko na jednym serwerze Prometheus. Z drugiej strony, używając Thanos, możesz zapytywać i agregować dane z kilku serwerów Prometheus, ponieważ wszystkie są dostępne z jednego punktu końcowego.
Wcześniej, aby uzyskać globalny widok w Improbable, zorganizowaliśmy nasze instancje Prometheus w wielopoziomową . Oznaczało to stworzenie jednego meta-serwera Prometheus, który zbiera część metryk z każdego "liściastego" serwera.

To podejście okazało się problematyczne. Doprowadziło do skomplikowania konfiguracji, dodania dodatkowego potencjalnego punktu awarii oraz zastosowania skomplikowanych zasad do udostępnienia federacyjnego punktu końcowego tylko potrzebnych danych. Ponadto, federacja tego rodzaju nie pozwala na uzyskanie rzeczywistego globalnego widoku, ponieważ nie wszystkie dane są dostępne z jednego zapytania API.
Niezwykle związane z tym jest jednolite przedstawienie danych, zbieranych na wysoko dostępnych (high-availability, HA) serwerach Prometheus. Model HA Prometheus zbiera dane niezależnie dwukrotnie, co jest na tyle proste, że prostsze być nie może. Jednakże korzystanie ze zintegrowanego i deduplikowanego widoku obu strumieni byłoby znacznie wygodniejsze.
Oczywiście, w wysoko dostępnych serwerach Prometheus istnieje potrzeba. W Improbable poważnie traktujemy monitorowanie danych w czasie rzeczywistym, ale posiadanie jednego egzemplarza Prometheus w klastrze jest jedynym punktem awarii. Każdy błąd konfiguracji lub awaria sprzętu mogą potencjalnie prowadzić do utraty ważnych danych. Nawet proste wdrożenie może prowadzić do małych problemów w zbieraniu metryk, ponieważ ponowne uruchomienie może zająć znacznie więcej czasu niż interwał skanowania.
Niezawodne przechowywanie danych historycznych
Tanie, szybkie i długoterminowe przechowywanie metryk to nasz wspólny cel (dzielony przez większość użytkowników Prometheus). W Improbable musieliśmy ustawić czas przechowywania metryk na dziewięć dni (dla Prometheus 1.8). To wprowadza oczywiste ograniczenia w zakresie tego, jak daleko możemy spojrzeć wstecz.
Prometheus 2.0 w tym zakresie stał się lepszy, ponieważ liczba serii czasowych nie wpływa już na ogólną wydajność serwera (zob. ). Niemniej jednak Prometheus przechowuje dane na lokalnym dysku. Chociaż wysokoefektywne kompresowanie danych może znacznie zmniejszyć zużycie lokalnego SSD, ostatecznie wciąż istnieje ograniczenie na ilość przechowywanych danych historycznych.
Ponadto, w Improbable dbamy o niezawodność, prostotę i koszt. Duże lokalne dyski są trudniejsze w eksploatacji i tworzeniu kopii zapasowych. Są droższe i wymagają więcej narzędzi do tworzenia kopii zapasowych, co prowadzi do zbędnej złożoności.
Próbkowanie w dół
Gdy zaczęliśmy pracować z danymi historycznymi, zrozumieliśmy, że istnieją fundamentalne trudności związane z O-wielkością, które sprawiają, że zapytania stają się coraz wolniejsze, jeśli pracujemy z danymi z tygodni, miesięcy i lat.
Standardowym rozwiązaniem tego problemu będzie — zmniejszanie częstotliwości próbkowania sygnału. Dzięki obniżeniu próbkowania możemy "zmniejszyć skalę" do większego zakresu czasowego i zachować taką samą liczbę próbek, co pozwoli na utrzymanie responsywności zapytań.
Próbkowanie w dół starych danych jest nieuniknionym wymaganiem każdego rozwiązania do długoterminowego przechowywania i wykracza poza standardowy Prometheus.
Dodatkowe cele
Jednym z początkowych celów projektu Thanos była bezproblemowa integracja z dowolnymi istniejącymi instalacjami Prometheus. Drugim celem była łatwa eksploatacja z minimalną barierą wejścia. Wszystkie zależności powinny być łatwe do zaspokojenia zarówno dla małych, jak i dużych użytkowników, co również wiąże się z nieznacznymi kosztami podstawowymi.
Architektura Thanos
Po wymienieniu naszych celów w poprzedniej sekcji, przyjrzyjmy się, jak Thanos rozwiązuje te problemy.
Globalny widok
Aby uzyskać widok globalny na istniejące instancje Prometheusa, musimy połączyć jednolitą bramę zapytań ze wszystkimi serwerami. To właśnie robi komponent Thanos. . Jest wdrażany obok każdego serwera Prometheus i działa jako proxy, obsługując lokalne dane Prometheusa przez interfejs gRPC Store API, który pozwala na wybieranie danych szeregów czasowych według etykiet i zakresu czasowego.
Z drugiej strony znajduje się komponent Querier, który jest skalowalny horyzontalnie i nie przechowuje stanu, który robi nieco więcej niż tylko odpowiada na zapytania PromQL przez standardowe API HTTP Prometheusa. Komponenty Querier, Sidecar i inne elementy Thanos komunikują się za pomocą .

- Querier, odbierając zapytanie, łączy się z odpowiednim serwerem Store API, czyli z naszymi Sidecar'ami, i uzyskuje dane szeregów czasowych z odpowiednich serwerów Prometheus.
- Następnie łączy odpowiedzi i wykonuje zapytanie PromQL. Querier może łączyć zarówno nieprzechodzące dane, jak i dane zduplikowane z serwerów HA Prometheusa.
To rozwiązuje główną część naszej zagadki — scalenie danych z izolowanych serwerów Prometheusa w jednolite przedstawienie. W rzeczywistości Thanos można używać tylko dla tej funkcji. Nie wymaga się żadnych zmian w istniejących serwerach Prometheusa!
Nielimitowany czas przechowywania!
Jednak prędzej czy później będziemy chcieli zachować dane, które przekraczają standardowy czas przechowywania Prometheusa. Do przechowywania danych historycznych wybraliśmy magazyn obiektowy. Jest on szeroko dostępny w każdej chmurze, a także w lokalnych centrach danych i jest bardzo ekonomiczny. Co więcej, niemal każdy magazyn obiektowy jest dostępny przez dobrze znany interfejs API S3.
Prometheus zapisuje dane z pamięci operacyjnej na dysk co około dwie godziny. Blok zapisywanych danych zawiera wszystkie dane za określony przedział czasu i jest niezmienny. To bardzo wygodne, ponieważ Thanos Sidecar może po prostu przeglądać katalog danych Prometheusa i, w miarę pojawiania się nowych bloków, ładować je do koszyków magazynu obiektowego.

Ładowanie do magazynu obiektowego bezpośrednio po zapisaniu na dysk pozwala również zachować prostotę 'skrapera' (Prometheus i Thanos Sidecar). Co upraszcza utrzymanie, koszty i projektowanie systemu.
Jak widać, kopia zapasowa danych jest realizowana bardzo prosto. A co z zapytaniami do danych w obiektowej pamięci masowej?
Komponent Thanos Store działa jako proxy do pozyskiwania danych z obiektowej pamięci masowej. Tak jak Thanos Sidecar, uczestniczy w gossip-klastrze i implementuje Store API. W ten sposób istniejące Querier mogą traktować go jak Sidecar, jako dodatkowe źródło danych czasowych — nie jest wymagane żadne specjalne ustawienie.

Bloki danych czasowych składają się z kilku dużych plików. Pobieranie ich na żądanie byłoby dość nieefektywne, a lokalne buforowanie wymagałoby ogromnej pamięci i przestrzeni dyskowej.
Zamiast tego Store Gateway wie, jak obsługiwać format przechowywania Prometheus. Dzięki inteligentnemu planowaniu zapytań i buforowaniu tylko niezbędnych części indeksu bloków, możliwe stało się skrócenie złożonych zapytań do minimalnej liczby zapytań HTTP do plików obiektowej pamięci masowej. W ten sposób można zredukować liczbę zapytań o cztery do sześciu rzędów i osiągnąć czas odpowiedzi, który jest ogólnie trudny do odróżnienia od zapytań do danych na lokalnym SSD.

Jak pokazano na powyższym diagramie, Thanos Querier znacznie obniża koszty jednego zapytania do danych w obiektowej pamięci masowej, korzystając z formatu przechowywania Prometheus i umieszczając powiązane dane blisko siebie. Używając tego podejścia, możemy połączyć wiele pojedynczych zapytań w minimalną liczbę operacji zbiorczych.
Dekompozycja i downsampling
Po tym, jak nowy blok danych czasowych zostanie pomyślnie załadowany do obiektowej pamięci masowej, traktujemy go jako „dane historyczne”, które natychmiast stają się dostępne za pośrednictwem Store Gateway.
Jednak po pewnym czasie bloki z jednego źródła (Prometheus z Sidecar) gromadzą się i już nie wykorzystują całego potencjału indeksacji. Aby rozwiązać ten problem, wprowadziliśmy kolejny komponent o nazwie Compactor. Po prostu stosuje lokalny mechanizm kompaktowania Prometheus do danych historycznych w obiektowej pamięci masowej i może być uruchamiany jako prosty okresowy zadań wsadowe.

Dzięki efektywnemu kompresowaniu, zapytanie do magazynu przez długi czas nie stwarza problemów z perspektywy rozmiaru danych. Jednak potencjalny koszt dekompresji miliarda wartości i przetwarzania ich przez silnik zapytań nieuchronnie prowadzi do znacznego wydłużenia czasu wykonania zapytania. Z drugiej strony, ponieważ na każdy piksel ekranu przypada setki punktów danych, staje się niemożliwe nawet wizualizowanie danych w pełnej rozdzielczości. Tak więc, downsampling nie tylko jest możliwy, ale również nie prowadzi do zauważalnej utraty dokładności.

Do downsample'ingu danych Compactor ciągle agreguje dane o rozdzielczości pięciu minut i jednej godziny. Dla każdego nieprzetworzonego fragmentu, zakodowanego przy użyciu kompresji TSDB XOR, przechowywane są różne typy zagregowanych danych, takie jak min, max lub sum dla jednego bloku. Umożliwia to Querierowi automatyczne wybieranie agregatu, który pasuje do danego zapytania PromQL.
Aby korzystać z danych o obniżonej precyzji, użytkownik nie potrzebuje żadnej specjalnej konfiguracji. Querier automatycznie przełącza się między różnymi rozdzielczościami a danymi surowymi w miarę powiększania i zmniejszania skali przez użytkownika. W razie potrzeby użytkownik może zarządzać tym bezpośrednio poprzez parametr „step” w zapytaniu.
Ponieważ koszt przechowywania jednego GB jest niewielki, domyślnie Thanos przechowuje dane surowe, dane o rozdzielczości pięciu minut i jednej godziny. Nie ma potrzeby usuwania danych surowych.
Reguły rejestracji
Nawet z Thanos, reguły rejestracji są istotną częścią stosu monitorowania. Zmniejszają złożoność, opóźnienie i koszt zapytań. Są również wygodne dla użytkowników do uzyskiwania zagregowanych danych na podstawie metryk. Thanos opiera się na standardowych instancjach Prometheus, więc jak najbardziej dozwolone jest przechowywanie reguł rejestracji i reguł alertowania na istniejącym serwerze Prometheus. Jednak w niektórych przypadkach może to być niewystarczające:
- Globalne alerty i reguły (np. powiadomienia, gdy usługa nie działa w więcej niż dwóch z trzech klastrów).
- Reguła dla danych poza lokalnym magazynem.
- Dążenie do przechowywania wszystkich reguł i alertów w jednym miejscu.

Wszystkie te przypadki Thanos obejmują osobny komponent zwany Ruler, który oblicza reguły i alerty za pomocą zapytań Thanos. Umożliwiając znany StoreAPI, węzeł zapytań może uzyskać dostęp do świeżo obliczonych metryk. Później są one również przechowywane w obiektowej pamięci masowej i stają się dostępne przez Store Gateway.
Moc Thanos
Thanos jest na tyle elastyczny, że można go dostosować do swoich wymagań. To szczególnie przydatne podczas migracji z prostego Prometheusa. Przypomnijmy sobie szybko na małym przykładzie, co dowiedzieliśmy się o komponentach Thanos. Oto jak przenieść swojego waniliowego Prometheusa do świata „nieograniczonego przechowywania metryk”:

- Dodaj Thanos Sidecar do swoich serwerów Prometheus — na przykład sąsiadujący kontener w podzie Kubernetes.
- Rozmieść kilka replik Thanos Querier, aby mieć możliwość przeglądania danych. Na tym etapie łatwo skonfigurować gossip między Scraper a Querier. Aby sprawdzić interakcję komponentów, użyj metryki ‘thanos_cluster_members’.
Te dwa kroki są wystarczające, aby zapewnić globalny widok i płynne deduplikowanie danych z potencjalnych replik HA Prometheusa! Po prostu podłącz swoje pulpitowe widoki do końcowego punktu HTTP Querier lub użyj interfejsu Thanos UI bezpośrednio.
Jeśli potrzebujesz jednak kopii zapasowych metryk i długoterminowego przechowywania, będziesz musiał wykonać jeszcze trzy kroki:
- Utwórz koszyk AWS S3 lub GCS. Skonfiguruj Sidecar do kopiowania danych do tych koszyków. Teraz można zminimalizować lokalne przechowywanie danych.
- Rozmieść Store Gateway i podłącz go do istniejącego klastra gossip. Teraz możesz wysyłać zapytania do danych w kopiach zapasowych!
- Rozmieść Compactor, aby zwiększyć efektywność zapytań dotyczących długich okresów czasu, wykorzystując kompresję i downsampling.
Jeśli chcesz dowiedzieć się więcej, nie wahaj się, zapoznaj się z naszymi i !
W pięciu krokach przekształciliśmy Prometheusa w niezawodny system monitorowania z globalnym widokiem, nieograniczonym czasem przechowywania i potencjalnie wysoką dostępnością metryk.
Pull request: potrzebujemy cię!
od samego początku był projektem open source. Bezproblemowa integracja z Prometheusem i możliwość korzystania tylko z części Thanos czyni go doskonałym wyborem do skalowania systemu monitorowania bez zbędnego wysiłku.
Zawsze chętnie przyjmujemy Pull Requesty i Issues z GitHub. W razie potrzeby nie wahaj się z nami skontaktować przez Github Issues lub Slack., jeśli masz pytania lub uwagi, lub chcesz podzielić się swoim doświadczeniem! Jeśli podoba Ci się to, co robimy w Improbable, nie wahaj się z nami skontaktować — !
Źródło: habr.com
