Привет, Хабр! Меня зовут Ткачев Константин, и я работаю архитектором в Леруа Мерлен.
В этой статье я хочу рассказать, как мы смогли, используя только open-source, построить систему работы с метаданными, которая позволила:
централизовать и унифицировать описания данных, используемых в компании;
автоматизировать процессы загрузки данных в корпоративное хранилище — платформу данных;
и сделать еще многое-многое другое…
А если добавить к этому, что мы сделали это быстро — и в итоге за пару месяцев получили работающую систему, то станет ясно, почему мы решили поделиться этим опытом с пользователями Хабра.
Что такое метаданные
Если совсем коротко, то метаданные — это информация (данные) о другой информации. Метаданные могут описывать объекты базы данных, как, например, это выполняет системный каталог PostgreSQL, или процессы обработки данных ETL/ELT в виде направленного графа (DAG’а) Airflow.
Важность метаданных в IT-системах чрезвычайно высока, поскольку без них поиск и использование нужной информации были бы весьма и весьма затруднительны.
Разработанная нами система управления метаданными оперирует, если так можно выразиться, технологическими метаданными, которые описывают:
структуру источников центрального хранилища данных компании — платформу данных (платформа);
различные STTM (Source To Target Mapping);
настройки наших инструментов, например Airflow, который используется для загрузки данных в платформу (о работе нашего коммунального Airflow мы писали тут);
права доступов к объектам платформы;
описания DAG’ов Airflow, использующихся в одном из наших решений — Marts Loader;
правила работы наших сервисов, например, условия партиционирования таблиц платформы данных для соответствующего сервиса.
Наши метаданные не только описывают данные, но и определяют потоки их обработки, а также настройки инструментов работы с данными в нашей компании.
С чего все началось
В далеком 2019-м одним из направлений наших работ было построение платформы данных, к которой ваш покорный слуга имел самое непосредственное отношение. Мы определились с подходом и инструментарием, за исключением того, что у нас не была выбрана система управления метаданными и справочниками. В данной статье речь пойдет только о метаданных, так как о справочниках и всем, что с ними связано, напрашивается целый цикл статей)).
Поскольку нам необходимо было оперативно двигаться в отношении построения платформы и мы начинали интегрировать первые источники, отсутствие инструментария по работе с различными метаданными «несколько» сдерживало нас. Можно сказать, что, создавая платформу данных, мы не знали, что она будет в себе хранить и как в ней можно будет найти требуемую информацию. Необходимо было в краткие сроки найти подходящий инструмент. В число базовых требований были включены гибкость применения и расширение функциональных возможностей инструмента. Да, и мы, в рамках принятого подхода, рассматривали только open-source-инструменты.
Требования к системе управления метаданными
Требования к системе управления метаданными включают:
описание объектов и процессов информационных систем, причем не только платформы данных;
описание различных настроек работы информационных систем;
возможность предоставления метаданных через REST API;
наличие инструмента по редактированию и просмотру метаданных с учетом прав доступа;
возможность гибкой классификации и редактирования структуры метаданных;
необходимость дополнительно обеспечить data lineage (забегая немного вперед, скажу, что мы это обеспечили хранением STTM, которые используются в наших процессах обработки данных);
скорость разработки и применения инструмента управления метаданными;
скорость освоения сотрудниками компании;
простую интеграцию в CI/CD pipeline;
обеспечение качества метаданных, на основе выработанных критериев;
использование только собственных разработок или open-source-инструментов.
Рассматривали собственную разработку с хранением метаинформации в БД (планировали использовать PostgreSQL), но времени на разработку относительно гибкой структуры и пользовательского интерфейса не было, так как, повторю, начиналась интеграция источников.
Также мы рассмотрели применение следующих инструментов:
Hive metastore заточен для описания таблиц в БД, включая наименования и типы столбцов, а также специфическую для HDFS информацию — партиции и бакеты. Мы же планировали не только описывать таблицы в БД, тем более что системный каталог платформы данных уже решал эту задачу.
Atlas предполагал слишком уж большой уровень абстракции, мы решили, что его применение, описание метаданных и поддержка будут сложны и нам, как внедренцам, и пользователям.
Amundsen неплох: имеет приятный интерфейс и развитые средства Data Discovery, использует Airflow для Data ingestion, ElasticSearch для поиска данных и Neo4J или Atlas для хранения метаданных, API layer реализован с использованием Flask. В общем, он нам понравился, но все-таки его функционал ограничен (фактически ограничен предоставляемым UI) и он не отвечал многим из наших требований. Стоит отметить, что к исследованию Amundsen мы приступили, уже начав разработку собственного инструмента, и это окончательно повлияло на наше решение. Если перед вами стоит вопрос выбора инструмента управления метаданными, то можем порекомендовать обратить внимание на эту систему.
Жизнь не стоит на месте, появляются новые интересные инструменты для работы с метаданными. Мы пробуем использовать появившиеся возможности и сейчас мы тестируем такое средство как Open Metadata. Пока у нас нет полного представления о всех его функциях, но вполне вероятно, что оно приживется в нашем стеке технологий))
DIY-путь
Поскольку мы компания, работающая в сегменте DIY (Do It Yourself), то и на подходы в области IT-технологий философия компании влияет — разумеется, в хорошем смысле этого слова. Мы не сторонники изобретать велосипед, но у нас руки горят доработать этот самый велосипед, чтобы он максимально соответствовал целям, ради которых мы его используем. Ну и, конечно, добавить немного индивидуальности и привнести что-то свое и полезное — дополнительная мотивация для нас.
А если серьезно, то мы хотели в достаточно короткое время разработать систему, которая позволит удовлетворить наши потребности в области описания данных и, что немаловажно, их использования широкой аудиторией.
Так мы начали создавать свою систему по управлению метаданными, или DIY-мету.
Как все это работает (архитектура DIY-меты)
Общая идея такова...
Метаданные мы решили хранить в виде файлов yaml. Почему? Этот формат читабелен и пользователям легко с ним работать.
Для хранения и изменения DIY-меты мы используем github. Пользователи выполняют изменения метаданных и формируют pull request (PR). Выбрав github, как систему хранения для DIY-меты, мы дополнительно получили ряд полезных и вкусных «плюшек»:
использование в CI/CD pipeline (об этом подробнее позже);
решение вопроса с авторизацией и аутентификацией, в том числе использование CODEOWNERS для ограничения изменений данных в GIT.
После изменений в виде PR стартует CI/CD pipeline, который выполняет тестирование, сборку и деплой контейнера Docker с сервисом метаданных на определенное окружение (в зависимости от того, в какую ветку был PR). В результате сборки контейнер содержит yaml-файлы с метаданным.
Доступ к DIY-мете для наших информационных систем и пользователей предоставляется посредством сервиса метаданных.
Структура хранения метаданных и соглашение по наименованию объектов
Получилось, что в нашем случае метаданные — набор yaml-файлов и python-файлов, которые объединены в определенную структуру хранения.
Python-файлы содержат тесты пользователей, которые проверяются в рамках автотестов, о чем я расскажу ниже более подробно.
Однако простота и гибкость ведения DIY-меты могла обернуться полной неразберихой, поэтому мы задали определенные правила наименования, а также верхнеуровневую классификацию метаданных в виде структуры каталогов (папок). Таким образом, у нас появилось соглашение, которое определяет структуру хранения файлов и их наименования. При этом, поскольку мы храним DIY-мету как файлы в каталогах (как в файловой системе), мы сохраняем определенную гибкость по переопределению описания данных.
И еще, для некоторых типов файлов, структура которых должна быть четко определена, мы задали канонические схемы в виде json-схем. Эти схемы используются автотестами для проверки корректного описания данных. Например, такие схемы описывают таблицы, которые являются источниками для платформы данных, также схемы используются для задания мэппингов атрибутов объектов.
Ниже приведена структура метаданных, которую мы используем.
metadata(root)
|
├── metadata_repository_tests (for metadata tests: structure, naming, etc)
|
├── system_1 (e.g. dataplatform)
| |
| ├── processes
| | ├── base (base process)
| | | ├── ...
| | | └── data.yaml (types mapping, etc)
| | |
| | ├── technology process_1
| | | ├── ...
| | | └── data.yaml (types mapping, etc)
| | └── technology process_N
| | ├── ...
| | └── data.yaml (types mapping, etc)
| |
| ├── data (sources, destinations, etc)
| │ ├── data_name_1
| │ | ├── namespace_1 (!!!! If only necessary !!!)
| | | | ├── object_name_1
| │ | | | └── data.yaml
| │ | | ├── object_name_N
| │ | | | └── data.yaml
| | | | └── data.yaml
| | | └── data.yaml
| │ │
| │ ├── data_name_N
| │ | └── ...
| | |
| | └── data.yaml
| |
| ├── access
| │ ├── system_1(Greenplum)
| | | |
| │ | ├── data_name_1/namespace
| │ │ | └── data.yaml
| │ │ ├── ...
| | │ │
| | | └── data_name__N/namespace
| │ | └── data.yaml
| │ |
| │ ├── system_2 (NiFi)
| | ├── system_3 (S3)
| | └── system_N (Airflow)
| |
| ├── infrastructure
| | |
| | ├── airflow_<...>
| | └── ...
| |
| └── data.yaml (common information about system)
|
└── system_N
А ниже приведен пример шаблона описания таблицы базы данных, который является источником платформы данных. Для этого шаблона у нас определена каноническая схема в json.
object:
name: <table_name>
key_list:
- <attribute_1_name>
- <attribute_2_name>
confidentiality:
- confidential
- sensitive
attibutes:
- name: <attribute_1_name>
type: <type_1>
- name: <attribute_2_name>
type: <type_2>
...
CI/CD pipeline
Применить изменения и выкатить их на окружения нам помогает старина Jenkins.
Понятно, что CI-часть у нас организована в github. При PR происходят достаточно стандартные действия: на Jenkins’е клонируется репозиторий с DIY-метой (в том числе с Jenkinsfile), а затем запускается процесс, определенный в Jenkinsfile, который тестирует изменения, собирает Docker-контейнер с DIY-метой и деплоит его на нужное окружение в зависимости от ветки GIT, в которую были внесены изменения.
Для старта CD pipleline в github настроены webhooks на наш сервер Jenkins, а он знает URL репозитория DIY-меты в github, по которому расположен в том числе Jenkinsfile, содержащий инструкции для исполнения. Базовый образ Docker’а, использующийся для создания контейнера, получаем из нашего Artifactory, пароли получаем из Vault и сохраняем их в переменных окружения.
В процесс деплоя мы внесли ограничения по изменению на ПРОД-окружении. Для изменений в master-ветке (и, соответственно, на ПРОД-окружении сервиса метаданных) пользователям нужен approve их PR от CODEOWNERS, для изменения в dev- или test-ветке (ДЕВ- или ТЕСТ-окружение сервиса) approve не нужен.
Сервис метаданных
Итак, как я уже сказал выше, сервис метаданных — Docker-контейнер, который содержит сами метаданные и предоставляет API для доступа к DIY-мете. Доступ есть только на чтение. Сервис развернут на окружениях, которые соответствуют веткам в GIT: ДЕВ-окружение сервиса использует dev-ветку, ПРОД-окружение использует ветку master.
Первая версия сервиса была реализована на Flask, так как нам был нужен быстрый результат. Позднее, по мере развития работы сервиса, мы портировали его на Go, что повысило производительность и надежность, а также стабилизировали процесс деплоя сервиса.
Автотесты
Поскольку метаданные — особо важные данные, то после их изменения мы выполняем проверки, связанные с содержанием изменений. Автотесты существенно упрощают code-review и экономят нам время, что позволяет сфокусироваться на новых DIY — инструментах и сервисах)))
Поскольку сама DIY-мета хранится в GIT’е, то проверке подвергаются только измененные/добавленные метаданные (git diff нам в помощь). Проверок несколько, приведу основные:
соответствие соглашению о наименовании файлов и папок DIY-меты;
соответствие определенных файлов заранее заданной канонической схеме;
yaml-линтер проверяет на соответствие формату;
поскольку мы предоставили разработчикам возможность писать собственные тесты, которые запускаются при тестировании изменений, то дополнительно проверяем тесты разработчиков на наличие команд, которые могут потенциально удалить или изменить как метаданные, так и данные.
Надо сказать, автотесты можно использовать также и локально (на машинах разработчиков), и, что примечательно, автотесты работают на разных платформах (Windows, Linux).
Schema evolution
Дополнительно мы определили требования к процессу изменения структуры данных и конкретные инструкции, которым необходимо следовать при такого рода изменениях. В числе прочего коснулись, например, следующих вопросов:
использование значений по умолчанию для атрибутов/полей объектов данных, что обеспечивает обратную совместимость;
изменение существующих атрибутов/полей (наименование, тип); такие изменения выполняются путем добавления новых полей; поскольку в конечном итоге данные попадают в таблицы Платформы, такой подход позволяет сохранять историю;
требования и рекомендации по использованию данных после изменения структуры.
Вместо заключения
В настоящее время результаты наших усилий по созданию DIY-меты пользуются популярностью, что не может нас не радовать.
Так получилось, что все системы и сервисы, которые выполняют обработку данных в интересах платформы и автоматизируют процессы интеграции и предоставления доступа, пользуются DIY-метой: это и Airflow, и Marts Loader, и все процессинги обработки данных. Да, мы разрабатываем системы, которые позволяют автоматизировать процессы интеграции в платформу и ускорить их до нескольких дней, но это уже совсем другая история…