Cześć wszystkim! W swoim Pisałem o organizacji modułowego systemu monitorowania dla architektury mikroserwisów. Nic nie stoi w miejscu, nasz projekt nieustannie rośnie, a liczba przechowywanych metryk również. Jak zorganizowaliśmy przejście z Graphite+Whisper na Graphite+ClickHouse w warunkach wysokich obciążeń, o oczekiwaniach wobec niego i wynikach migracji przeczytacie poniżej.

Zanim opowiem, jak zorganizowaliśmy przejście z przechowywania metryk w Graphite+Whisper na Graphite+ClickHouse, chciałbym podać informacje o przyczynach podjęcia takiej decyzji oraz o wadach Whisper, z którymi żyliśmy przez długi czas.
Problemy Graphite+Whisper
1. Wysokie obciążenie systemu dyskowego
W momencie przejścia otrzymywaliśmy około 1,5 mln metryk na minutę. Przy takim strumieniu wykorzystanie dysków na serwerach wynosiło ~30%. Ogólnie to było całkiem akceptowalne — wszystko działało stabilnie, dane były szybko zapisywane i szybko odczytywane… Do momentu, gdy jedna z drużyn deweloperskich nie wprowadziła nowej funkcji i nie zaczęła nam przesyłać 10 mln metryk na minutę. Wtedy system dyskowy był mocno obciążony i zauważyliśmy 100% wykorzystania. Problem udało się szybko rozwiązać, ale pozostał niesmak.
2. Brak replikacji i spójności
Najprawdopodobniej tak jak wszyscy, którzy używają/używali Graphite+Whisper, wysyłaliśmy ten sam strumień metryk jednocześnie na kilka serwerów Graphite w celu zapewnienia odporności na awarie. I nie było z tym dużych problemów — do momentu, gdy jeden z serwerów z jakiegoś powodu nie padł. Czasami udawało nam się szybko przywrócić padły serwer, a carbon-c-relay zdążał zalać go metrykami z pamięci podręcznej, a czasami nie. I wtedy w metrykach powstawała luka, którą zasypywaliśmy za pomocą rsynca. Procedura była dość długa. Ratujące było tylko to, że coś takiego zdarzało się bardzo rzadko. Okresowo także wybieraliśmy losowy zestaw metryk i porównywaliśmy je z innymi takimi samymi na sąsiednich węzłach klastra. W około 5% przypadków kilka wartości różniło się, co nas nieco niepokoiło.
3. Duża ilość zajmowanego miejsca
Ponieważ w Graphite zapisujemy nie tylko metryki infrastrukturalne, ale także metryki biznesowe (a teraz także metryki z Kubernetes), dość często mamy sytuację, w której w metryce znajduje się tylko kilka wartości, a plik .wsp jest tworzony z uwzględnieniem całego okresu retencji i zajmuje przydzieloną objętość miejsca, która wynosiła około 2 MB. Problem pogłębia się tym, że takich plików z czasem pojawia się bardzo wiele, a podczas tworzenia raportów o nich na odczytywanie pustych punktów poświęca się dużo czasu i zasobów.
Od razu warto zauważyć, że z problemami opisanymi powyżej można walczyć różnymi metodami i z różnym stopniem efektywności, ale im więcej danych zaczyna do Ciebie napływać, tym bardziej się one zaostrzają.
Mając wszystko, co wymienione powyżej (z uwzględnieniem poprzedniej ), a także stały wzrost liczby otrzymywanych metryk oraz chęć przekształcenia wszystkich metryk na interwał przechowywania wynoszący 30 sek. (w razie potrzeby — do 10 sek.), zdecydowaliśmy się spróbować Graphite+ClickHouse jako perspektywicznej alternatywy dla Whisper.
Graphite+ClickHouse. Oczekiwania
Odwiedzając kilka meetupów organizowanych przez ludzi z Yandexa, czytając , przeszukując dokumentację i znajdując sensowne komponenty do integrowania ClickHouse z Graphite, postanowiliśmy działać!
Chcieliśmy osiągnąć następujące cele:
- zmniejszyć wykorzystanie systemu dyskowego z 30% do 5%;
- zmniejszyć zajmowaną przestrzeń z 1 TB do 100 GB;
- mieć możliwość przyjmowania 100 milionów metryk na minutę na serwer;
- replikację danych i odporność na awarie z pudełka;
- nie siedzieć nad tym projektem przez rok i zrealizować przejście w rozsądnym czasie;
- przełączyć się bez przestojów.
Dosyć ambitnie, prawda?
Graphite+ClickHouse. Komponenty
Do uzyskiwania danych za pomocą protokołu Graphite i późniejszego zapisywania ich w ClickHouse wybrano (golang).
Jako bazę danych do przechowywania szeregów czasowych wybrano najnowszą w tamtym czasie stabilną wersję ClickHouse 1.1.54253. Podczas pracy z nim pojawiły się problemy: w logach pojawiało się mnóstwo błędów, a nie było do końca jasne, co z nimi zrobić. W dyskusji z (autorem carbon-clickhouse, graphite-clickhouse i jeszcze wielu innych rzeczy) wybrano starszą Błędy zniknęły — wszystko zaczęło działać jak należy.
Do odczytu danych z ClickHouse wybrano (golang). Jako interfejs API dla Graphite — (golang). Aby zorganizować replikację między tabelami ClickHouse, użyto . Do routingu metryk pozostawiliśmy naszą ulubioną (C) .
Graphite+ClickHouse. Struktura tabel
„graphite” — baza danych stworzona przez nas dla tabel monitorujących.
„graphite.metrics” — tabela z silnikiem ReplicatedReplacingMergeTree (replikowana ). W tej tabeli przechowywane są nazwy metryk i ścieżki do nich.
CREATE TABLE graphite.metrics ( Date Date, Level UInt32, Path String, Deleted UInt8, Version UInt32 ) ENGINE = ReplicatedReplacingMergeTree('\/clickhouse\/tables\/replicator\/graphite.metrics', 'r1', Date, (Level, Path), 8192, Version);„graphite.data” — tabela z silnikiem ReplicatedGraphiteMergeTree (replikowana ). W tej tabeli przechowywane są wartości metryk.
CREATE TABLE graphite.data ( Path String, Value Float64, Time UInt32, Date Date, Timestamp UInt32 ) ENGINE = ReplicatedGraphiteMergeTree('\/clickhouse\/tables\/replicator\/graphite.data', 'r1', Date, (Path, Time), 8192, 'graphite_rollup')„graphite.date_metrics” — tabela wypełniana na podstawie warunków, z silnikiem ReplicatedReplacingMergeTree. Do tej tabeli zapisywane są nazwy wszystkich metryk, które wystąpiły w ciągu dnia. Powody stworzenia opisano w sekcji na końcu tego artykułu.
CREATE MATERIALIZED VIEW graphite.date_metrics ( Path String, Level UInt32, Date Date) ENGINE = ReplicatedReplacingMergeTree('\/clickhouse\/tables\/replicator\/graphite.date_metrics', 'r1', Date, (Level, Path, Date), 8192) AS SELECT toUInt32(length(splitByChar('.', Path))) AS Level, Date, Path FROM graphite.data„graphite.data_stat” — tabela wypełniana na podstawie warunków, z silnikiem ReplicatedAggregatingMergeTree (replikowana ). Do tej tabeli zapisywane jest liczba przychodzących metryk, z podziałem na 4 poziomy zagnieżdżenia.
CREATE MATERIALIZED VIEW graphite.data_stat ( Date Date, Prefix String, Timestamp UInt32, Count AggregateFunction(count)) ENGINE = ReplicatedAggregatingMergeTree('\/clickhouse\/tables\/replicator\/graphite.data_stat', 'r1', Date, (Timestamp, Prefix), 8192) AS SELECT toStartOfMonth(now()) AS Date, replaceRegexpOne(Path, '^([^.]+.[^.]+.[^.]+).*$', '1') AS Prefix, toUInt32(toStartOfMinute(toDateTime(Timestamp))) AS Timestamp, countState() AS Count FROM graphite.data GROUP BY Timestamp, PrefixGraphite+ClickHouse. Schemat interakcji komponentów

Graphite+ClickHouse. Migracja danych
Jak pamiętamy z oczekiwań wobec tego projektu, przejście na ClickHouse powinno odbyć się bez przestojów, w związku z czym musieliśmy w jakiś sposób przełączyć nasz cały system monitorowania na nowe magazyn w sposób maksymalnie przejrzysty dla naszych użytkowników.
Zrobiliśmy to w ten sposób.
W carbon-c-relay dodaliśmy regułę wysyłania dodatkowego strumienia metryk do carbon-clickhouse na jednym z serwerów biorących udział w replikacji tabel ClickHouse.
Napisaliśmy mały skrypt w Pythonie, który za pomocą biblioteki whisper-dump odczytywał wszystkie pliki .wsp z naszego repozytorium i przesyłał te dane do opisanego wcześniej carbon-clickhouse w 24 wątkach. Liczba przyjmowanych wartości metryk w carbon-clickhouse osiągnęła 125 mln/min, a ClickHouse nawet się nie spocił.
Stworzyliśmy oddzielny DataSource w Grafanie w celu debugowania funkcji używanych w istniejących dashboardach. Zidentyfikowaliśmy listę funkcji, które wykorzystywaliśmy, ale nie były one zaimplementowane w carbonapi. Dopisaliśmy te funkcje i wysłaliśmy PR-y do autorów carbonapi (szczególne podziękowania dla nich).
- Aby przełączyć obciążenie odczytu, zmieniliśmy punkty końcowe w ustawieniach load balancerów z graphite-api (interfejs API dla Graphite+Whisper) na carbonapi.
Graphite+ClickHouse. Wyniki
ograniczyliśmy wykorzystanie systemu dyskowego z 30% do 1%;

- zmniejszyliśmy zajmowaną przestrzeń z 1 TB do 300 GB;
- mamy możliwość przyjmowania 125 mln metryk na minutę na serwer (szczyty w momencie migracji);
- przenieśliśmy wszystkie metryki na 30-sekundowy interwał przechowywania;
- uzyskaliśmy replikację danych i odporność na awarie;
- przełączyliśmy się bez przestojów;
- wszystko zajęło nam około 7 tygodni.
Graphite+ClickHouse. Problemy
W naszym przypadku nie obyło się bez niespodzianek. Oto co napotkaliśmy po przejściu.
- ClickHouse nie zawsze na bieżąco odczytuje konfiguracje, czasami trzeba go ponownie uruchomić. Na przykład, w przypadku opisu klastra zookeeper w konfiguracji ClickHouse — nie był on stosowany do momentu ponownego uruchomienia clickhouse-server.
- Nie przeszły duże zapytania ClickHouse, dlatego nasza linia połączenia w graphite-clickhouse wygląda tak:
url = "http://localhost:8123/?max_query_size=268435456&max_ast_elements=1000000" - W ClickHouse dość często wydawane są nowe wersje stabilnych wydań, mogą się tam pojawić niespodzianki: bądź ostrożny.
- Dynamicznie tworzone kontenery w Kubernetes wysyłają dużą ilość metryk z krótkim i losowym okresem życia. Punktów dla takich metryk jest niewiele, a problemy z miejscem nie występują. Jednak podczas budowania zapytań ClickHouse pobiera ogromną ilość tych metryk z tabeli ‘metrics’. W 90% przypadków dane dotyczące nich są niedostępne na przestrzeni okna (24 godziny). Czas poświęcany na wyszukiwanie tych danych w tabeli ‘data’ jest znaczący i ostatecznie prowadzi do timeoutu. Aby rozwiązać ten problem, zaczęliśmy prowadzić osobny widok z informacjami o metrykach, które pojawiły się w ciągu ostatnich 24 godzin. W ten sposób, przy tworzeniu raportów (wykresów) dotyczących dynamicznie tworzonych kontenerów, pytamy tylko o te metryki, które pojawiły się w określonym oknie czasowym, a nie przez cały czas, co znacząco przyspieszyło tworzenie raportów na ich temat. Dla powyższego rozwiązania stworzono , obejmujący implementację pracy z tabelą date_metrics.
Graphite+ClickHouse. Tagi
Od wersji 1.1.0 Graphite oficjalnie . I aktywnie myślimy o tym, co i jak należy zrobić, aby wspierać tę inicjatywę w stosie graphite+clickhouse.
Graphite+ClickHouse. Wykrywacz anomalii
Na podstawie opisanej powyżej infrastruktury zrealizowaliśmy prototyp wykrywacza anomalii i działa! Ale więcej na ten temat — w następnym artykule.
Subskrybuj, kliknij strzałkę w górę i bądź szczęśliwy!
Źródło: habr.com

