Привет! Меня зовут Дима Ибрагимов. Я отвечаю за развитие и стабильность платформы данных «Леруа Мерлен». В этом посте я расскажу о наработках по мониторингу нашей платформы. Для нас это был (и остается) полезный опыт, который помог получить много новых инсайтов о работе всей системы. В «Леруа Мерлен» много пользователей GreenPlum — порядка 1000 ролей в самой БД и около 20000 BI-пользователей, которые ходят в дашборды и работают с данными. Речь пойдет о том, как грамотно настроить инструменты Observability и как принимать проактивные действия еще до того, как начнутся проблемы.
Больше Observability
Для начала нужно определиться с тем, что такое Observability. Этот термин появился с внедрением практик SRE (Site Reliability Engineering), которые активно продвигает на рынке компания Google. Поэтому логично взять определение Observability, которое дает Google.
Observability — это набор средств, позволяющий командам активно отлаживать свои системы. Observability базируется на изучении свойств и паттернов, которые не определены заранее.
Подход Observability нужен, когда мы не знаем заранее, как будет вести себя система. Расскажу на примере «Леруа Мерлен». Мы начали строить дата-платформу, развернули GreenPlum, пошли к пользователям и начали спрашивать: «А сколько вы данных будете заливать, а какие вам витрины, а что вам нужно?» Задавали много вопросов… и ни на один вопрос не получили ответа. И, знаете, это нормально! Бизнес-пользователи очень часто понятия не имеют, какие именно данные им в будущем понадобятся… и должны ли?
Observability — полезный подход, потому что позволяет решить реальную задачу бизнеса, при том что мы не знаем, как активно будут пользоваться системой. То есть фактически мы просто наблюдаем за GreenPlum в условиях нормального хаоса, а развитием системы в бОльшей степени занимаются наши пользователи, чем мы сами, так как они создают объекты, витрины, представления и наполняют их данными.
Кстати, организация Cloud Native Computing Foundation (CNCF) представляет ландшафт (Landscape) решений для Observability и отмечает огромное количество как самих инструментов, так и способов их имплементации.
Под GreenPlum и вокруг GreenPlum
Но прежде чем поговорить об инструментах, мне хочется рассказать о том, с чем мы в «Леруа Мерлен» имеем дело. На данный момент в компании насчитывается пять GreenPlum-инсталляций (это за исключением Docker-ных и тестовых инсталляций):
Production, развернутый на BareMetal;
Pre-prod кластер;
Disaster Recovery кластер;
два небольших кластера для сенситивных данных в секьюрном контуре.
Наш основной Production-кластер содержит 24 двухпроцессорные физические машины на Intel Xeon Gold 6148 по 40 ядер на каждом (с HT). На машинах установлено по 768 Гб памяти. Начинали мы с 256, но потом решили подрастить емкость, так как ETL часто генерировал слишком много спиллов (сейчас же спиллов на кластере почти нет). На каждой физической машине содержится по 18 сегментов GP, а также есть две выделенные машины — под Master и под Secondary Master. Все эти узлы распределены по двум стойкам в дата-центре с зеркалированием на выделенные ноды в соседних стойках.
Мы специально создали запас с точки зрения производительности. Master в среднем загружен на 60%. А чтобы не упираться в производительность дисковых подсистем, было создано два tablepace’а. Один работает на SSD и представляет собой «горячий» слой. А второй — «теплый» — он работает на базе HDD. Для этого мы собрали группы из 10 и 12 дисков соответственно в RAID 5. При этом объем хранимых данных в сумме — примерно 700 терабайт.
Конечно, мы ставим на все сервера стандартный node-exporter, грузим его дашборд в Grafana. Но для GreenPlum мы собрали отдельный дашборд по интересующим нас параметрам по всем серверам. О нем и поговорим дальше.
Метрики
Перейдем непосредственно к метрикам. Нас в первую очередь интересовали параметры утилизации CPU, дисков и память, а также значения I/O.
Утилизация CPU — это единая метрика для всего нашего кластера. Здесь мы в первую очередь смотрим на расхождение между самыми нагруженными и наименее нагруженными узлами. Если происходит большой перекос по нагрузке между нодами, мы сразу видим, что с кластером что-то не так: либо данные неправильно разложены, либо в данный момент на кластер приходят какие-то кривые запросы. Соответственно, можно что-то сделать.
Следующий тип метрик мы называем GP-inside. Мы их собираем с помощью Postgres Exporter
На картинке представлены те метрики, которые собираем мы. Самая интересная из них, наверное, gp_resgroup_status — метрика, которая говорит о состоянии ресурсных групп в нашем кластере.
На самом деле метрик для хранилища существует большое количество. Их можно определить по аналогии с Postgres — для этого даже есть специальный сайт pgstats.dev, на котором можно подсмотреть, какие метрики есть в Postgres. В принципе, бо́льшая часть из них есть и в GreenPlum. А если каких-то нет, то можно их сделать.
Нас, например, также интересует число запросов, находящихся в очереди в данный момент. Резкий рост этой метрики может говорить о том, что нужно как-то менять конфигурацию системы. В итоге можно предупредить разрастание очереди до того момента, как это станет проблемой.
Еще мы отрисовываем график по числу коннектов. Так как у нас большое число подключений, за ними нужно следить. Благодаря этой визуализации мы понимаем, что происходит в данный момент — и это важно, так как у нас есть глобальное ограничение на число подключений (max_connection).
Алерты
Алертов можно придумать огромное количество. У себя мы реализовали следующие:
упавшие сегменты;
очереди в ресурсных группах;
падение числа успешных запросов до нуля;
большое число коннектов;
спиллы/workfiles (если не ограничены);
лаг репликации сегментов.
Самые важные и интересные для нас алерты — по упавшим сегментам и по очередям в ресурсной группе. Конечно, когда мы говорим об очередях, временные скачки в этом разрезе не так критичны. Поэтому мы ставим на алерт событие, если в ресурсной группе очередь держится дольше 30 минут. Также мы следим за тем, чтобы число успешных запросов не падало до нуля. И если у вас нет ограничений по спиллам (на пользователя или глобально на весь кластер), очень важно следить и за ними тоже. Ведь если спиллы не вынесены на отдельные диски, то кластер может вообще развалиться, когда спиллами забьется все свободное место, а если вынесены, то могут падать запросы, их генерирующие. Поэтому в отношении спиллов тоже можно (и нужно) рисовать графики, создавать алерты.
Process-exporter
Следующий класс метрик, про который хотелось бы поговорить, — это process-exporter-метрики. Мы в «Леруа Мерлен» ставим process-exporter на все хосты кластера. Но для целей мониторинга GreenPlum стоит написать regexp, который парсит именно гринпламовские процессы, бегущие на кластере. Это очень удобно, потому что фактически в рамках задачи нас не интересуют все остальные процессы — нужны именно процессы GreenPlum и пользовательские запросы. Готовый дашборд, на котором видны их характеристики, собранные process-exporter, выглядит вот так:
С помощью process-exporter можно получить срез нагрузки на кластер относительно пользователей. И благодаря этой визуализации мы способны определить, сколько приходится ресурсов CPU на каждого пользователя, сколько он считал и записал информации на диск, сколько у него запущенных процессов, сколько открытых файлов, а также сколько резидентной и нерезидентной памяти он использует — все это делается практически в режиме Real Time.
В этом контексте интересно, например, посчитать процент использования CPU на пользователя. Для этого мы отправляем вот такой запрос:
(1 - avg(irate(node_cpu_seconds_total{mode='idle',cluster="$cluster"}[5m]))) * (sum by (username) (label_replace(rate(namedprocess_namegroup_cpu_seconds_total{cluster="$cluster", groupname!~"WAL.*"}[5m]), "username", "$1", "groupname", "(.*):.*")) / sum(rate(namedprocess_namegroup_cpu_seconds_total{cluster="$cluster"}[5m])))
И получаем следующий график:
Если приглядеться, можно увидеть, что бывают моменты, когда один пользователь отъедает почти все ресурсы CPU кластера. Когда мы это заметили, сначала не могли понять, почему так происходит. Но потом нашли. Оказывается, есть такая штука, как «CPU Burst». Это гринпламовская фича, которая позволяет запросам из одной ресурсной группы использовать ресурсы соседних ресурсных групп. Вот что написано в документации по этой фиче:
«A resource group may utilize more CPU than its CPU_RATE_LIMIT when other resource groups are idle. In this situation, Greenplum Database allocates the CPU resource of an idle resource group to a busier one. This resource group feature is called CPU burst» — GPDB Docs
Однако в GreenPlum 6.16 появился параметр gpu_resource_group_cpu_ceiling_enforcement, который можно поставить в true и отключить это безобразие. Тогда запросы, бегущие в одной ресурсной группе, не будут съедать ресурсы соседних групп даже в том случае, если они свободны.
Кстати, мы используем еще один экспортер — это Blackbox exporter. Он стандартный, поэтому о нем много писать не буду. Скажу лишь, что мы мониторим с помощью Blackbox SSH-порты, доступность всех сегментов, SQL-порты, Master, Secondary Master и прочего, а также PXF-порты всех нод. Если что-то оказывается недоступно — срабатывает алерт.
Кроме Blackbox, хорошие результаты дает мониторинг при помощи Elasticsearch query explorer. Он помогает мониторить и создавать алерты в случае возникновения всяческой жести и возрастающего числа FATAL/ERROR в логах.
Observability-подход для GreenPlum
Тут речь пойдет о Service Level Agreements и Service Level Objectives.
Как мы определяем SLA GreenPlum? Для этого мы оцениваем количество минут в кластере, когда не пробежало ни одного запроса, кроме админ-группы. Это важно, потому что мы, например, можем вывести кластер в maintenance, он будет доступен, мониторинг будет работать, но запросов, успешно пробежавших, в других группах, кроме админ-группы, не будет. И если нет ни одного запроса за минуту, успешно выполненного в кластере в других ресурсных группах, мы говорим, что с точки зрения SLA — это нолик, то есть недоступный кластер.
Desclaimer: Это наша реализация, т.к. мы знаем, что у нас на кластере всегда бегут пользовательские запросы, но для новых кластеров я бы посоветовал реализовать healthcheck’и, когда раз в минуту выполнялся бы запрос вида select 1 в не-административной ресурсной группе и возвращал бы 1 если кластер живой или 0, если запрос не выполнился.
Если посчитать SLA нашей платформы, то error budget будет в районе 99,5% — то есть порядка четырех часов в месяц. Мы закоммитились на этот SLA перед бизнесом и придерживаемся принятого порога. Таким образом, только если наш бюджет ошибок не исчерпан, мы проводим дополнительное обслуживание в кластере. А если по какой-то причине кластер упал или был недоступен, все регламентные обслуживания переносятся на следующий месяц. Такой подход позволяет выровнять ожидания пользователей по уровню доступности кластера.
Что касается метрик SLO, которые можно применить к кластеру GreenPlum, я могу предложить следующие значения.
Среднее время подключения к базе < 5 секунд
Среднее время ожидания начала выполнения запроса в ресурсной группе < 1 секунды
Время сбора GP-inside метрик (scrape duration) < 10 секунд
Время работы пайплайнов (расчета витрин, ODS/DDS слоев) колеблется в пределах 2-5%
Количество таблиц без статистики растет не более 100 в день (gp_toolkit.gp_stats_missing)
Генерация спиллов происходит не более чем для 0.5% запросов
Для >80% популярных/тяжелых запросов созданы витрины и DDS
Средний размер output’а AD-HOC запроса < 100.000 строк
И так далее
Дальнейший тюнинг
Помимо самого кластера GP, нам необходимо мониторить состояния сопутствующих сервисов. Например, pgbouncer. Как я уже упоминал, у нас довольно много коннектов к кластеру. А за счет внедрения pgbouncer мы собираем SHOW метрики с помощью pgbouncer-exporter.
Несколько идей мы как раз сейчас тестируем и обсуждаем. Например, интересным решением выглядит внедрение Envoy прокси перед GP. Если завернуть весь трафик в GreenPlum через Envoy, мы можем получать много разных интересных метрик. Также появляется возможность управлять запросами на уровне трафика и, как вариант, отправлять часть нагрузки на другие кластера (Dev/HA), чтобы снизить нагрузку на основной кластер GP.
Также мы внедрили в ознакомительном варианте анализ сегментов pg_statio_user_tables, pg_stat_user_tables. Метрика показывает количество sequential-сканов и прочитанных из хипа блоков. Анализ этих метрик позволяет выявлять паттерны нагрузки и популярность данных.
Итоги
Что я хотел сказать этим постом? С помощью хороших и правильно настроенных инструментов Observability можно выполнять довольно много операций: находить кривые запросы, находить людей, которые эти запросы пишут, вовремя к ним приходить, учить их, как правильно работать с GreenPlum, какие запросы нужно писать, а какие писать не надо. Также можно находить перекосы в раскладке данных: например, если у вас неправильно выбран ключ дистрибьюции, если данные разложены криво — все это можно отлавливать с помощью грамотно настроенных алертов и метрик.
Если вы предпочитаете смотреть, а не читать, то про мониторинг GreenPlum мы рассказывали в далеком 2021 году, видео по ссылке.
А как вы мониторите GreenPlum? Поделитесь в комментариях.