Від Google Docs до Data Lakehouse: як ми побудували OSS-платформу даних з нуля
Мене звати Михайло Климнюк, я Head of Data в AUTOMOTO — українському агрегаторі автооголошень, що працює в Україні, Балтії та Європі.
Коли я прийшов на поточне місце роботи, вся аналітика компанії трималась на Google Таблицях і Looker Studio. Менеджери збирали дані вручну, копіювали цифри з однієї таблички в іншу, і раз на два тижні хтось робив «звіт» — по суті, скріншот з Looker Studio для презентації. Ніхто не розумів, звідки беруться цифри, ніхто не довіряв їм на 100%, і кожен «а чому тут інше число?» перетворювався в годин зясування де кінці.
Думаю, у більшості українських компаній середнього розміру аналітика виглядає саме так. І це працює — до певного моменту. Деякі речі в нас досі робляться так само — але вже не в тому обсязі. Наш момент настав, коли кількість джерел даних виросла, а рішення мали ухвалюватися швидше.
Початок: Google Таблиці + Looker Studio
Google Таблиці — ідеальний інструмент для старту. Безкоштовно, зрозуміло для всіх, колаборація в реальному часі. Looker Studio підключається до Google Sheets і показує графіки — теж безкоштовно.
Проблеми з фільтрацією вже починаються 1 мільйона заповнених клітинок, а зміни можуть відбуватись по 15+ хвилин. Google Sheets має ліміт у 10 млн клітинок — з 15+ джерелами даних ти досягаєш цього ліміту швидше, ніж здається. Дашборди в Looker Studio, що тягнуть дані з 5 різних таблиць, завантажуються хвилинами, а якщо хтось зараз редагує вихідну таблицю — взагалі розсипаються. Версіонування — формально є, але хто реально шукає видалений рядок у стрічці ревізій на 500 змін? А формули перетворились на спагеті: IMPORTRANGE поверх IMPORTRANGE поверх VLOOKUP з іншої таблиці. Одна зміна — і каскад помилок.
Стало зрозуміло: потрібна нормальна інфраструктура даних.
Перші бази: MSSQL → PostgreSQL → MongoDB
Першою базою став MSSQL — банально через досвід з попередньої роботи. До появи нормальної БД вивантаження даних можна було чекати тижнями. Буквально: «можеш дістати ці дані?» — «пиши таск, візьму в роботу». Потім правки, потім ще правки, і так по колу. Коли зʼявився MSSQL, час від запиту до відповіді скоротився до годин, а потім — до хвилин.
Але з часом вперлись у ліміти: Express Edition обмежена 10 ГБ, екосистема Windows-центрична, а ліцензія на повну версію — платна. Перейшли на PostgreSQL — безкоштовний, з нативним JSONB, величезною спільнотою і кросплатформенністю. PG став нашою default базою для аналітичних даних. MySQL (а точніше MariaDB) теж є в стеку — на ньому працюють продакшн-сервіси компанії.
MongoDB зʼявився пізніше, під конкретні кейси: парсинг Facebook Graph API, дані із соціальних мереж, де структура відповідей змінюється з кожним запитом. Коли API повертає вкладений JSON з довільною глибиною — реляційна БД починає страждати. MongoDB тут якраз в тему. Оскільки Dremio на той момент вже працював, оверхед від ще одного джерела був мінімальний — підключили MongoDB як source, і до всіх баз пишуться однакові SQL-запити через Dremio.
Data Lakehouse: що це і навіщо нам
Отже, у нас вже було кілька баз: MSSQL, PostgreSQL, MongoDB, плюс дані в Google Sheets, файли, API. Кожне джерело — свій формат, свій доступ, свої проблеми.
🔹Data Lakehouse — це архітектура, яка обʼєднує переваги Data Lake (зберігання сирих даних дешево і масштабовано) з Data Warehouse (SQL-запити, ACID-транзакції, схеми). Ми вирішили побудувати його повністю на open-source. Наш стек: MinIO як обʼєктне сховище (Data Lake), Apache Iceberg як формат таблиць, Nessie як каталог даних, Dremio як SQL-рушій.
🔹MinIO — це self-hosted Amazon S3. Обʼєктне сховище з S3-сумісним API — все, що вміє працювати з S3, працює з MinIO. Безкоштовний, повний контроль, ніяких рахунків за трафік. Для нашого випадку це очевидний вибір — нам не потрібне автомасштабування хмари, зате потрібен контроль і передбачувані витрати.
🔹Iceberg — це формат таблиць поверх обʼєктного сховища. Він дає можливість працювати з файлами в MinIO так, ніби це таблиці в базі даних — з ACID-транзакціями, версіонуванням, еволюцією схеми.
🔹Nessie — це каталог даних, який працює як Git. Бранчі, коміти, мерджі — для даних. Звучить як фантастика, але реально працює, і це не раз нас рятувало.
Чому Nessie, а не LakeFS? LakeFS версіонує дані на рівні обʼєктного сховища — як Git для файлів в S3. Nessie працює на рівні каталогу — версіонує метадані таблиць, а не самі файли. Для Iceberg-таблиць це ефективніше. Плюс Nessie — дефолтний каталог у Dremio, інтеграція з коробки.
Nessie — це те, що тримає нашу інфраструктуру разом. Якщо дані в Nessie цілі — все інше можна відновити. Далі буде два кейси, які це підтвердили.
Dremio — серце нашого Lakehouse. SQL-движок, який підключається до всіх джерел: MinIO через Iceberg/Nessie, PostgreSQL, MSSQL, MongoDB — і дозволяє робити SQL-запити до всього як до однієї бази JOIN з excel + дані з репліки MySQL запросто.
Ми свідомо мінімізуємо копіювання даних в таблиці чи проміжні файли, через це у нас 90% результатів таблиць в Dremio — це view. Замість дублювання view поверх джерел, а для прискорення — Reflections (матеріалізовані агрегати, які Dremio створює і оновлює автоматично). Запити до view виконуються швидко за рахунок Reflections, а дані завжди актуальні, бо view читають напряму з джерела при цьому лаг даних 1 година (можна налаштовувати більший, також можна спеціальною конструкцією ігнорувати рефлексії і мати дані в реальному часі).
Головна проблема Dremio Community Edition — відсутність нормального керування ролями. Всі користувачі — адміни. Ти не можеш обмежити доступ до певних датасетів або дати read-only права. Поки що доступ тримається на довірі — команда невелика. Але ми вже думаємо про proxy ACL, який парситиме SQL-запити перед тим, як вони потраплять у Dremio, і на цьому рівні давати або забирати права.
Це один із тих компромісів, з якими живеш в OSS: функціонал є, але access control — добудовуй сам.
Кейси
Оновлення Dremio, що пішло не так
Одного дня ми вирішили оновити Dremio до нової версії. Dremio у нас крутиться в Docker Compose, тому процес мав бути простим: змінити тег образу, docker compose up -d, готово. Але після запуску Dremio не бачив половину датасетів. Внутрішні метадані зіпсувались при міграції. В логах — стіна помилок без нормального опису. Ми витратили час на дебаг, але врешті вирішили знести все з нуля.
Момент паніки? Так, секунд на тридцять. А потім — «стоп, у нас же Nessie». Всі Iceberg-таблиці, їхня схема, історія змін — все в Nessie, а не в Dremio. Dremio — лише движок для запитів. Ми підняли чистий Dremio, перепідключили Nessie-каталог, і всі дані повернулись. View були описані в dbt — одна команда dbt run, і все розгорнулось назад. За годину все працювало як раніше.
Це був момент, коли архітектурне рішення розділити compute (Dremio) і catalog (Nessie) виправдало себе на 200%. Якби ми покладалися на внутрішній каталог Dremio — відновлення зайняло б дні, а не годину.
DELETE без WHERE
Є класичний жарт про DELETE FROM table без WHERE. Так от, у нас це був не жарт.
Одного разу я запустив DELETE-запит на Iceberg-таблицю і і при цьому виділив запит без умови. Просто DELETE FROM ... — і все. Таблиця очистилась миттєво. Серце зупинилось на секунду, руки похололи — там були дані, які збирались тижнями.
Якби це була звичайна PostgreSQL або MSSQL — це був би кінець. Бекап? Може, вчорашній. А дані за сьогодні — втрачені. В кращому випадку — години на відновлення.
Але у нас Nessie. Кожна зміна — це коміт. Кожний коміт має хеш. Я просто відкатив бранч до попереднього коміту — і через 2 секунди всі дані були на місці. Як ніби нічого не сталось.
До речі, таке ж саме траплялось і з MSSQL — DELETE без WHERE на продакшн-таблиці. Тільки там Nessie не було. Бекапу свіжого — теж. Довелось відновлювати все з нуля: піднімати старий бекап, порівнювати з продакшном, вручну доливати дані. Це зайняло не секунди, а години. І нервів — на місяць вперед.
Це той момент, коли розумієш: time travel і версіонування даних — це не маркетингові слова, а реальна страховка від людських помилок.
Обвʼязка: трансформація, оркестрація
Airbyte тягає дані з різних джерел — зараз в основному таблички з Google Sheets в PostgreSQL. Інколи використовуємо no-code connector builder, коли потрібно швидко підключити нове джерело. Airbyte обрали бо self-hosted, 300+ конекторів і UI. Fivetran коштує стільки, що дешевше найняти ще одного інженера.
Проблем вистачає. Airbyte зараз віджирає 12 ГБ оперативки і толком нічого не робить — плануємо його дропнути. Синхронізація великих обсягів може виконуватись днями без жодної помилки — просто тихо молотить. Community-конектори ламаються після оновлень. Синхронізація з Google Sheets час від часу падає без причини. Коли щось падає — логи розкидані по десятку Docker-контейнерів. А кожне оновлення Airbyte — лотерея: може пройти гладко, а може зламати конектори, які працювали місяцями.
Dagster — наш оркестратор: визначає, що, коли і в якому порядку запускається. Чому не Airflow? Тому що Airflow — це 2015 рік. DAGs, operators, XCom — працює, але відчувається як legacy. Dagster побудований навколо концепції assets — ти описуєш не «що запустити», а «які дані потрібно отримати». Це фундаментально змінює підхід.
Окремо хочу відзначити механізм dependency injection — дуже крутий і зрозумілий. Чомусь згадуються студентські роки і Dagger 2 під Android, де все було максимально заплутано. Тут — відразу все ясно. Ще плюс — нативна підтримка запуску Airbyte, Airflow та інших інструментів, тобто міграція або інтеграція зовнішніх тулів робиться без милиць.
dbt — це SQL-моделі, які перетворюють сирі дані в аналітичні таблиці. Працює з Dremio через адаптер, будує моделі поверх Iceberg-таблиць. dbt — де-факто стандарт у цій ніші: величезна спільнота, 30+ адаптерів. Dataform привʼязаний до BigQuery, SQLMesh цікавий, але з меншою спільнотою.
Зараз Dagster і dbt у нас не зʼєднані. dbt запускається при пуші через GitLab CI/CD — оновив SQL-модель, зробив push, GitLab запускає dbt run проти Dremio. Працює, і нагальної потреби інтегрувати dbt в Dagster поки немає. Але плануємо — це логічний наступний крок.
Окремий бонус: dbt генерує документацію, яку ми заливаємо в Dremio wiki з лінком на dbt docs. І навіть наш MCP-шлюз має до неї доступ — тобто ШІ-асистент може відповідати на питання про моделі даних, опираючись на актуальну документацію.
Apache Superset — BI-платформу, створену в Airbnb і передану в Apache Software Foundation. Обрали, бо RBAC з коробки, 50+ типів візуалізацій, повний SQL Lab. Metabase простіший, але з базовими правами. Grafana — для моніторингу, не для аналітики.
Superset муторно налаштовувати — первинний setup це окремий квест, UI іноді глючить, деякі графіки потребують танців з бубном, а документація... скажемо так, вона існує але це єгипетські манускрипти (не завжди вчасно оновлюються з виходом нових версій). Але коли все налаштовано — він класний. Для безкоштовного продукту — це найкращий варіант BI, який ми знайшли.
Redpanda — Kafka-сумісна платформа для стрімінгу. На C++, без JVM і ZooKeeper, з мікросекундною латентністю. Обрали, бо простіша в операціях за Kafka.
Ідея була крута: автоматичне створення топіків в залежності від URL, на які скидаються дані, і автоматичний запис в Iceberg-таблиці. Реальний потоковий інгест.
Але чесно — на нашому проєкті Redpanda майже не використовується. Нам достатньо batch-завантаження через MinIO. Дані оновлюються раз на годину або раз на день — real-time стрімінг поки не потрібний. Може, його час ще прийде. А поки що це як спортивна машина в гаражі: красива, потужна, але їздиш на роботу на звичайній.
Де закінчується «безкоштовно»
Найбільший міф про open-source — «це безкоштовно». Так, ліцензії безкоштовні. Але час на налаштування — тижні. Коли щось ламається — ти сам: GitHub Issues, Stack Overflow, Discord, і молися, щоб хтось відповів.
Рольова модель — як я вже казав, в Dremio CE всі адміни, в Airbyte OSS теж не густо з правами. Кожне оновлення кожного компонента — це потенційний breaking change.
Це типова проблема OSS: безкоштовна версія дає 80% функціональності, але той критичний 20% — security, RBAC, audit log — в платній. І ти або платиш, або живеш з компромісами, або будуєш обхідні рішення.
Але при цьому — ми повністю контролюємо свою інфраструктуру. Ніякого vendor lock-in. Ніяких несподіваних рахунків від AWS. І найважливіше — ми розуміємо кожен компонент системи, бо самі його налаштовували.
Висновки
Наш шлях від Google Sheets до Data Lakehouse зайняв десь два роки. Не тому, що це складно зробити за раз — атому, що кожен інструмент підключався по мірі виникнення проблем і потреб. Росло стихійно, під конкретні болі. Але зараз у нас є єдина точка доступу до даних через Dremio, версіонування через Nessie, надійне сховище на MinIO + Iceberg, автоматизація через Dagster і dbt, і BI через Superset.
Чи ідеальна ця система? Ні. Є проблеми з ролями, є баги в OSS-продуктах, є моменти, коли хочеться просто заплатити за SaaS і не думати. Але для нашого масштабу і бюджету — це найкращий варіант, який ми змогли побудувати.
15 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарівДякую за статтю!
Чи дивилися в сторону Apache Polaris? Він вже вийшов з інкубатора і там наче є рольова модель.
Ні. Але знаю, що підтримка Polaris є в Dremio Cloud також швидше за все в Dremio Enterprise. Cloude можна потестувати безкоштовно на тріалі.
Цікаво, дякую! А на що плануєте переходити замість airbyte?
Dagster & Sling docs.dagster.io/...egrations/libraries/sling закриває базові моменти для яких використовуєтсья airbyte. (БД ↔ БД,БД → файли, Google Sheets → БД) і протсто dagster assets як заміну API Builder
Це ви так для драматичного ефекту написали про зупинку серця? :) Ви ж свідомо вибрали всі технології і добре розумієте, як вони працюють.
Насправді, в першу чергу все вирішив Iceberg — ніяких даних фізично не було видалено, а просто створений новий снепшот. І навіть без Nessie таблицю можна було б відновити, повернувшись до попереднього снепшоту. Nessie тут лише виводить процес на новий рівень і робить rollback зручним і швидким.
Дякую за статтю. Весело такі зоопарки технологій водити :)
Переляк був справжній секунди дві точно :) Спочатку емоції, потім розум. Коли бачиш порожню таблицю, тіло реагує швидше за голову. А вже через пару секунд вмикається мозок і вирішує проблему.
По зоопарку влучніше не скажеш (по логотипах або фавіконах).
Nessie — лохнеське чудовисько
Dremio — норвала
Redpanda — червона панда
Dagster — восьиминіг
Minio — фламінго
В порівнянні з гугл таблицями, тут наварено дайбоже. Шкода що поверхнево, але глибше не влізло б. Було б цікаво більш детально, якщо плануєте ще статті, хоча б по кускам якщо не по всьому
взяв собі покататись на майбутнє з nessie
так планую детальніше описати з прикладами і кодом, але це буде вже пізніше.
Minio репрзиторій уже заархівований, і більше не open source. Чи розглядали альтернативи?
github.com/minio/minio
Пропустив цей момент. 100% будемо розглядати альтернативи.
Якщо є варіанти на пишіть, цікаво буде глянути.
не дивились garage, rustfs?
Запланували протестувати і подивитись поки на rustfs. Переїзд найближчих півроку точно не планується.
А які альтернативи?
людських опенсорсних здається і нема, наскідьки я шукав є проекти які роблять певні куски, для лаби собі згодно але так прям щоб замінити minio то мабуть лиш ceph але він складніший в рази
поки просто запінив версію, де ще людська адмінка
Точно так само використовуємо версію з людською адмінкою.
blog.vonng.com/en/db/minio-resurrect