Зберігання метрик: як ми перейшли з Graphite+Whisper на Graphite+ClickHouse

Всім привіт! В своїй минулій статті я писав про організацію модульної системи моніторингу мікросервісної архітектури. Нічого не стоїть на місці, наш проект постійно зростає, і кількість метрик, що зберігаються, — теж. Як ми організували перехід з Graphite+Whisper на Graphite+ClickHouse в умовах високих навантажень, про очікування від нього та результати міграції читайте під катом.

Зберігання метрик: як ми перейшли з Graphite+Whisper на Graphite+ClickHouse

Перш ніж я розповім, як ми організували перехід від зберігання метрик у Graphite+Whisper на Graphite+ClickHouse, хотілося б дати інформацію про причини прийняття такого рішення та про ті мінуси Whisper, з якими ми жили протягом тривалого часу.

Проблеми Graphite+Whisper

1. Високе навантаження на дискову підсистему

На момент переходу до нас прилітало приблизно 1.5 млн метриків за хвилину. З таким потоком дискова утилізація на серверах дорівнювала ~30%. Загалом це було цілком прийнятно — все працювало стабільно, швидко писалося, швидко читалося… Доти, доки одна з команд розробки не викотила нову фічу і не відправляла нам 10 млн метрик на хвилину. Ось тоді дискова підсистема напружилася, і ми побачили 100% утилізації. Проблему вдалося швидко вирішити, але осад залишився.

2. Відсутність реплікації та консистентності

Швидше за все, як і всі, хто використовує/використовував Graphite+Whisper, ми лили однаковий потік метрик відразу на кілька серверів Graphite з метою створення стійкості до відмов. І з цим особливих проблем не було — до того моменту, коли один із серверів з якоїсь причини не падав. Іноді ми встигали підняти сервер, що впав, досить швидко, і carbon-c-relay встигав заливати в нього метрики зі свого кеша, а іноді ні. І тоді в метриках була дірка, яку ми затягували rsync`ом. Процедура була досить довгою. Рятувало лише те, що відбувалося таке дуже рідко. Також ми періодично брали рандомний набір метрик і порівнювали їх іншими на сусідніх нодах кластера. Приблизно в 5% випадків кілька значень відрізнялися, що нас не дуже тішило.

3. Великий обсяг займаного місця

Так як ми пишемо в Graphite не тільки інфраструктурні, а й бізнес-метрики (а тепер ще й метрики з Kubernetes), то досить часто отримуємо ситуацію, при якій у метриці є лише кілька значень, а .wsp-файл створюється з урахуванням всього retention періоду, і займає передвиділений обсяг місця, який у нас дорівнював ~2Мб. Проблема погіршується ще й тим, що подібних файлів з часом з'являється дуже багато, і при побудові звітів про читання порожніх точок йде багато часу і ресурсів.

Відразу хотілося б відзначити, що з проблемами, описаними вище, можна боротися різними методами і з різним ступенем ефективності, але чим більше до вас починає надходити дані, тим сильніше вони загострюються.

Маючи все перераховане вище (з урахуванням попередньої статті), а також постійне зростання кількості одержуваних метрик, бажання перевести всі метрики до інтервалу зберігання 30 сек. (за потреби — до 10 сек.), ми вирішили спробувати Graphite+ClickHouse як перспективну альтернативу Whisper.

Graphite+ClickHouse. Очікування

Відвідавши кілька мітапів хлопців з Яндекса, прочитавши пару статей на Хабре, прошерстівши документацію і знайшовши осудні компоненти для обв'язки ClickHouse під Graphite, ми вирішили діяти!

Хотілося отримати таке:

  • зменшити утилізацію дискової підсистеми з 30% до 5%;
  • знизити обсяг місця з 1Тб до 100Гб;
  • мати можливість приймати по 100 млн метрик за хвилину на сервер;
  • реплікацію даних та відмовостійкість із коробки;
  • не сидіти над цим проектом рік і зробити перехід за певний термін;
  • перейти без даунтайму.

Досить амбітно, правда?

Graphite+ClickHouse. Компоненти

Для отримання даних по протоколу Graphite і наступного запису їх у ClickHouse, було обрано carbon-clickhouse (Golang).

Як база даних для зберігання часових рядів був обраний останній на той момент реліз ClickHouse стабільної версії 1.1.54253. Працюючи з ним були проблеми: у логи сипало гору помилок, і було зовсім зрозуміло що з нею робити. В обговоренні з Романом Ломоносовим (автор carbon-clickhouse, graphite-clickhouse та все ще багато-багато) був обраний більш старий реліз 1.1.54236. Помилки зникли — все почало працювати на ура.

Для читання даних із ClickHouse був обраний graphite-сlickhouse (Golang). Як API-інтерфейс для Graphite carbonapi (Golang). Для організації реплікації між таблицями ClickHouse було використано Zookeeper. Для маршрутизації метрик ми залишили нами гаряче коханий carbon-c-реле (С) (Див. минулу статтю).

Graphite+ClickHouse. Структура таблиць

graphite - база даних, створена нами для таблиць моніторингу.

"graphite.metrics" - таблиця з движком ReplicatedReplacingMergeTree (реплікований ReplacingMergeTree). У цій таблиці зберігаються імена метрик та шляхи до них.

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" - таблиця з двигуном ReplicatedGraphiteMergeTree (реплікований GraphiteMergeTree). У цій таблиці зберігаються значення метрик.

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" - таблиця, що заповнюється за умовою, з двигуном ReplicatedReplacingMergeTree. У цю таблицю записуються імена всіх метриків, які зустрілися за добу. Причини створення описані у розділі «Проблеми» наприкінці цієї статті.

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" - таблиця, що заповнюється за умовою, з движком ReplicatedAggregatingMergeTree (реплікований AggregatingMergeTree). У цю таблицю записується кількість вхідних метрик з розбивкою до 4 рівня вкладеності.

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, Prefix

Graphite+ClickHouse. Схема взаємодії компонентів

Зберігання метрик: як ми перейшли з Graphite+Whisper на Graphite+ClickHouse

Graphite+ClickHouse. Міграція даних

Як ми пам'ятаємо з очікувань цього проекту, перехід на ClickHouse повинен бути без даунтаймів, відповідно, ми повинні були якимось чином переключити всю нашу систему моніторингу на нове сховище максимально прозоро для наших користувачів.
Зробили ми це так.

  • У carbon-c-relay додали правило відправляти додатковий потік метрик до carbon-clickhouse одного з серверів, що беруть участь у реплікації ClickHouse таблиць.

  • Написали невеликий скрипт на python, який за допомогою бібліотеки whisper-dump вичитував усі .wsp-файли з нашого сховища та відправляв ці дані до вищеописаного carbon-clickhouse у 24 потоки. Кількість значень метрик, що приймаються в carbon-clickhouse, досягала в 125 млн/хв., і ClickHouse навіть не спітніла.

  • Створили окремий DataSource Grafana з метою налагодження функцій, що використовуються в існуючих дашбордах. Виявили список функцій, які ми використовували, але вони не були реалізовані в carbonapi. Дописали ці функції, і відправили PR авторам carbonapi (окреме їм спасибі).

  • Для перемикання навантаження, що читає, в налаштуваннях балансувальників змінили ендпоінти з graphite-api (API інтерфейс для Graphite+Whisper) на carbonapi.

Graphite+ClickHouse. Результати

  • знизили утилізацію дискової підсистеми з 30% до 1%;

    Зберігання метрик: як ми перейшли з Graphite+Whisper на Graphite+ClickHouse

  • знизили обсяг займаного місця з 1 Тб до 300 Гб;
  • маємо можливість приймати по 125 млн метрик за хвилину на сервер (піки в момент міграції);
  • переклали всі метрики на тридцятисекундний інтервал зберігання;
  • отримали реплікацію даних та відмовостійкість;
  • перейшли без даунтайму;
  • на все витратили приблизно 7 тижнів.

Graphite+ClickHouse. Проблеми

У нашому випадку не обійшлося і без підводного каміння. Ось із чим ми зіткнулися після переходу.

  1. ClickHouse не завжди перечитує конфіги на льоту, іноді його треба перезавантажувати. Наприклад, у випадку з описом кластера zookeeper в конфізі ClickHouse - він не застосовувався до перезавантаження clickhouse-server.
  2. Не проходили великі запити ClickHouse, тому у нас у graphite-clickhouse рядок підключення до ClickHouse має такий вигляд:
    url = "http://localhost:8123/?max_query_size=268435456&max_ast_elements=1000000"
  3. У ClickHouse досить часто виходять нові версії стабільних релізів, у них можуть зустрітися сюрпризи: будьте уважні.
  4. Динамічно створювані контейнери в kubernetes відправляють велику кількість метрик з коротким та випадковим періодом життя. Точок за такими метриками не багато, і проблем із місцем немає. Але при побудові запитів ClickHouse піднімає величезну кількість цих самих метрик з таблиці 'metrics'. У 90% випадків дані щодо них за вікно (24 години) відсутні. А ось час на пошук цих даних у таблиці 'data' витрачається, і зрештою впирається в тайм-аут. Для того, щоб вирішити цю проблему, ми почали вести окрему юшку з інформацією по метриках, які зустрілися за добу. Таким чином, при побудові звітів (графіків) по контейнерах, що динамічно створюваються, ми опитуємо тільки ті метрики, які зустрічалися в межах заданого вікна, а не за весь час, що в рази прискорило побудову звітів по них. Для вищеописаного рішення було зібрано graphite-clickhouse (fork), що включає реалізацію роботи з таблицею date_metrics

Graphite+ClickHouse. Теги

З версії 1.1.0 Graphite став офіційно підтримувати теги. І ми активно думаємо над тим, що і як треба зробити, щоб підтримати цю ініціативу в стеку graphite+clickhouse.

Graphite+ClickHouse. Детектор аномалій

На базі описаної вище інфраструктури ми реалізували прототип детектора аномалій, і він працює! Але про нього у наступній статті.

Підписуйтесь, натисніть стрілку вгору і будьте щасливі!

Джерело: habr.com

Додати коментар або відгук