Эта статья — не гайд и не туториал, а честный рассказ о том, как мы строили платформу данных на open-source и что из этого вышло. С граблями, компромиссами и реальными цифрами.
Когда я пришёл на текущее место работы, вся аналитика компании держалась на Google Таблицах и Looker Studio. Менеджеры собирали данные вручную, копировали цифры из одной таблички в другую, и раз в две недели кто-то делал "отчёт" — по сути, скриншот из Looker Studio для презентации. Никто не понимал, откуда берутся цифры, никто не доверял им на 100%, и каждое "а почему тут другое число?" превращалось в час переписки.
Знакомо? Думаю, в 80% компаний среднего размера аналитика выглядит именно так. И это работает — до определённого момента. Кстати, некоторые результаты у нас до сих пор делаются так же — но уже не в том объёме, как раньше. Наш момент настал, когда количество источников данных выросло, а решения нужно было принимать быстрее.
Эта статья — рассказ о нашем пути от хаоса к Data Lakehouse, полностью на open-source инструментах. Без облачных провайдеров, без лицензий за $50k/год. Со всеми проблемами, компромиссами и выводами.
Начало: Google Таблицы + Looker Studio
Google Таблицы — идеальный инструмент для старта. Бесплатно, понятно всем, коллаборация в реальном времени. Looker Studio (бывший Data Studio) — бесплатная BI-система, которая подключается к Google Sheets и показывает графики.
Проблемы начались, когда:
- Объём данных вырос. Google Sheets имеет лимит в 10 млн ячеек. Когда у тебя 15+ источников данных, ты достигаешь этого лимита быстрее, чем кажется.
- Looker Studio тормозил. Дашборды, тянущие данные из 5 разных таблиц, загружались минутами. А если кто-то в этот момент редактирует исходную таблицу — вообще рассыпались.
- Слабое версионирование. Да, у Google Sheets есть история изменений — но кто ей реально пользуется? Кто-то удалил строку из таблицы, а ты замечаешь через неделю. Искать в ленте ревизий на 500 изменений, кто и когда это сделал — отдельное удовольствие.
- Формулы как спагетти. IMPORTRANGE поверх IMPORTRANGE поверх VLOOKUP из другой таблицы. Одно изменение — и каскад ошибок.
Стало понятно: нужна нормальная инфраструктура данных.
Первая база: MSSQL
Почему MSSQL, а не сразу PostgreSQL? Банально — опыт. На предыдущей работе я работал с SQL Server, знал его сильные и слабые стороны, мог быстро поднять и настроить.
До появления нормальной БД выгрузки данных можно было ждать неделями. Буквально: "можешь достать эти данные?" — "пиши таск, возьму в работу". Потом правки, потом ещё правки, и так карусель крутилась. Когда появился MSSQL, время от запроса до ответа сократилось до часов, а потом — до минут.
Тогда же появился и Airbyte — для переноса данных из других баз в MSSQL. Работало это неплохо до определённого момента, пока объёмы и количество источников не выросли.
MSSQL vs PostgreSQL:
| Критерий | MSSQL | PostgreSQL |
|---|---|---|
| Лицензия | Express бесплатно (10 ГБ лимит), полная — платная | Полностью бесплатный |
| Экосистема | Windows-центричная, SSMS | Кроссплатформенная, pgAdmin, DBeaver |
| JSON-поддержка | Базовая | Нативная, JSONB |
| Репликация | AlwaysOn (Enterprise) | Встроенная, streaming |
| Сообщество | Меньше, корпоративное | Огромное, активное |
MSSQL хорошо работал на старте, но со временем стало понятно, что PostgreSQL подходит лучше — бесплатный, открытый, с лучшей поддержкой JSON и более широкой экосистемой.
PostgreSQL: рабочая лошадка
Потом мы подняли PostgreSQL. Сейчас туда пишет Airbyte, и если есть потребность в классических реляционных данных — пишем тоже туда. PG стал нашей default базой для структурированных данных.
PostgreSQL vs MySQL:
| Критерий | PostgreSQL | MySQL |
|---|---|---|
| Стандарты SQL | Строгое соблюдение | Свободная трактовка |
| Сложные запросы | CTE, оконные функции, LATERAL | Базовая поддержка CTE |
| Расширяемость | Огромная (PostGIS, pgvector, ...) | Ограниченная |
| Репликация | Logical + physical | Row-based, Group Replication |
| Для аналитики | Хорошо | Средне |
MySQL (а точнее MariaDB) тоже есть в нашем стеке — на нём работают продакшн-сервисы компании. Но для новых аналитических задач мы всегда выбираем PG.
MongoDB: для специфических задач
MongoDB появился уже после того, как мы подняли Dremio — под конкретные кейсы: парсинг Facebook Graph API, данные из социальных сетей, где структура ответов может меняться с каждым запросом. Когда API возвращает вложенный JSON с произвольной глубиной — реляционная БД начинает страдать. MongoDB тут чувствует себя как рыба в воде.
Поскольку Dremio уже работал, оверхед от ещё одного источника был минимальный — подключили MongoDB как source, и ко всем базам (MSSQL, PostgreSQL, MongoDB) пишутся одинаковые SQL-запросы через Dremio. Один язык, один интерфейс.
MongoDB vs PostgreSQL (JSONB):
| Критерий | MongoDB | PostgreSQL JSONB |
|---|---|---|
| Гибкость схемы | Полная, schemaless | JSON в реляционных рамках |
| Вложенные документы | Нативно | Нужны JSONB-операторы |
| Агрегации | Aggregation Pipeline | SQL |
| Масштабирование | Sharding из коробки | Citus, партиционирование |
| Для парсинга API | Идеально | Приемлемо |
Data Lakehouse: зачем и что это
Итак, у нас уже было несколько баз: MSSQL, PostgreSQL, MongoDB, плюс данные в Google Sheets, файлы, API. Классический хаос. Каждый источник — свой формат, свой доступ, свои проблемы.
Data Lakehouse — это архитектура, которая объединяет преимущества Data Lake (хранение сырых данных дёшево и масштабируемо) с Data Warehouse (SQL-запросы, ACID-транзакции, схемы). И мы решили построить его полностью на open-source.
Наш стек:
- MinIO — объектное хранилище, совместимое с S3 API. Наш Data Lake
- Apache Iceberg — формат таблиц с поддержкой ACID, time travel, schema evolution
- Nessie — каталог данных с Git-подобным версионированием
- Dremio — SQL-движок для запросов ко всему этому
MinIO: свой S3
MinIO — это, по сути, self-hosted Amazon S3. Объектное хранилище с S3-совместимым API. Всё, что умеет работать с S3 — работает с MinIO.
MinIO vs Amazon S3 vs Azure Blob:
| Критерий | MinIO | Amazon S3 | Azure Blob |
|---|---|---|---|
| Стоимость | Бесплатно (self-hosted) | Pay-per-use | Pay-per-use |
| Контроль | Полный | Ограниченный | Ограниченный |
| S3 API | Совместимый | Оригинал | Свой API + S3 adaptor |
| Масштабирование | Ручное | Автоматическое | Автоматическое |
| Для нас | Идеально | Дорого для объёмов | Не нужен |
Для нашего случая MinIO — идеальный выбор. Мы контролируем железо, нет счетов за трафик, и всё работает так же, как если бы мы были на AWS.
Apache Iceberg: таблицы, которые не ломаются
Iceberg — это формат таблиц поверх объектного хранилища. По сути, он даёт возможность работать с файлами в MinIO так, будто это таблицы в базе данных. С ACID-транзакциями, с версионированием, с эволюцией схемы.
Iceberg vs Delta Lake vs Apache Hudi:
| Критерий | Iceberg | Delta Lake | Hudi |
|---|---|---|---|
| Основатель | Netflix → Apache | Databricks | Uber → Apache |
| Vendor lock-in | Никакого | Тесно с Databricks | Меньший |
| Поддержка движков | Spark, Flink, Dremio, Trino | Spark, Databricks | Spark, Flink |
| Time Travel | Да | Да | Да |
| Schema Evolution | Отличная | Хорошая | Хорошая |
| Партиционирование | Hidden partitioning | Явное | Явное |
| Сообщество | Растёт быстро | Самое большое | Среднее |
Iceberg победил потому, что он наиболее vendor-neutral. Мы не хотим привязываться к Databricks или кому-то ещё.
Nessie: Git для данных
Nessie — это каталог данных, который работает как Git. Ты можешь создавать бранчи, делать коммиты, мерджить изменения. Для данных. Это звучит как фантастика, но это реально работает.
Nessie vs Hive Metastore vs AWS Glue vs LakeFS:
| Критерий | Nessie | Hive Metastore | AWS Glue | LakeFS |
|---|---|---|---|---|
| Версионирование | Git-like (бранчи, коммиты) | Нет | Нет | Git-like (бранчи, коммиты) |
| Self-hosted | Да | Да | Нет (AWS only) | Да |
| Iceberg-поддержка | Нативная | Через плагин | Да | Через S3 gateway |
| Сложность | Низкая | Высокая (Hadoop) | Средняя | Низкая |
| Стоимость | Бесплатно | Бесплатно | Pay-per-use | Бесплатно (OSS) |
| Dremio-интеграция | Встроенная, нативная | Нет | Нет | Нет |
Почему Nessie, а не LakeFS? LakeFS — отличный инструмент, который версионирует данные на уровне объектного хранилища (как Git для файлов в S3). Но Nessie работает на уровне каталога — он версионирует метаданные таблиц, а не сами файлы. Для Iceberg-таблиц это эффективнее. А ещё Nessie — дефолтный каталог во всех официальных туториалах Dremio. То есть интеграция работает из коробки, без танцев с бубном.
Nessie — это то, что держит нашу инфраструктуру вместе. Если данные в Nessie целы — всё остальное можно восстановить.
Dremio: SQL-движок, который объединяет всё
Dremio — сердце нашего Lakehouse. Это SQL-движок, который подключается ко всем нашим источникам: MinIO через Iceberg/Nessie, PostgreSQL, MSSQL, MongoDB — и позволяет делать SQL-запросы ко всему этому как к одной базе.
Dremio vs Trino vs Apache Spark SQL vs Databricks:
| Критерий | Dremio | Trino (Starburst) | Spark SQL | Databricks |
|---|---|---|---|---|
| UI | Удобный веб-интерфейс | Минимальный | Нет | Полноценный |
| Iceberg-поддержка | Нативная, отличная | Нативная (отличная) | Через коннектор | Нативная (Delta) |
| Nessie-интеграция | Встроенная | Плагин | Плагин | Нет |
| Self-hosted | Community Edition | Да | Да | Нет (SaaS) |
| Оптимизация | Reflections, Columnar Cloud Cache | Кеширование | RDD кеш | Photon |
| Простота | Высокая | Средняя | Низкая | Высокая |
| Ролевая модель | Базовая (все админы в CE) | Полноценная | Через Ranger | Полноценная |
90% наших таблиц в Dremio — это view. Мы сознательно минимизируем копирование данных. Вместо того чтобы дублировать данные в отдельные таблицы, мы создаём view поверх источников, а для ускорения — добавляем Reflections (материализованные агрегаты, которые Dremio создаёт и обновляет автоматически). Это позволяет держать минимум физических копий: агрегированные данные хранятся как Reflections, неагрегированные — как view с другим представлением. Запросы к view выполняются быстро за счёт Reflections, а данные всегда актуальны, потому что view читают напрямую из источника.
Главная проблема Dremio Community Edition — и это касается многих OSS-продуктов — отсутствие нормального управления ролями. В Community Edition все пользователи — админы. Ты не можешь ограничить доступ к определённым датасетам или дать read-only права. Для маленькой команды это терпимо, но с ростом — болит.
Пока доступ к Dremio у нас держится на доверии — команда небольшая, все понимают, куда можно лезть, а куда нет. Частично мы решили эту проблему через MCP-шлюз, о котором расскажу ниже — он добавляет ACL-слой поверх Dremio и контролирует, кто к чему имеет доступ. Но для прямых подключений к Dremio проблема остаётся — это один из тех компромиссов, с которыми живёшь в OSS: функционал есть, а access control — достраивай сам.
Это, кстати, типичная проблема OSS: бесплатная версия даёт 80% функциональности, но тот критический 20% (security, RBAC, audit log) — в платной версии. И ты или платишь, или живёшь с компромиссами — или строишь обходные решения.
Кейс: обновление Dremio, которое пошло не так
Однажды мы решили обновить Dremio до новой версии. Dremio у нас крутится в Docker Compose, поэтому процесс должен был быть простым: поменять тег образа, docker compose up -d, готово. Но что-то пошло не так — после запуска Dremio не видел половину датасетов. Внутренние метаданные повредились при миграции. В логах — стена ошибок без нормального описания проблемы. Что именно сломалось — непонятно. Мы потратили время на дебаг, но в итоге решили снести всё с нуля и поднять чистую инсталляцию.
Момент паники? Да, секунд на тридцать. А потом — "стоп, у нас же Nessie". Все наши Iceberg-таблицы, их схема, история изменений — всё хранится в Nessie, а не в Dremio. Dremio — это лишь движок для запросов. Мы подняли чистый Dremio, переподключили Nessie-каталог, и все данные вернулись. А все view у нас были описаны в dbt — одна команда dbt run, и все view развернулись обратно. За час всё работало как раньше.
Это был момент, когда архитектурное решение разделить compute (Dremio) и catalog (Nessie) оправдало себя на 200%. Если бы мы полагались на внутренний каталог Dremio — восстановление заняло бы дни, а не час.
Кейс: DELETE без WHERE, или как Nessie спас за 2 секунды
Есть классическая шутка про DELETE FROM table без WHERE. Так вот, у нас это была не шутка.
Однажды я запустил DELETE-запрос на Iceberg-таблицу и забыл добавить условие. Просто DELETE FROM ... — и всё. Таблица очистилась мгновенно. Сердце остановилось на секунду, руки похолодели — там были данные, которые собирались неделями.
Если бы это был обычный PostgreSQL или MSSQL — это был бы конец. Бэкап? Может, вчерашний. А данные за сегодня — потеряны. В лучшем случае — часы на восстановление из бэкапа, проверку целостности, ручное доливание свежих данных.
Но у нас Nessie. А Nessie — это Git для данных. Каждое изменение — это коммит. Каждый коммит имеет хеш. Я просто откатил бранч до предыдущего коммита — и через 2 секунды все данные были на месте. Как будто ничего не произошло.
Две. Секунды.
Кстати, то же самое случалось и с MSSQL — DELETE без WHERE на продакшн-таблице. Только там Nessie не было. Свежего бэкапа — тоже. Пришлось восстанавливать всё с нуля: поднимать старый бэкап, сравнивать с продакшном, вручную доливать данные, которые успели накопиться. Это заняло не секунды, а часы. И нервов — на месяц вперёд.
Это тот момент, когда понимаешь, почему time travel и версионирование данных — это не маркетинговые слова, а реальная страховка от человеческих ошибок. Мы все делаем ошибки. Вопрос лишь в том, сколько времени нужно на восстановление. С Nessie ответ — секунды. С MSSQL — часы и седые волосы.
Airbyte: ингест данных
Airbyte — наш инструмент для извлечения данных из различных источников. Сейчас он тянет таблички из Google Sheets и пишет в PostgreSQL. Иногда используем no-code connector builder — когда лень писать asset в Dagster, а нужно быстро подключить новый источник.
Airbyte OSS vs Fivetran vs Meltano vs dlt:
| Критерий | Airbyte OSS | Fivetran | Meltano | dlt |
|---|---|---|---|---|
| Лицензия | Open-source | SaaS, платный | Open-source | Open-source |
| Количество коннекторов | 300+ | 400+ | 300+ (Singer) | Библиотека |
| UI | Веб-интерфейс | Веб-интерфейс | CLI | Код |
| No-code builder | Да | Нет | Нет | Нет |
| Self-hosted | Да | Нет | Да | Да (это библиотека) |
Проблемы Airbyte OSS, с которыми мы столкнулись:
- Ресурсоёмкость. Сейчас Airbyte отжирает 12 ГБ оперативки и толком ничего не делает. Планируем его дропнуть. Он тяжело справляется с большими объёмами данных — синхронизация может выполняться днями, и при этом никакой ошибки не будет. Просто тихо молотит.
- Нестабильность коннекторов. Некоторые community-коннекторы ломаются после обновлений. Синхронизация с Google Sheets время от времени падает без видимой причины и требует перезапуска.
- Сложный дебаг. Когда что-то падает — логи разбросаны по десятку Docker-контейнеров. Найти, что именно пошло не так, иногда занимает больше времени, чем сам фикс.
- Обновления. Каждое обновление Airbyte — это лотерея. Может пройти гладко, а может сломать коннекторы, которые работали месяцами.
Но при этом Airbyte всё равно лучший вариант для нас, потому что Fivetran стоит столько, что дешевле нанять ещё одного дата-инженера.
Dagster: оркестрация
Dagster — наш оркестратор. Он определяет, что, когда и в каком порядке запускается. Каждый pipeline — это набор assets, которые Dagster отслеживает, запускает по расписанию или по триггеру.
Dagster vs Apache Airflow vs Prefect vs Mage:
| Критерий | Dagster | Airflow | Prefect | Mage |
|---|---|---|---|---|
| Концепция | Software-defined assets | DAGs of tasks | Flows & tasks | Blocks & pipelines |
| UI | Современный, удобный | Функциональный, устаревший | Облачный | Notebook-style |
| Тестирование | Встроенное | Сложное | Среднее | Базовое |
| Типизация | Сильная (IO managers, types) | Слабая | Средняя | Слабая |
| dbt-интеграция | Нативная (dagster-dbt) | Через операторы | Через блоки | Базовая |
| Сложность | Средняя | Высокая | Низкая | Низкая |
Почему Dagster, а не Airflow? Потому что Airflow — это 2015 год. DAGs, operators, XCom — это всё работает, но ощущается как legacy. Dagster построен вокруг концепции assets — ты описываешь не "что запустить", а "какие данные нужно получить". Это фундаментально меняет подход.
Отдельно хочу отметить в Dagster механизм dependency injection — очень крутой и очень понятный. Почему-то вспоминаются студенческие годы и Dagger 2 под Android, где всё было максимально запутано. Тут — сразу всё ясно, всё на месте.
Ещё один плюс Dagster — нативная поддержка запуска Airbyte, Airflow и других инструментов. То есть если нужно мигрировать с другого оркестратора или интегрировать внешний тул — это делается на изи, без костылей.
dbt: трансформация
dbt — это трансформации. SQL-модели, которые превращают сырые данные в аналитические таблицы. dbt работает с Dremio через адаптер, и это позволяет нам строить модели поверх Iceberg-таблиц.
Важный нюанс: сейчас Dagster и dbt у нас не соединены. dbt запускается при пуше через GitLab CI/CD pipeline — обновил SQL-модель, сделал push, GitLab запускает dbt run против Dremio. Это работает, и насущной потребности интегрировать dbt в Dagster пока нет. Но планируем — это логичный следующий шаг к единой точке оркестрации.
На сегодняшний день наш dbt-проект — это 445 моделей, 848 тестов, 103 sources и 652 макроса. Это не просто SQL-файлы — это полноценная кодовая база с версионированием, code review и CI/CD.
Отдельный бонус: dbt генерирует документацию, которую мы заливаем в Dremio wiki с линком на dbt docs.
MCP-шлюз: AI-клиент для Dremio
Одна из самых интересных вещей в нашем стеке — MCP-сервер (Model Context Protocol), подключённый к Dremio. По сути, это шлюз, через который AI-ассистенты (Claude, Cursor, любой MCP-клиент) могут ходить в наш Lakehouse — делать SQL-запросы, читать метаданные таблиц, просматривать dbt-документацию.
Но главная фишка не в этом. Главная фишка — контроль доступа. Как я уже писал, Dremio Community Edition не имеет нормальной ролевой модели — все пользователи по сути админы. MCP-шлюз решает эту проблему: у него есть собственный ACL-слой, который контролирует, кто к каким датасетам имеет доступ. Каждый запрос от AI-клиента проходит через проверку прав — и если у тебя нет доступа к определённому пространству или таблице, ты его просто не увидишь.
То есть то, чего нет в самом Dremio, мы достроили на уровне шлюза. Это позволяет безопасно давать доступ к данным разным людям и AI-агентам — каждый видит только то, что ему разрешено.
dbt vs Dataform vs SQLMesh:
| Критерий | dbt | Dataform | SQLMesh |
|---|---|---|---|
| Сообщество | Огромное | Меньше (Google) | Растёт |
| Адаптеры | 30+ | BigQuery-центричный | 10+ |
| Версионирование | Git | Git | Git + автоматическое |
| Тестирование | Встроенное | Встроенное | Расширенное |
| Incremental | Стандартное | Стандартное | Продвинутое |
| Цена | Core бесплатный | Бесплатный (GCP) | Бесплатный |
Apache Superset: BI для всех
Looker Studio заменили на Apache Superset. Это BI-платформа, созданная в Airbnb и переданная в Apache Software Foundation. Подключается к любой SQL-базе — включая Dremio.
Superset vs Metabase vs Looker Studio vs Grafana:
| Критерий | Superset | Metabase | Looker Studio | Grafana |
|---|---|---|---|---|
| Лицензия | Apache 2.0 | AGPL / Commercial | Бесплатный (Google) | AGPL |
| SQL Lab | Полноценный | Есть, упрощённый | Нет | Explore |
| Визуализации | 50+ типов | 15+ | 30+ | Для метрик |
| Self-hosted | Да | Да | Нет | Да |
| Кастомизация | Высокая | Средняя | Низкая | Высокая |
| Ролевая модель | Полная (RBAC) | Базовая | Google accounts | Org/Team |
| Для аналитики | Идеально | Хорошо | Базово | Для мониторинга |
Superset муторно настраивать — первичный setup это отдельный квест, UI иногда глючит, некоторые графики требуют танцев с бубном, а документация... скажем так, она существует. Но когда всё настроено — он классный. Для бесплатного продукта — это лучший вариант BI, который мы нашли.
Проблема OSS: где заканчивается "бесплатно"
Самый большой миф об open-source — "это бесплатно". Да, лицензии бесплатные. Но:
- Время на настройку. Каждый инструмент нужно поднять, настроить, заинтегрировать. Это недели работы.
- Отсутствие поддержки. Когда что-то ломается — ты сам. GitHub Issues, Stack Overflow, Discord — и молись, чтобы кто-то ответил.
- Ролевая модель. Как я уже говорил, в Dremio CE все — админы. В Airbyte OSS тоже не густо с правами. В Superset есть нормальный RBAC, но настроить его — отдельный квест.
- Обновления. Каждое обновление каждого компонента — это потенциальный breaking change. И никто тебе не гарантирует, что новая мажорная версия Airbyte будет совместима с твоим конфигом — мы это прочувствовали на себе при переходе на 2.0.
Но при этом — мы полностью контролируем свою инфраструктуру. Никакого vendor lock-in. Никаких неожиданных счетов от AWS. И самое важное — мы понимаем каждый компонент системы, потому что сами его настраивали.
Выводы
Наш путь от Google Sheets к Data Lakehouse занял около двух лет. Не потому что это сложно сделать за раз — а потому что каждый инструмент подключался по мере возникновения проблем и потребностей. Это был органический процесс с ошибками, откатами и "а давай попробуем вот это". Но сейчас у нас есть:
- Единая точка доступа к данным — Dremio, где все источники объединены
- Версионирование данных — Nessie, где каждое изменение отслеживается
- Надёжное хранилище — MinIO + Iceberg, где данные хранятся в открытом формате
- Автоматизация — Dagster для оркестрации, dbt для трансформаций через GitLab CI/CD
- BI для всех — Superset, где менеджеры сами строят дашборды
Идеальна ли эта система? Нет. Есть проблемы с ролями, есть баги в OSS-продуктах, есть моменты, когда хочется просто заплатить за SaaS и не думать. Но для нашего масштаба и бюджета — это лучший вариант, который мы смогли построить.
И главный вывод: данные — это не про инструменты, а про процессы. Самый крутой стек не поможет, если люди не понимают, зачем он нужен. Мы начали с простого — показали, как быстрее получать ответы на вопросы. Остальное пришло само.