Несколько лет назад наш корпоративный слой данных жил на проприетарных технологиях. Данных было много, а основная СУБД — MPP-система Sybase IQ — долго не обновлялась. Мы регулярно сталкивались с тем, что у кластера «падали» ноды, каталог базы повреждался, порой даже терялись данные, а вендор не спешил выпускать исправления или даже признавать проблему. ETL-процессы работали через IBM DataStage, который также перестал развиваться. Все решения были закрыты, и мы не могли влиять на их улучшение. Vendor lock-in означает, что вы зависите от поставщика: если вендор не поддерживает нужные возможности, развитие замедляется, а долгоживущие ошибки остаются нерешенными. Такое положение становилось критичным.

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

В этой статье расскажу о том, как мы перешли с проприетарных ETL-инструментов на open-source на базе dbt, какие проблемы решали по ходу внедрения, и как построили экосистему вокруг dbt для автоматизации рутинных задач.

Зачем вообще менять?

Со старой платформой у нас было несколько проблем:

  • Зависимость от вендора. Проприетарные базы и ETL — это дорого. Мы столкнулись с классическим vendor lock-in: лицензии и сопровождение стоили миллионы рублей в год, а развитие тормозилось из-за негибкости поставщика.

  • Устаревшие технологии и нестабильность. Sybase IQ и DataStage давно не получали существенных обновлений. Их процессами сложно было управлять, интеграция с современными СУБД (Greenplum, ClickHouse, Impala) требовала постоянных костылей. Все это сопровождалось периодическими «падениями» базы, а иногда даже потерей данных. Отдельные разработчики тратили больше времени на стабилизацию работы, чем на построение витрин.

  • Сложные процессы. ETL строился на асинхронных вызовах и семафорах, что было сложно сопровождать; в тестовых средах возникали конфликты, а изменения схемы приходилось делать вручную. Настроить CI/CD и автоматические тесты для такой архитектуры было почти невозможно.

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

Кроме того open-source-продукты позволяют свободно использовать, модифицировать и распространять код, что делает такие решения гибкими и экономически эффективными. 

Как выбрать новый инструментарий

Когда мы решили уходить от проприетарной платформы, нужно было подобрать два ключевых компонента: средство трансформации и средство оркестрации

До миграции наша банковская платформа уже имела несколько open-source-MPP-движков: Greenplum, Apache Impala, Apache Spark. Однако ни один из них не решал задачу «запускайте один и тот же бизнес-SELECT в разных СУБД» — это просто СУБД или вычислительные движки, а не инструменты описания и контроля трансформаций. 

Мы не хотели привязываться к конкретной базе: в каких-то проектах удобен Greenplum, в других — Impala или ClickHouse, а завтра может появиться что-то еще. Поэтому важным требованием стало наличие инструмента, который генерирует SQL-код независимо от конкретной СУБД и тем самым позволяет описывать трансформации один раз, выполняя их на любой поддерживаемой базе. 

Трансформация

На рынке множество решений, но большинство из них либо требуют глубоких инженерных навыков, либо жестко привязаны к конкретным стекам: 

  • Apache Spark — популярный движок обработки больших данных, который предоставляет несколько способов описания преобразований. Благодаря наличию модуля Spark SQL он подходит аналитикам, которые могут работать с ним будто с обычной СУБД, с помощью привычных SQL-запросов. Однако Spark сам по себе не концентрирует внимание на бизнес-логике, не помогает описывать модели единым и однозначным путем и собирать их воедино в структурированный проект.

  • Talend, Pentaho и другие классические ETL-платформы. Это мощные визуальные инструменты, но они дорогие и закрытые. Легаси-решения вроде Talend и Informatica плохо подходят к современным требованиям: они не работают с неструктурированными данными, требуют дорогостоящих лицензий и мощных серверов, а отсутствие автоматизации заставляет команды тратить 80% времени на ручное сопровождение и устранение ошибок.

  • Dataform (Google) — управляется Google и тесно интегрирован с BigQuery, который работает в облаке и не «приземлен» в России. К сожалению, в нашем случае облачные решения неприменимы.

По совокупности критериев мы выбрали dbt (есть еще его прямой конкурент — SqlMesh, и, возможно, мы присмотримся к нему в будущем, но на момент нашего старта он был сыроват). dbt позволяет аналитикам описывать сложную логику на привычном SQL, что снижает порог входа. Но главное — dbt обеспечивает независимость от СУБД: он генерирует код под конкретную базу (Greenplum, ClickHouse и т. д.), решая проблему с мультиплатформенностью. 

Инструмент предоставляет встроенные возможности для тестирования, документирования и версионирования кода трансформаций. При этом функциональность можно расширять через макросы и пакеты, не трогая основной код инструмента. И наконец, вокруг dbt сложилась богатая экосистема с большим количеством полезных библиотек от сообщества (например, dbt-utils, dbt-expectations), которые заметно ускоряют разработку и закрывают типовые задачи.

Оркестрация 

Для управления процессами трансформации нужен оркестратор. Вот что мы рассматривали: 

  • Prefect, Dagster — относительно новые инструменты с упором на Python и динамические пайплайны. Они предлагают современные подходы и удобный developer experience, но на момент нашего выбора их экосистема была небольшой, а интеграции с dbt не так хорошо отработаны.

  • Luigi — оркестратор от Spotify, но он уже устарел и имеет ограниченную функциональность по сравнению с более современными решениями.

  • Airflow — самый «зрелый». Его поддерживает Apache Software Foundation, у него огромное сообщество с готовыми решениями типовых задач и проверенные интеграции с dbt.

Выбор пал на Airflow. Он надежный, определение пайплайнов в виде кода на Python (DAGs) дает полный контроль над логикой и зависимостями, а готовые интеграции, включая нативную поддержку для запуска задач dbt, позволяют быстро запустить процесс. В итоге связка dbt + Airflow обеспечила нам свободу выбора технологий, SQL-подход для аналитиков и мощную экосистему для дальнейшего развития.

Что не так с «ванильным» dbt

Хотя dbt — действительно мощный инструмент, для построения DWH в реальном enterprise-проекте многое хочется кастомизировать, чтобы работало немного иначе.

  • Работа со схемой. Из коробки dbt incremental не имеет backfill. Добавление колонки в инкрементальную модель обычно приводит к полной перезагрузке таблицы. Это неприемлемо для таблиц на десятки терабайт. Также хорошо бы типы колонок и constraints протягивать «как их запроектировали» для дальнейших автоматических контролей. На тот момент dbt такого не поддерживал. Кроме того, есть особенности применения изменений в различных СУБД, которые хотелось обыграть отдельно.

  • Поддержка различных СУБД. В нашем же стеке есть Greenplum с партиционированием, ClickHouse с шардированием и ReplicatedMergeTree, Impala и Spark с файлами iceberg в S3. Адаптеры не всегда актуальны и поддерживают современные версии СУБД и их особенности для оптимальной работы. 

  • Контроль доступа. В dbt нам не хватило кроссплатформенного ролевого механизма разграничения прав на уровне моделей и схем. Настраиваться все должно простым назначением роли.

  • Рутинные действия. Разработчики вынуждены тратить непропорционально много времени на инфраструктурную рутину вместо бизнес-логики. Для каждой модели пишется инкрементальная загрузка, поддерживается историчность (SCD 2–4), генерируются суррогатные ключи. В результате фокус внимания смещается с бизнес-ценности на техническую обвязку. К тому же такой зоопарк тяжело поддерживать. Нужно бы стандартизировать.

  • Оркестрация и масштабирование. Граф из тысяч моделей превращается в спагетти. При стандартном подходе DAG Airflow отображает все модели одним длинным списком. Компиляция большого проекта занимает минуты и даже часы. Пришлось решить, как правильно разделять и оркестрировать проекты.

  • Штатные материализации. Для каждой СУБД есть свои особенности применения изменений update / insert / merge / insert overwrite. Хотелось написать модели так, чтобы не переписывать их под каждую версию СУБД. И чтобы можно было подкрутить настройки своей материализации, не трогая бизнес-код, в случае, когда найдется более оптимальный подход.

  • Проверки типов. Есть требование гораздо более гибко проверять и контролировать типы данных, constraints, дубли и т. д. В нашем случае нужны поколоночные настройки поведения, возможная корректировка данных, ведение журнала ошибок для последующего разбора.

Что мы сделали: экосистема вокруг DBT

Мы решили, что dbt core — это ядро, и не стали форкать или модифицировать его. Теперь можно безболезненно обновляться и пользоваться всеми библиотеками и плагинами, которые развивает сообщество. Весь дополнительный функционал реализован поверх dbt — через макросы, материализации и самописные Python-утилиты. Поверх ядра построили целую экосистему, которая автоматизирует рутинные задачи.

Кастомные материализации и макросы

Главная идея — превратить тяжелый ETL-код в low-code: разработчик пишет лишь бизнес-SELECT, а весь «служебный» код делает материалиация. Это позволяет аналитику или дата-инженеру сосредоточиться на смысле данных, а не на инфраструктуре.

Наши материализации берут на себя всю техническую рутину:

  • Автоматическое управление схемой. Мы реализовали функционал, который анализирует различие между метаданными модели (schema.yml) и базой, выбирает стратегию (добавить колонку и заполнить ее в пайплайне, выдать ошибку несоответствия метаданных, пересоздать таблицу по метаданным) и выполняет необходимый DDL при заданных заранее условиях и настройках в пайплайне CI/CD, — ровно то же делал разработчик при тестировании функционала. Т. к. DDL полностью генерируется автоматом — исключен человеческий фактор. Если же по каким-то причинам база поменяется, а модель нет, — Dag загрузки модели будет падать с ошибкой, не позволив испортить данные.

  • Low-code. Разработчик пишет только SELECT, а функционал сам формирует набор ключевых полей для инкрементальной загрузки, поддерживает разные стратегии инкремента и позволяет вести историю по модели SCD 4. Так же генерятся суррогаты, пишутся логи, инкремент режется на батчи, автоматически поддерживаются техполя. И все это стандартизировано для 2000+ моделей.

  • Встроенный контроль качества. Проверка на дубли, контроль ссылочной целостности (foreign keys) и приведение типов выполняются автоматически. Для каждой строки формируется «тракт» данных — идентификатор, по которому можно отследить ее до источника или приемника.

  • Мультиплатформенность. Одна и та же модель работает под Greenplum, ClickHouse и Spark благодаря адаптивной генерации SQL.

  • Объектные права и безопасность. Материализация создает таблицы и представления с корректными привилегиями для ролей разработчиков, аналитиков, сервисов и прочих.

  • Инкрементальная репликация в ClickHouse. dbt может выгружать готовые витрины через EXTERNAL TABLE и автоматически инкрементально реплицировать их в ClickHouse без ручного кода.

  • Мониторинг. Мы ведем метабазу запусков потабличных загрузок. В Grafana доступна вся информация о data-freshness, SLA, времени готовности витрин, ошибках при их формировании, техническом качестве данных. Все группируется по тегам моделей, давая возможность проверить готовность тех или иных витрин данных, системы-источника и т. д.

  • Специфические настройки для баз. Для GreenPlum автоматически поддерживаем партиции, для Impala — хинты, разные типы файлов, merge / insert overwrite и еще множество кастомизаций.

Оркестратор и генератор DAG’ов

Чтобы не писать DAG'и для Airflow вручную (при большом количестве моделей это довольно больно), мы разработали утилиту DagGenerator. В описании модели в schema.yml архитектор задает теги (например, source_system:CRM, domain:Loans) — эти теги определяют, в какой DAG попадет модель.

DagGenerator читает настройки из YAML-файла и создает DAG'и с расписанием и зависимостями, отбирая модели по тегам. Добавление новой модели в DAG происходит динамически, по тегу. Это исключает ошибки из-за человеческого фактора и упрощает поддержку. Кроме того, мы добавили в утилиту функционал построения зависимостей не только по ref-ссылкам, но и по внешним ключам моделей, описанных в их метаданных.

Утилиты и инструменты

  • Metadata Manager. Это универсальная утилита чтения и записи метаданных. Она подключается к любой СУБД, считывает структуру таблиц (колонки, типы, PK, FK) и формирует из этого schema.yaml для dbt. Развертывание проекта на «чистой» базе сводится к запуску dbt.

  • Утилита для выгрузки YAML. Архитектор проектирует модель в CASE-инструменте, нажимает кнопку — генерируются schema.yaml. Скрипт выгружает структуру модели, избавляя от ручного копирования.

  • Генератор шаблонных моделей. Отдельная утилита, которая создает простые dbt-модели и YAML-описания по шаблону. Ускоряет создание однотипных витрин и стандартизирует их структуру.

  • Мониторинг и метрики. Логи выполнения сохраняются в ClickHouse, а дашборды строятся в Grafana. Мы видим, сколько времени работала каждая модель и каждый ее шаг, сколько записей прошло / не прошло проверки и где произошел сбой. Также мы контролируем SLA витрин и систем.

  • Интеграция с data lineage. Manifest и SQL-код автоматически отправляются в Open Metadata; таким образом мы получаем колоночный lineage и всю структуру нашей базы с описаниями и прототипами.

Расширения 

Мы старались использовать лучшее, что предлагает сообщество, и дополнили наш стек следующими решениями:

  • dbt-utils. Фундаментальный набор макросов и тестов (генераторы SQL, surrogate_key, универсальные тесты).

  • dbt-expectations. Библиотека тестов, вдохновленная Great Expectations, для богатых проверок данных (типы, диапазоны, количество колонок) в формате YAML.

  • dbt-external-tables. Пакет для декларативного описания внешних таблиц (например, файлов в S3 или HDFS) прямо в dbt.

  • Elementary. Расширение, которое отправляет отчеты о тестах в Slack или почтой и автоматически формирует отчеты о качестве данных.

  • Astronomer Cosmos. Библиотека, упрощающая интеграцию dbt и Airflow. Она разбивает большую задачу на несколько TaskGroup и улучшает визуализацию.

  • Плагины для IDE. Расширения для VS Code и JetBrains DataSpell, которые подсвечивают макросы dbt и позволяют запускать модели прямо из редактора.

Процесс и роли

Технологии — только половина успеха. Мы детально прописали процесс разработки и роли в нем.

  1. Аналитик: собирает требования, пишет прототип на SQL и оформляет бизнес-описание.

  2. Архитектор: проектирует модель в CASE-инструменте и выгружает YAML-описание.

  3. Разработчик: на основе прототипа и YAML пишет конечную модель в dbt. Ему не нужно думать об инкрементах — все делает материализация. 

  4. Тестировщик + Аналитик: проверяют модель и пишут тесты (разовые для проверки доработки или регрессионные для постоянного запуска по модели в случае изменений).

  5. Dev-ops. CI/CD-конвейер: запускает пайплайн. Решение конфликтов, компиляция dbt, запуск тестов и линтеров для SQL и YAML. После этого — генерация документации, обновление DAG’ов и деплой.

  6. Поддержка. Продакшен — финальный шаг. Новая модель попадает в прод, а мониторинг (Grafana + Prometheus) наблюдает за ее работой вместе с коллегами из технической поддержки.

Благодаря такому процессу у каждой активности есть владелец, прозрачные точки контроля и автоматические проверки.

Что на выходе

Благодаря шаблонизации, low-code-разработке, автотестам и автоматическому управлению схемой (DDL) количество ошибок сократилось примерно вдвое. Настолько же увеличилась скорость внедрения доработок: разработчики теперь фокусируются на бизнес-логике, а не на технической рутине.

Покрытие тестами выросло до 85%, ошибки перехватываются еще в процессе CI/CD, не доходя до прода. 

Платформа легко масштабируется: сейчас в репозитории более 2000 моделей, а в команде работает более 50 разработчиков. Персональные песочницы и динамические DAG'и позволяют им работать параллельно без конфликтов.

Экономический эффект: стоимость лицензий на проприетарные продукты сократилась в разы. Переход на open-source дал возможность развивать платформу самостоятельно, не завися от roadmap-вендора.

Наконец, платформа стала прозрачной для бизнеса. Благодаря встроенной документации dbt и интеграции с Open Metadata мы можем показать бизнес-пользователям путь каждого показателя в витрине данных, сообщить время его выгрузки из источника (data-freshness) или спрогнозировать время загрузки. 

Заключение

Если вы задумываетесь о миграции с проприетарных систем, присмотритесь к dbt. Сообщество активно развивается и предлагает готовые пакеты, которые можно использовать в существующем виде или расширять под свои задачи. Менять привычный стек непросто, но open-source дает возможность строить систему, которая работает именно так, как нужно вам, а не так, как решил вендор. 

Комментарии (0)