Lakekeeper и Apache Polaris: сравниваем REST-каталоги для Iceberg

Ну и конечно сегодня снова про Iceberg. Почему? …таковы реалии времени.
Сейчас попытаюсь. Всё идёт вперёд. Мы идём. Они идут. И те тоже, которые ещё пока не шли, уже в тапках и стоят наготове. Всё идёт довольно быстро. И важно успеть. Про «догнать и перегнать», это уж ладно, просто груз у нас коллеги тяжёлый — данные. В моём кратком вступлении речь пойдёт про парадигмы, а они сместились за последний год два и достаточно сильно. Дело в том, что образцы DWH пяти-десятилетней давности, которые до сих пор превалируют в проде, проектировали по модели «один раз и надолго». К сожалению, сейчас так не работает. То, что вчера было лень делать и можно было отложить «на потом», посмаковав лавры творца глобальных решений (пальцем тыкать не буду), сегодня закрывается командой из трёх-четырёх человек. И ты уже позади! С приходом ИИ цикл сжался ещё сильнее. Данных это коснулось точно так же: источники меняются каждый квартал, аналитики каждый день приходят с новым экспериментом, производители железа не отстают, и подкидывают всё новые ускорители вычислений, то на видеокартах, то на «облачных атласах» и так далее.
Есть подозрение, что пришла пора слезать с «иглы» зависимости от вендоров больших СУБД. Причина не в лицензиях и импортозамесах — личное дело каждого, лезть в это не хочу. Причина в том, что выросла стоимость внедрения и сопровождения изменений: большие DWH исторически размещены на тяжёлом OLTP-стеке, а он всё-таки был придуман для других целей и задач. Каждая правка модели данных — это окна даунтаймов, блокировка процессов и всякие многочисленные «судороги». А что в Iceberg? В Iceberg то же самое делается над метаданными: добавить колонку, поменять тип, перепартиционировать задним числом — файлы остаются на месте теми же файлами, какими и были. Нет, там тоже есть свои нюансы по обслуживанию, ETL и т. д., но это нюансы, которые вполне себе удобоваримы по сравнению с перспективами стоимости владения.
Итак. Вендоры и OLTP-стек это только первая часть платы «за иглу». Вторая часть платы размещена чуть «под капотом». Неважно, Oracle, MSSQL или Postgres, у каждого OLTP-стека всё своё: формат на диске, диалект, механика. Данные внутри, и достать их можно только через него же и по сути это правильно, потому что СУБД тяжёлого класса спроектированы так, что там «каждая гайка к месту». Между тем, файл в виде parquet он и через десять лет parquet. Лежит себе в объектном хранилище, читается чем угодно — Trino, ClickHouse, Spark, ну или питоном с ноутбука, DuckDB тут тоже рядом. Надоел движок — поменял движок, данные не трогал. Чем-то напоминает архив где могут пылиться тонны бумаги и никому не мешать даже будучи забытыми, а что сейчас закрывает стек больших ДВХ на опенсорсе? ну пока что из самых современных — Iceberg. Всё, что нестабильно — стремится к стабильности, и Iceberg неплохо выступает в роли глобального арбитра, этакой системы сдержек и противовесов в войнах вендоров за форматы хранения. Показательна сама вендорская договорённость по формату и протоколу, а следом за ней — огромное комьюнити, подхватившее идею. Комьюнити пусть и виртуальное, но это гарантия, что проект проживёт хоть сколько-то предсказуемый срок. А файлы? они так и останутся ВАШИМИ файлами.
В этой же парадигме проявляется ценность метаданных и удобство работы с ними. Мы непосредственно наблюдаем трансформацию взглядов: данные имеют все шансы превратиться в настоящий data product, причём «продуктовость» связана не столько с самими данными, это как раз понятно, сколько с метаданными, которые приобретают для «продуктовости» необходимую значимость, а именно метаданные — частая «хворь» старых, олдскульных DWH. Теперь же описание можно отдать LLM, и «домен данных», который производит «продукт данных», перестаёт выглядеть теоретической конструкцией. Также ярче проявляются возможности для data mesh, это когда у всех доменов общий формат хранения и общий каталог, домену не нужно пускать соседа в свою СУБД, достаточно дать права на таблицу в Iceberg. Саму парадигму это, конечно, не реализует, а кто-то и оспорит: мол, при чём тут data mesh если данные сливаются в итоге в кучу, но коллеги! Куча куче рознь, как говорится. Data mesh это про «владение и ответственность», а не про форматы и места хранения, поэтому в реальной жизни у средних компаний подобная конструкция весьма жизнеспособна.
С вступительной частью пора заканчивать, и в этой связи (прям ощутил себя на 26-м съезде КПСС :) речь в моём тексте будет посвящена отнюдь не облачным инфраструктурам (да не обидятся на меня их предержащие). Всё, о чём дальше — можно разворачивать у себя на железе, и это условие я считаю самым важным, да что там — определяющим. Кто-то скажет «облака-облака»! Ну какие облака? милостивые государи! Если у вас там кликстрим например — храните хоть где, а вот банковские ДВХ уже пухнут от данных, тратят огромные средства поддерживая архитектуры DWH на OLTP-стеке и отдать в облака они их, по понятным причинам, никак не могут. За 20 лет, даже здесь, в России, серьёзных финансовых данных скопилось столько, что в СУБД это просто уже не лезет (шутка). Не потому что СУБД не тянут — тянут конечно. Просто на больших массивах вся эта машинерия начинает требовать очень серьёзного обслуживания: свободное место, логи транзакций, неймспейсы и привязанные к ним файлы данных, настройка, конфигурация, индексы и т. д. и т. п… А это всё — стоимость! Которая начинает обходиться владельцу совсем не в копеечку. Не говоря уже про то, что в строковой СУБД данные лежат строками, а в DWH данные чаще запрашивают под колоночную структуру (давайте только не будем про колоночные индексы, сейчас не об этом речь).
Итак. Спор о формате таблиц для Lakehouse закончился. Iceberg поддерживают Spark, Trino, Flink, StarRocks, ClickHouse, Snowflake, BigQuery — перечислять можно долго. Зато открылся следующий вопрос — каталог. По сути, каталог, это тот сервис, который превращает Iceberg из спецификации в механизм. Именно каталог хранит указатель на актуальный metadata.json, выполняет атомарный commit и решает, кто имеет право читать таблицу, а кто — нет. По весу это решение я бы сравнил с выбором СУБД, поменять каталог потом можно, но есть свои подводные камни.
В этой статье разберу Lakekeeper — каталог сделанный на Rust, который за два года прошёл путь от тестирования идей до продакшен-инсталляций, — и сравню его с Apache Polaris, самым заметным конкурентом в нише self-hosted REST-каталогов. Всё по состоянию на конец лета 2026-го, оба проекта выпускают релизы довольно часто и это говорит о заинтересованности и вовлечённости аудитории.
Точка отсчёта
Коротко напомню, зачем для Iceberg вообще нужен каталог. Таблица Iceberg — это дерево файлов в объектном хранилище: данные хранятся в Parquet, над ними манифесты, над манифестами metadata.json, ну и актуальной версией таблицы считается та, на которую как раз и указывает каталог. Commit — атомарное движение этого указателя.

Старые каталоги (Hive Metastore, JDBC-каталог) умели именно это — хранить указатель. REST-спецификация каталога, ставшая частью проекта Iceberg, переносит на сервер значительно больше: разрешение конфликтов при параллельных commit, транзакции на несколько таблиц, выдачу временных учётных данных к хранилищу. Движок обращается к каталогу по HTTP, а тот выписывает короткоживущий токен на нужный префикс, при этом постоянные ключи от S3 в этой схеме больше не требуются. По-простому: что-то вроде бюро пропусков где у пропуска есть срок жизни (например час) и охранник записывает каждый визит :)
«Побочный» эффект такой архитектуры даже важнее выдачи токенов. Через каталог проходит каждое обращение к каждой таблице. Значит, именно здесь будет логично разместить контроль доступа и аудит для всех клиентов. Обе системы, и Lakekeeper, и Polaris реализуют эту идею, но каждый немного по-разному.
Lakekeeper: бинарник, Postgres и OpenFGA
Lakekeeper написан на Rust поверх apache/iceberg-rust, распространяется под Apache 2.0, один исполняемый файл, который тянет за собой единственную обязательную зависимость, PostgreSQL версии 15 или новее, для хранения собственных метаданных. Состояния внутри сервиса нет, поэтому горизонтальное масштабирование сводится к запуску ещё одного экземпляра за балансировщиком. Все экземпляры подключаются к одной и той же базе как обычные клиенты, каждый со своим пулом соединений, а одновременные commit одной таблицы сериализует сам Postgres — проходит одна транзакция, вторая возвращает движку конфликт по REST-спеке, и тот повторяет попытку на свежих метаданных. Схема ровно та же, что у фермы бэкендов веб-приложения над одной СУБД.

Для DBA картина подкупающе знакомая. Вся ответственность за durability лежит на Postgres, а Postgres мы бэкапить умеем. Сломался сервис — перезапустили, база цела, метаданные на месте, просто и быстро.
Три API
Сервер выставляет три отдельных интерфейса:
/catalog/v1/...— стандартный Iceberg REST. Сюда обращаются Spark, Trino, PyIceberg и остальные движки. Руками его дёргать не нужно./management/v1/...— администрирование, которого в спецификации Iceberg нет: bootstrap сервера, проекты, warehouse’ы со storage-профилями, пользователи, роли, фоновые задачи.API прав доступа — появляется при включённой авторизации.
Swagger со всеми тремя доступен прямо на сервере по /swagger-ui. Мелочь, но при интеграции экономит часы.
Ну и конечно, есть web UI.
Предпросмотр данных в консоли сделан на DuckDB WASM, то есть крутится прямо в браузере. Вещь удобная, но зависит от браузерной безопасности: за parquet браузер лезет в S3 сам, минуя каталог. Значит хранилище должно быть доступно ему по тому же адресу, по которому туда ходит сам Lakekeeper, плюс на бакете нужна CORS-политика с origin вашей консоли. В примерах из репозитория это из коробки не заводится, MinIO там виден только внутри docker-сети, и про это есть в документации, так что обратите внимание.
Мультиарендность и хранилища
Одна инсталляция Lakekeeper обслуживает несколько проектов, где у каждого — несколько warehouse, соответственно, у каждого warehouse свой storage-профиль и свои учётные данные к хранилищу, которые лежат в отдельном secret store — в том же Postgres или в HashiCorp Vault.
Поддерживаются S3 в исполнении AWS, S3-совместимые хранилища (в примерах из репозитория используется MinIO, для on-prem это основной сценарий), Azure ADLS Gen2, Google Cloud Storage, а с версии 0.13 — Microsoft OneLake / Fabric, включая private endpoints. Выдача доступа движкам — через vended credentials либо remote signing для S3.
Авторизация: OpenFGA
Самая сильная, на мой взгляд, часть Lakekeeper. Вместо самописной ролевой модели проект интегрирован с OpenFGA1 — открытой реализацией модели Google Zanzibar2. OpenFGA разворачивается рядом с каталогом как обычный контейнер без внешних сервисов, кортежи прав хранятся в Postgres или MySQL, так что подойдёт тот же инстанс, что и у самого Lakekeeper, отдельной базой. Права описываются отношениями между объектами и раздаются до уровня отдельной таблицы: этот пользователь читает prod.sales.orders, эта роль администрирует warehouse, этот сервисный аккаунт создаёт таблицы в одном namespace и не имеет доступа к другому, удобно, логично.
Аутентификация — любой OIDC-провайдер, плюс нативная поддержка Kubernetes service accounts. В российских реалиях, с их закрытыми контурами, чаще всего становится Keycloak on-prem, он же обеспечивает федерацию с Active Directory и LDAP, и в примерах Lakekeeper с включённым контролем доступа Keycloak уже лежит контейнером в том же docker compose. С 0.13 провайдеров может быть несколько одновременно — скажем, Keycloak для людей и отдельный issuer3 для сервисных аккаунтов. Для Trino связка с правами каталога делается через мост на Open Policy Agent — политики лежат в том же репозитории.
Если в компании уже есть своя система доступа, авторизатор подменяется — это Rust-трейт, реализуете несколько методов, и каталог запрашивает решения у вашей системы. Тем же способом подменяются хранилище метаданных, secret store и шина событий. Для платной версии Lakekeeper+ команда проекта сделала на этих трейтах авторизацию на Cedar и синхронизацию ролей из Okta, Entra и LDAP — хорошая иллюстрация того, что расширяемость там реальная.
События и контракты данных
Каждую операцию над таблицей, от создания и commit до удаления, Lakekeeper умеет публиковать как событие в формате CloudEvents4, транспортом служит NATS5 или Kafka. Смысл идеи в том, что внешним системам больше не нужно опрашивать каталог по расписанию, событие доставляется брокером в момент изменения.
Приёмники строите под свои задачи. Оркестратор подписывается на commit нужной таблицы и запускает downstream-обработку сразу после появления данных, без периодического опроса и cron-расписаний. BI-слой сбрасывает кэш по факту изменения, каталог метаданных вроде DataHub или OpenMetadata синхронизируется без ночных выгрузок, а поток событий целиком складывается в SIEM6 — для банка это готовый журнал аудита операций над данными.
Отдельный механизм — ContractVerification. (фанатам data mesh и Data Governance посвящается :))
Контракт данных — это договорённость между тем, кто таблицу производит, и теми, кто её читает. Какие колонки, каких типов, насколько свежие. По смыслу штука старая, раньше она была в головах, в переписке или конфлюенсе. Теперь контракт стал описываться формально и лежать в реестре рядом с самой таблицей. В OpenMetadata он теперь отдельная сущность со схемой, правилами качества и SLA по свежести, причём в формате Open Data Contract Standard, не в самодельном YAML. Потребитель заходит и видит, на что подписался.
Проверяется такой контракт обычно по расписанию. Раз в сутки приходит задание, сверяет схему с описанием, заводит инцидент при расхождении. Значит о поломке вы узнаёте утром, когда три витрины уже пересчитались на кривых данных, а регуляторный отчёт ушёл. К примеру: аналитик выкатил изменение дропающее колонку, на ней висел чужой пайплайн или отчёт, в итоге алерт прилетел в три часа ночи.
ContractVerification переносит проверку в момент записи. Движок присылает изменение, Lakekeeper собирает новые метаданные и перед тем как записать их в каталог, спрашивает вашу систему, пропускаем или нет. Отказ означает, что подмены указателя (commit) не будет, движок получит ошибку, таблица останется в прежней версии. Сначала это работало только на изменении существующих таблиц, теперь распространилось и на создание. Для DBA (админам баз данных) ближайшая аналогия — DDL-триггер, откатывающий ALTER TABLE, когда тот ломает зависимый объект. В этом случае «триггер» находится снаружи, в вашем реестре контрактов, а каталог у него спрашивает разрешения на внесение изменений в схему.
Контракты стоят особняком среди остальных точек расширения. Хранилище метаданных, secret store, авторизатор, шина событий — тоже трейты, но у каждого в поставке лежит готовая реализация и включается переменной окружения. Авторизацию поднимают установкой LAKEKEEPER__AUTHZ_BACKEND в openfga, дальше остаётся развернуть рядом сам OpenFGA, контейнер уже прописан в примерах и в helm-чарте. Никакого кода, трейт нужен только тем, у кого своя система прав.
У контрактов готовой реализации нет, трейт и есть механизм. Придётся взять Lakekeeper как библиотеку, написать реализацию на Rust и собрать собственный бинарь. Загрузки плагинов в рантайме нет, в документации про это указано. Выбор реализации делается на этапе сборки, зато компилятор проверяет интеграцию. Мне такой подход скорее нравится, хотя порог он поднимает заметно, но возможно в скором времени выпустят какие-то интеграции «из коробки».
В целом, без своего разработчика на Rust механизм ContractVerification существует пока только на бумаге. При наличии своего разработчика вы получаете точку стыковки реестра с реальной записью в таблицы. Вещь редкая, описывать и проверять контракты умеют многие инструменты, запрещать — ни один. OpenMetadata при этом остаётся источником истины, а каталог спрашивает его в момент commit.
Эксплуатационные мелочи
За последние релизы накопился набор фич, по которым видно, что проектом пользуются в реальной эксплуатации:
мягкое удаление таблиц с настраиваемым сроком и защита от удаления для warehouse, namespace, таблиц и view;
read-only режим обслуживания — сервер отвечает 503 с Retry-After на любые изменения, пока применяется миграция (0.12.3);
сами миграции схемы применяются одной транзакцией — прерванное обновление не оставит базу в полусмигрированном виде;
политика версий формата Iceberg на уровне warehouse, можно запретить создание таблиц старого формата (0.13);
шифрование записей клиентскими ключами AWS KMS через vended credentials (0.13);
защита горячих кэшей от cache stampede — одновременные одинаковые промахи схлопываются в один запрос к базе (0.13).
Плюс веб-консоль — warehouse’ы, поиск по таблицам, раздача прав, предпросмотр данных через встроенную WASM-сборку DuckDB прямо в браузере.
Текущая ветка — 0.13, релизы выходят каждые несколько недель. Про номер меньше единицы поговорим ниже.
Polaris: каталог под флагом Apache
Polaris создан внутри Snowflake и передан в Apache Software Foundation летом 2024-го. Дальше классический путь — инкубация, релиз 1.0 в июле 2025-го, выход из инкубатора в top-level проект 4 апреля 2026-го. Релизы идут плотно: 1.3.0 в январе, 1.4, 1.5, 1.6, наконец 1.7.0 второго августа 2026-го. Стек — Java, Quarkus, метаданные в реляционной БД через JDBC, в продакшене это Postgres. Managed-вариант существует в виде Snowflake Open Catalog.
Двухуровневая RBAC
Polaris реализует собственную модель доступа — классическую RBAC7 в два уровня. Принципалы (люди и сервисы) группируются в principal roles. Привилегии вида TABLE_READ_DATA или CATALOG_MANAGE_CONTENT выдаются на catalog roles — уровень полномочий внутри конкретного каталога. Затем catalog roles назначаются principal roles. Защищаемые объекты — каталог, namespace, таблица, view и policy.
Схема понятная и хорошо ложится на корпоративные регламенты. Гранулярность — до таблицы, как и у Lakekeeper, но выразительность ниже, чем у графа отношений OpenFGA.

С версии 1.3.0 авторизацию можно вынести наружу в Open Policy Agent — для организаций, где политики доступа обязаны храниться в одном месте, это плюс.
Федерация каталогов
Polaris умеет регистрировать внешние каталоги как федерированные источники: Hive Metastore, Hadoop, AWS Glue, BigQuery Metastore, другие Iceberg REST-каталоги. Их содержимое проецируется через собственные эндпоинты Polaris и подчиняется его модели доступа. Получается каталог каталогов — одна точка входа и одна модель прав поверх набора систем, копившегося в большой организации десятилетие.
У Lakekeeper федерации нет. Для компании с тремя поколениями инфраструктуры это может закрыть вопрос выбора, хотя я бы на это сильную ставку не делал ну если прям холдинг и data mesh в руки.
Delta и Hudi по соседству
С релиза 1.3.0 в статус GA вышли generic tables — Polaris каталогизирует таблицы Delta Lake и Hudi вместе с Iceberg, в тех же namespace. Полноценного управления commit’ами для этих форматов там нет, но для организации, в процессе миграции между форматами, единая точка учёта — преимущество. Lakekeeper здесь принципиально моноформатен, только Iceberg.
Туда же относится отчётность по метрикам. Движки могут отправлять в Polaris статистику выполнения запросов через Iceberg REST API — строки, байты, commit-активность. Каталог превращается в источник операционного сигнала о том, как таблицы реально используются.
Релиз 1.7.0
Заметных изменений в релизе четыре. Первое — идемпотентные записи, они убирают старую болячку: повтор commit после сетевого сбоя больше не создаёт дубликат. Второе — Semantic Model API в статусе беты. За ним стоит Open Semantic Interchange, спецификация описания метрик и измерений, которую в конце 2025-го затеяли Snowflake, dbt Labs и Salesforce с группой BI-вендоров, сейчас она лежит в инкубаторе ASF. Polaris хранит такие описания как полноценные сущности каталога рядом с таблицами, к которым они относятся, раздаёт на них права через свою же RBAC и ничего при этом не вычисляет. Каталог начинает отвечать не только на вопрос, где лежит, но и на вопрос, что это значит.
Третье изменение на вид скучнее, зато для эксплуатации важнее. Валидация локаций при выдаче временных учётных данных — это закрытая дыра, а не новая возможность. Нативный каталог пропускал повторную проверку allowedLocations, и креды можно было получить на путь за пределами разрешённого префикса. Той же темы касается новый флаг уникальных локаций: он выдаёт новой таблице непредсказуемый суффикс в пути, чтобы две таблицы не делили общий префикс. По умолчанию выключен.
Четвёртое — переработанная чистка orphan-файлов, не ссылается ни один снапшот. Копятся они от упавших записей, откаченных commit’ов и компакции, занимают место и деньги.
Последние две вещи смотрят в одну сторону, на границы в хранилище. Валидация держит выданные креды внутри разрешённого префикса, уникальные суффиксы не дают префиксам разных таблиц пересекаться, а чистка работает уже внутри этих границ и безопасна настолько, насколько надёжно они проведены. По этому списку видно, как фокус проекта смещается с «работает ли» на «можно ли это отдать аудитору».
Два каталога рядом
Lakekeeper 0.13 | Polaris 1.7 | |
|---|---|---|
Язык / рантайм | Rust, один бинарник | Java, Quarkus, JVM |
Лицензия | Apache 2.0 | Apache 2.0 |
Управление проектом | Компания-разработчик + сообщество | Apache Software Foundation (TLP) |
Метаданные | PostgreSQL ≥ 15 | Реляционная БД через JDBC (Postgres) |
Форматы таблиц | Только Iceberg | Iceberg + generic tables (Delta, Hudi) |
Авторизация | OpenFGA до уровня таблицы, Cedar в Lakekeeper+, свой Authorizer через трейт | Двухуровневая RBAC до уровня таблицы, внешняя авторизация через OPA |
Федерация каталогов | Нет | Hive, Hadoop, Glue, BigQuery Metastore, REST-каталоги |
События изменений | CloudEvents в Kafka / NATS | Event listeners внутри сервера |
Вендинг учётных данных | S3 (AWS и совместимые), ADLS Gen2, GCS, OneLake; remote signing | S3 / GCS / Azure через STS-механики, session tags в CloudTrail |
Контракты данных | ContractVerification (запрет commit) | Нет прямого аналога |
Веб-консоль | Вкомпилирована в сервер, предпросмотр данных через DuckDB | Отдельный проект в polaris-tools, собирается и хостится самостоятельно |
Метрики использования таблиц | Нет | Приём метрик движков по Iceberg REST |
Теперь то, что в таблицу не помещается.
Эксплуатационный профиль. Rust-бинарник с Postgres против JVM-приложения. У Lakekeeper область для настройки минимальная, время старта — секунды, и его спокойно поднимают даже в CI для интеграционных тестов. В трекере DuckDB коллеги прямо рекомендовали его вместо Polaris, потому что настройка оказалась заметно проще. Polaris требует обычной для Java-сервисов заботы о памяти и прогреве. Для команды, где уже стоит десяток JVM-сервисов, это ничего не меняет, для команды из двух инженеров — меняет. Туда же веб-интерфейс. У Lakekeeper он вкомпилирован в тот же бинарь и поднимается вместе с сервером. Консоль Polaris живёт отдельным проектом в репозитории polaris-tools, это приложение на React, которому нужен Node.js, своя сборка и свой хостинг, а готовых образов среди релизных артефактов нет. Плюс её надо подружить с сервером по CORS, потому что запросы к API она шлёт из браузера напрямую.
Зрелость и управление. Тут преимущество у Polaris, и оно двойное. Во-первых, ASF-governance8 — проект принадлежит фонду, развитие не зависит от бизнес-модели одной компании. Во-вторых, номер версии — 1.7 против 0.13. Страх перед цифрой 0.x считаю преувеличенным, так как по содержимому релизов Lakekeeper (атомарные миграции9, maintenance mode10, защита кэшей от stampede11) виден продукт, который эксплуатируют всерьёз. Тем не менее для корпоративного архитектора, который защищает выбор перед инвест-комитетом, «top-level проект Apache версии 1.7» звучит немного весомее, ну его понять можно.
Богатство модели доступа против готовности из коробки. OpenFGA интереснее двухуровневой RBAC. Граф отношений с наследованием отвечает на вопрос «почему у этого пользователя есть доступ» одним запросом. Расходы — ещё один сервис в инфраструктуре (сам OpenFGA) и порог входа в модель Zanzibar. RBAC Polaris проще объяснить безопаснику за одну встречу.
Направления развития. Polaris строит каталог-агрегатор с федерацией, метриками и семантическими моделями — заявка на роль слоя управления всем Lakehouse. Lakekeeper строит лучший каталог для Iceberg — событийная модель на CloudEvents и контракты данных вместо поддержки дополнительных форматов. Направления разные, отсюда и разные списки фич.
Выбор под задачу
Мой рабочий алгоритм такой.
Lakekeeper, если у вас один-два движка (Trino, Spark, ClickHouse), хранилище — S3 или MinIO on-prem, команда небольшая, а от каталога нужны надёжный commit, нормальные права и минимум эксплуатационных хлопот. Установка через docker compose занимает минуты, дальше вся забота — бэкап Postgres, который у вас и так налажен. Событийная модель через Kafka встраивается в существующие пайплайны без самодеятельности.
Polaris, если организация большая, каталогов уже несколько (скажем, Glue в облаке и Hive Metastore в наследство от Hadoop-эпохи) и задача звучит как «единая точка доступа и аудита поверх всего». Федерация плюс generic tables закрывают этот сценарий штатно. Требование «только проекты ASF» из корпоративной политики также снимает вопрос выбора.
Про скорость развёртывания — случай из практики. В одном банке новый архитектор DWH начал разработку хранилища по Data Vault 2.0, тяжёлые финансовые компании часто выбирают именно такой, экстенсивный путь и их понять можно — наследие Инмона/Кимбалла 20 лет усваивалось на уровне подкорки, к слову, в виде рабочих, хоть и местами муторных решений. Строить хотели на Oracle, как и предыдущее хранилище. Я предложил собрать параллельную альтернативу, что оставляло возможность отката на Oracle в случае «если не взлетит». Стек получился такой:
хранение S3 — RustFS (выбирали между SeaweedFS и RustFS, победил последний, по отзывам «быстрее»);
каталог — Lakekeeper + Postgres (временно на кубере, посмотрим по нагрузке);
ETL — SeaTunnel, три воркера на кубере;
оркестрация ETL — NiFi (от Airflow ушли умышленно, чтобы всё работало «из коробки» в кубере; данные через себя NiFi не гонит);
SQL-федерация — Trino, четыре воркера на кубере;
витрины — ClickHouse.
Результат по календарю: развёртывание на железе заняло 3 дня, первые дашборды появились в течение недели, ещё две недели ушло на тестирование — и стартовала тестовая эксплуатация. Ветка Data Vault к этому моменту существовала в виде концептуальных схем на бумаге.
Обе системы реализуют одну и ту же спецификацию — Iceberg REST. Это удерживает цену ошибки в разумных пределах — движки настроены на спецификацию, и переезд между каталогами — процедура неприятная, но выполнимая.
Потрогать оба можно за вечер: у Lakekeeper в репозитории лежит examples/minimal с docker compose, Jupyter-ноутбуками и консолью на localhost:8181; у Polaris — готовые образы на Docker Hub и Helm-чарт. Документация — docs.lakekeeper.io и polaris.apache.org.
Ну в целом всё )) … задавайте вопросы. Отвечу на все ;)
Глоссарий:
1. OpenFGA — открытый сервер авторизации, реализация модели Zanzibar. Проект создан в Auth0 и принят в CNCF. Права хранятся как кортежи вида (пользователь, отношение, объект), проверка доступа — обход графа этих кортежей. назад
2. Zanzibar — внутренняя система авторизации Google, описанная в публичной статье 2019 года. Единый сервис проверки прав для Drive, YouTube, Calendar и других продуктов компании. Статья дала начало семейству открытых реализаций; OpenFGA — одна из них, наряду со SpiceDB и Ory Keto. назад
3. Issuer — сервер, выпускающий токены доступа. Он же идентифицируется URL внутри самого токена: по этому адресу приложение забирает публичные ключи, проверяет подпись и понимает, чьей выдаче можно верить. Для людей типичный issuer — Keycloak с федерацией в Active Directory, для сервисных аккаунтов — сам Kubernetes, который выпускает и ротирует их токены по собственному расписанию. назад
4. CloudEvents — спецификация CNCF, задаёт общий набор обязательных полей у события: id, source, type и время. Приёмник, который умеет CloudEvents, читает события Lakekeeper без кастомного парсера, и тот же приёмник подойдёт для любого другого источника с этой спецификацией. назад
5. NATS — открытый брокер сообщений из экосистемы CNCF. Один бинарник на Go, ставится за минуты, заметно легче Kafka по эксплуатации, за что его любят в Kubernetes-окружениях. Название — аббревиатура от Neural Autonomic Transport System, хотя расшифровку давно никто не вспоминает. назад
6. SIEM (Security Information and Event Management) — класс систем, которые собирают события безопасности со всей инфраструктуры в одно место для корреляции, алертинга и расследований. В российском ландшафте это, например, MaxPatrol SIEM или KUMA. назад
7. RBAC (Role-Based Access Control) — ролевая модель доступа. Привилегии выдаются ролям, а люди и сервисы получают их через назначение ролей. Та же логика, что у ролей базы данных в SQL Server или групп в Active Directory. назад
8. ASF-governance — модель управления проектами Apache Software Foundation. Код принадлежит фонду, а решения принимает комитет проекта (PMC) публичным голосованием. Каждый релиз проходит формальную процедуру проверки и голосование. Для заказчика это страховка на случай, если компания-донор потеряет интерес к проекту. назад
9. Атомарные миграции — изменения схемы служебной базы каталога применяются одной транзакцией, обновление либо проходит целиком, либо откатывается. Апгрейд, прерванный на середине, не оставит базу в промежуточном состоянии. назад
10. Maintenance mode — режим обслуживания. Сервер продолжает отдавать метаданные на чтение, а на любые изменения отвечает кодом 503 с заголовком Retry-After. Позволяет проводить обновления, останавливая запись без остановки чтения. назад
11. Cache stampede — лавина одинаковых запросов к базе, когда популярная запись кэша истекает и десятки клиентов одновременно запрашивают её из источника. Lakekeeper схлопывает такие одновременные промахи в один запрос к базе и добавляет случайный сдвиг к срокам жизни кэша, чтобы записи не истекали одновременно. назад
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.