Построить платформу данных, которая станет не просто очередным корпоративных хранилищем, а реальным драйвером для бизнеса — это стратегический вызов. И эта статья посвящена тому, как превратить данные в актив, создав управляемую экосистему. Для этого посмотрим на то, какие принципы легли в основу построения платформы, как выглядит архитектура, и конечно же особое внимание будет уделено стеку. Надеюсь статья подарит вдохновение всем, кто ищет идеи для своей платформы!

Привет, Хабр! Меня зовут Ольга, как CDO я всегда заинтересована в монетизации данных и в выборе релевантных подходов для воплощения в жизнь своей стратегии по работе с данными наиболее эффективным способом, поэтому особое внимание уделяю архитектуре и стеку. Технологии и подходы быстро развиваются, важно не только успевать подхватить волну изменений, но и выстроить эффективный пайплайн для всего жизненного цикла данных.
При построении Платформы данных в Самолет использовались самые современные подходы и технологии. В моей дирекции присутствует глубокая экспертиза dataops, поэтому мы самостоятельно занимаемся разверткой и настройкой технологического стека. Меня часто спрашивают в сообществе, на чём мы построили свои решения, поэтому я и решила написать эту статью с пояснением подходов и инструментов.
И для начала расскажу о базовых принципах, которые были заложены в проектировании платформы:
1. «Не просто хранилка, а точка роста бизнеса»
Данные – это актив, нужно не просто уметь их накапливать, но намного важнее уметь ими управлять и применять для повышения эффективности бизнеса компании. Поэтому моя цель была создать комплексное решение, включающие набор сервисов для обслуживания полного цикла данных.
Экосистема сервисов и их назначение представлены на обложке данной статьи.
2. «И снова Open-Source»
OSS хорош, если уметь его готовить. Всегда ориентируюсь на подготовку собственных сборок из ванили с минимальными форками. Сообщество активно развивает открытые продукты и в большинстве случаев не нужно изобретать велосипеды. При продуманном скоринге и отборе инструментов стека можно обеспечить гибкость и хорошее развитие собранной платформы. Однако к OSS нужно подходить разумно, в другой моей статье как раз есть мысли на этот счет.
3. «Акцент на безопасность»
Безопасность данных и безопасность разработки всегда должны стоять во главе угла, поэтому подход должен учитывать связку компонентов аутентификации, авторизации и хранения секретов.
4. «Тиражируемость и отслеживаемость»
Мой опыт работы в облаке научил меня всегда следовать этому принципу.
И наконец, перейдем к технике, начиная с этого принципа.
Как выстроена Платформа данных в Самолете
Платформа построена на базе кластера Kubernetes. Весь код платформы находится в системе контроля версий Git и доставляется с помощью подхода GitOPS и инструмента Flux2. Это позволяет отслеживать все изменения платформы и легко ее тиражировать. По сути, мы создали «коробочное» решение и можем развернуть его на любой аппаратной или облачной платформе в кратчайшие сроки. Основными компонентами платформы являются:
Gitlab — система контроля версий;
Flux2 + Weave GitOps — это инструмент непрерывной поставки (CD) для Kubernetes осуществляет доставку и отслеживание изменений в кластер K8s;
Данные хранятся в корпоративном S3 minio, но при необходимости возможно использовать и облачный сервис, а также реализовывать гибрид;
Hashicorp Vault отвечает за хранение секретов;
Keycloak реализует функцию централизованной аутентификации пользователей или SSO для всех компонент платформы, включая каталоги данных такие как Iceberg Nessie;
Nexus отвечает за локальное хранение артефактов, что довольно актуально, если пропадает доступ к внешним ресурсам;
Airflow обеспечивает оркестрацию заданий;
Spark выступает вычислительным движком и отвечает за выполнение расчетов витрин данных;
Kafka реализует потоковую платформу;
Debezium применяем для захвата изменений данных;
Jupyterhub служит для разработки прототипов;
Clickhouse используется для хранения широких витрин данных которые применяются для визуализации в bi инструментах;
OpenSearch: сбор логов и их обработка являются основной составляющей, которая позволяет реализовать функцию мониторинга в базовом виде, поэтому выбрали эту БД как систему хранения логов всей платформы LakeHouse;
В качестве SQL engine используется Trino + Hive metastore с несколькими каталогами данных такими как Hive, iceberg, REST Iceberg, Iceberg Nessie;
MLFlow управляет жизненным циклом моделей машинного обучения;
Qdrant обеспечивает корпоративную базу знаний для реализации проектов искусственного интеллекта;
Open Web UI реализует сервис для запросов к текстовым генеративным моделям;
В качестве платформы для управления мета данными и обеспечения функции каталога данных применяем DataHub.
Солюшн-архитектура связки данных компонент в упрощенном виде выглядит следующим образом:

Далее уделю внимание ряду инструментов, о которых меня чаще всего спрашивают и подсвечу их значимость в платформе данных.
Каталоги данных
DataHub — это open-source-платформа LinkedIn для управления метаданными и каталогизации данных, созданная для упрощения поиска, понимания и контроля за данными в организациях. По сути это часть современного стека Data Governance и Data Discovery, которая обеспечивает функции:
Индексирует метаданные из различных источников (базы данных, дата-лайки, ETL-инструменты);
Позволяет искать таблицы, дашборды, pipelines по названию, тегам или описанию;
Обеспечивает просмотр lineage (происхождения данных) и визуализирует, как данные перемещаются между системами;
Предоставляет управление доступом;
Позволяет добавлять владельцев, теги и аннотаций к наборам данных;
Поддерживает 50+ источников: Snowflake, BigQuery, Kafka, dbt, Looker, Airflow и др.
Реализует политики качества данных и предоставляет уведомления об изменениях схемы.
Nessie Catalog — это компонент системы управления данными Nessie (также известной как Project Nessie), который представляет собой версионированное хранилище метаданных для Lakehouse-архитектур (например, Apache Iceberg, Delta Lake, Apache Hudi).
Основные функции Nessie Catalog:
1.Версионирование метаданных
Позволяет отслеживать изменения в таблицах (схемах, партициях и т. д.) с поддержкой ветвления, слияния и отката (как Git для данных);
Каждая версия каталога (commit) имеет уникальный идентификатор.
2.Поддержка транзакционности
Обеспечивает ACID-транзакции для операций с таблицами в рамках Data Lake.
3.Гибкость работы
Ветвление (branching) и теги (tagging)
Слияние изменений (merge)
Откат к предыдущим версиям (time travel)
4.Интеграция с движками табличных форматов
Работает с Apache Iceberg, Delta Lake и другими форматами через совместимые клиенты (Spark, Flink, Trino и др.). Ниже пример использования:
-- Создание ветки в Nessie Catalog
CREATE BRANCH analytics_branch IN nessie FROM main;
-- Переключение на ветку
USE REFERENCE analytics_branch IN nessie;
-- Внесение изменений (например, создание таблицы)
CREATE TABLE nessie.ns.my_table (id INT, name STRING);
Таким образом, Nessie Catalog решает проблему управления версиями данных в озёрах данных, позволяя командам:
Тестировать изменения без риска повредить прод;
Отслеживать историю изменений;
Работать в командном режиме (аналогично Git).
Доступ к данным
Немного подробнее остановлюсь на контроле доступа к данным. Ролевая модель доступа к данным (RBAC) реализована с помощью групповых политик и посредством Open Policy Agent, который интегрирован в нашу Платформу и в конечном итоге использует группы Keycloak, который в свою очередь применяет группы Active Directory. Это позволяет гибко управлять доступами к каталогам, схемам и таблицам, а также настраивать маскировку чувствительных данных при запросах.
Как это работает:
OPA проверяет запрос Trino (
input.query.sql
).Если пользователь не admin, политика находит столбцы из
mask_columns
. Применяет к нимmask_data()
, используяregex_replace
.
Интеграция с Trino выглядит следующим образом (псевдокод):
Trino для использования OPA (в etc/access-control.properties):
access-control.name=opa
opa.policy-uri=http://opa:8181/v1/data/system/opa/masking
package system.opa.masking
import future.keywords.in
# Определяем, какие столбцы маскируются
mask_columns := {
"customers": {"email", "phone", "credit_card"}
}
# Правила маскировки для каждого столбца
mask_rules := {
"email": {
"regex": "(?P<prefix>[^@]+)@(?P<domain>.+)",
"replace": "***@${domain}"
},
"phone": {
"regex": "\\+(\\d{1,3})(\\d{3})(\\d{3})(\\d{4})",
"replace": "+${1} *** *** ${4}"
},
"credit_card": {
"replace": "****-****-****-****"
}
}
# Проверяем, есть ли у пользователя права на просмотр данных
default is_admin := false
is_admin {
# Проверяем JWT-токен или заголовок запроса
input.context.identity.roles[_] == "admin"
}
# Применяем маскировку, если пользователь не admin
mask_data(column, value) := masked_value {
not is_admin
column_rules := mask_rules[column]
regex := column_rules.regex
replace := column_rules.replace
masked_value := regex_replace(regex, replace, value)
} else := value {
is_admin
}
# Основное правило для Trino
prepared_query := query {
input.query.sql == query
} else := masked_query {
not is_admin
masked_query := sqlglot.transpile(
input.query.sql,
column_mapper: func(col, table) {
if table in mask_columns && col in mask_columns[table] {
return sprintf("mask_data('%s', %s)", [col, col])
}
return col
}
)
}
Дополнительные возможности:
Динамическая маскировка на основе ролей (JWT, LDAP).
Логирование запросов с маскировкой.
Поддержка SQL-инъекций через
sqlglot
(транспиляция запросов).
Платформа машинного обучения
Поскольку на волне хайпа тема Искусственного интеллекта и в Самолет его считают драйвером эффективности бизнеса, не могу обойти стороной стек для реализации Платформы машинного обучения. Не буду рассказывать об MLFlow и JupyterHub, на эту тему много материала на Хабр, но уделю внимание мощному open source инструменту для работы с локальными и внешними LLM моделями - Open WebUI. Довольно важно, что он использует ту же инфраструктуру, что и Data-платформа, что существенно экономит ресурсы и облегчает управление доступами.
Главные преимущества Open WebUI:
1.Полная приватность
Данные не уходят в облако (в отличие от ChatGPT или Claude, или других);
Можно работать с конфиденциальной информацией без риска утечек.
2.Простота использования
Интуитивный веб-интерфейс, похожий на ChatGPT;
Поддержка Markdown, темной/светлой темы, удобного управления чатами;
Встроенный API обеспечивает легкую имплементацию в другие инструменты.
3.On premise запуск
Работает на нашем кластере Kubernetes;
Не требует оплаты подписок (как GPT-4 Turbo или Claude Pro).
4.Поддержка множества моделей
Совместимость с Ollama, vLLM, LM Studio и другими бэкендами;
Можно быстро переключаться между моделями (например, Llama 3 для сложных задач и Phi-3 для быстрых ответов);
Служит единым шлюзом для разных моделей.
5.Расширенные функции
Загрузка файлов (PDF, DOCX, TXT) для анализа текста. В нашем случае персистентные данные находятся в корпоративном S3;
RAG (Retrieval-Augmented Generation) — подключение собственных данных для более точных ответов;
Плагины (например, для генерации изображений через Stable Diffusion).
6.Гибкость настройки
Поддержка пользовательских промптов и системных инструкций;
Возможность тонкой настройки интерфейса под свои нужды;
Централизованная система аутентификации SSO (Keycloak) с возможностью настройки RBAC
Платформа качества данных
И, конечно же, хочется рассказать о реализации Платформы качества данных, продукт занимает особое место в нашей экосистеме и заслуживает внимания. Его архитектура представлена на схеме ниже.

Пайплайны автотестов качества данных оркестрируются с помощью Airflow через специализированные операторы, такие как KubernetesPodOperator, и развертываются изолированно в Kubernetes. Тесты организованы по системам и сгруппированы в отдельные Airflow DAGs. При этом для каждой системы предусмотрено два типа DAG:
Тестирование сырого слоя (stage layer);
Тестирование остальных слоев (ODS, DDS, CDM).
Такое разделение обусловлено спецификой тестов для сырого слоя, где основное внимание уделяется проверке корректности загрузки данных и их соответствия системе-источнику. Это включает проверку количества строк, минимальных и максимальных значений ключевых атрибутов, а также количества NULL-значений и ряда других метрик.
В большинстве DAGs используется сенсор, отслеживающий завершение соответствующих DAGs загрузки или формирования слоев. Как только необходимые данные загружены в хранилище или обновление слоя завершено, запускается DAG тестирования.
Конфигурации всех тестов, тестируемых таблиц и другая метаинформация вносится специалистами DQ и аналитиками через UI специализированного сервиса. Цель сервиса - предоставление возможности конфигурации десятков тысяч тестов в удобном формате, а также валидация вносимых данных для предотвращения дальнейших ошибок. В перспективе дальнейшего развития этот же сервис будет предоставлять отчетность по результатам тестирования. В качестве бэкенд базы данных используется так называемый DQ Metastore на базе PostgreSQL.
В связке со специальным сервисом в качестве основного каталога данных используется Data Hub, где аналитики вешают различные тэги на соответствующие таблицы. В дальнейшем, с заданной периодичностью тэги маппятся с соответствующими им тестами и отправляются в DQ Metastore. Таким образом, DQ Metastore выступает единой точной для получения информации о тестах и таблицах для всех компонентов платформы.
При запуске DAG происходит обращение к конфигурациям тестов, хранящимся в DQ Metastore и GitLab-репозитории. На основе этих конфигураций DAG динамически перестраивается: добавляются или удаляются задачи, изменяются приоритеты их выполнения и другие параметры.
Внутри DAG для каждой тестируемой таблицы создается отдельная задача в Airflow. Для каждой такой задачи генерируются динамическая задача (Dynamic Task), каждая из которых соответствует одному тесту. Такой подход позволяет детально управлять запуском тестов, обеспечивает их изоляцию друг от друга, дает возможность перезапуска отдельных тестов для конкретных таблиц и экономии ресурсов в случае перезапуска.
Исходники тестов упакованы в docker-образы. Каждый образ содержит в себе всё необходимое окружение для тестирования, исходники и зависимости.
Для выполнения логики тестов используются два основных движка: DuckDB и Trino. Благодаря этому выбору мы минимизировали время, затрачиваемое на запуск Spark сессий, и достигли максимальной изоляции процессов между собой.
Собранные из мастер-систем метрики и результаты тестов мелкими транзакциями записываются в DQ Metastore. После завершения выполнения тестов каждый DAG формирует инкремент собранных данных, записывает его в Iceberg таблицы с сохранением историчности в разрезе дней, а также, агрегирует данные и отправляет отчет по электронной почте дежурным DQ инженерам, специалистам и аналитикам.
Хочется верить, что эта статья оказалась для вас полезной и вдохновляющей. Мне было важно показать, как опыт и экспертиза команды данных могут превратиться в мощный платформенный продукт, который помогает бизнесу расти и меняться. Это не просто история про технологии — это про людей, идеи и стремление к лучшему. Спасибо моей команде — вы те, кто делает невозможное возможным!