Учебный Lakehouse-стенд (Trino + Spark + Iceberg + MinIO)
Учебный стенд для демонстрации Lakehouse-архитектуры на одном ноутбуке:
- объектное хранилище S3-класса (MinIO),
- движок запросов Trino,
- Spark для batch/ETL и интерактивных экспериментов,
- формат таблиц Iceberg,
- JDBC-каталог (PostgreSQL) для метаданных Iceberg в Trino,
- конфиг Spark, заточенный под работу с Iceberg + S3.
Стенд ориентирован на обучение менти и быструю демонстрацию концепции Lakehouse: разделение storage / compute / catalog без лишней обвязки (Hive Metastore, полноценный Hadoop-кластер и т.п.).
Архитектура
graph LR
subgraph Storage
M[(MinIO<br/>S3-compatible)]
end
subgraph Catalog
P[(PostgreSQL<br/>Iceberg JDBC catalog)]
end
subgraph Compute
S[Spark 3.5.1<br/>PySpark / SQL]
T[Trino 478<br/>Iceberg connector]
end
S <--> M
S <--> P
T <--> M
T <--> P
Основные идеи:
- Данные (Parquet-файлы + служебные каталоги Iceberg) лежат в бакете MinIO (
s3a://lakehouse/warehouse/...). - Метаданные Iceberg хранятся в PostgreSQL (JDBC-каталог
lakehouse). - Spark и Trino используют один и тот же JDBC-каталог: таблицы, созданные в Spark, доступны в Trino, и наоборот.
Быстрый старт
-
Установить Docker и Docker Compose (см. раздел «Требования» ниже).
-
В корне репозитория выполнить:
docker compose build docker compose up -d -
Открыть основные интерфейсы:
- Trino Web UI:
http://localhost:8090 - MinIO Console:
http://localhost:9001 - JupyterLab (если включён):
http://localhost:8888
- Trino Web UI:
-
Для пошаговых лабораторных работ см. файл
HOWTO.md.
Состав репозитория
-
docker-compose.yml— описание всех сервисов стенда:- Spark master / worker(ы) на базе кастомного образа
spark-iceberg, - Trino,
- MinIO (S3-совместимое хранилище),
- PostgreSQL под Iceberg JDBC-каталог,
- (опционально) Jupyter / notebook для PySpark.
- Spark master / worker(ы) на базе кастомного образа
-
spark/Dockerfile— сборка кастомного образа Spark с зависимостями:hadoop-aws,aws-java-sdk,- библиотека Iceberg нужной версии,
pyspark,pyarrowи базовый набор инструментов.
-
jupyter/Dockerfile— образ JupyterLab на базе Spark-образа. -
spark/spark-defaults.conf— конфигурация Spark для работы с:- Iceberg-каталогом
lakehouse(типjdbc, метаданные в Postgres), - MinIO через
s3a://, - расширениями
IcebergSparkSessionExtensions.
- Iceberg-каталогом
-
src/— учебные примеры для Spark и Trino:src/spark/cluster_smoke.py— проверка, что кластер жив (Spark master/worker).src/spark/iceberg_smoke.py— Spark создаёт Iceberg-таблицу и читает её.src/spark/iceberg_demo.sql— пример создания Iceberg-таблицы через Spark SQL.src/trino/iceberg_smoke.sql— Trino читает таблицу, созданную в Spark.
-
trino/catalog/lakehouse.properties— конфиг каталога Trinolakehouse:- коннектор
iceberg, jdbc-каталог (PostgreSQL),- доступ к MinIO как к S3-хранилищу.
- коннектор
Требования
- Docker и Docker Compose.
- Порты по умолчанию должны быть свободны (см. таблицу «Сервисы и порты» ниже).
Сервисы и порты
| Сервис | Контейнер | Порт (host → container) | Назначение / UI |
|---|---|---|---|
| Trino | trino |
8090 → 8080 |
Web UI Trino |
| MinIO API | minio |
9000 → 9000 |
S3 endpoint |
| MinIO Console | minio |
9001 → 9001 |
Веб-консоль MinIO |
| PostgreSQL (каталог) | postgres-iceberg |
5432 → 5432 |
Доступ для psql/DBeaver и т.п. |
| Spark master UI | spark-master |
8080 → 8080 |
Web UI мастера Spark |
| Spark worker-1 UI | spark-worker-1 |
8081 → 8081 |
Web UI первого воркера |
| Spark worker-2 UI | spark-worker-2 |
8082 → 8081 |
Web UI второго воркера (host 8082) |
| JupyterLab | jupyter |
8888 → 8888 |
JupyterLab с PySpark |
Сборка и запуск
Все команды в этом разделе выполняются из корня репозитория.
1. Собрать образы
docker compose build
Будут собраны кастомные образы Spark/Jupyter с зависимостями Iceberg, S3A, JDBC-драйвером Postgres и Python-библиотеками.
2. Поднять стенд
docker compose up -d
Что происходит при старте:
- MinIO поднимается с root-пользователем/паролем (по умолчанию смотри в
docker-compose.yml, обычноminioadmin/minioadmin), init-контейнер создаёт бакетlakehouse. - PostgreSQL под каталог Iceberg создаёт БД и пользователя (значения — в
docker-compose.yml/.env). - Trino стартует с каталогом
lakehouse, описанным вlakehouse.properties. - Spark master/worker получают конфиг из
spark-defaults.conf(общий JDBC-каталог Iceberg + MinIO).
Проверить статус:
docker compose ps
3. Остановить стенд и очистить данные
Чтобы остановить все сервисы и удалить данные в MinIO/PostgreSQL (Docker volumes), можно выполнить:
docker compose down -v
Доступ к сервисам
Trino
Web UI (координатор):
http://localhost:8090
(точный порт см. в docker-compose.yml).
Подключение из контейнера trino:
docker exec -it trino trino \
--server http://localhost:8080 \
--catalog lakehouse
Проверка:
SHOW CATALOGS;
SHOW SCHEMAS FROM lakehouse;
MinIO
- Консоль:
http://localhost:9001 - S3 endpoint:
http://localhost:9000
Учётные данные — MINIO_ROOT_USER / MINIO_ROOT_PASSWORD из docker-compose.yml или .env.
Создай в MinIO бакет lakehouse (если его нет) — данные Iceberg будут храниться именно там.
PostgreSQL (каталог Iceberg для Trino)
Подключение (пример):
psql -h localhost -p 5432 -U iceberg -d iceberg
(имя пользователя, БД и порт уточняются в docker-compose.yml).
Служебные таблицы Iceberg JDBC-каталога (iceberg_tables, iceberg_namespace_properties) создаёт однократный контейнер iceberg-catalog-init. Если база уже запускалась без них, можно переинициализировать вручную:
docker compose run --rm iceberg-catalog-init
Jupyter / notebooks
Веб-интерфейс: http://localhost:8888 (по умолчанию без токена).
- В контейнере монтируется
./notebooksв/opt/work. ./srcдоступен read-only в/opt/src, переменнаяPYTHONPATH=/opt/srcуже установлена — можно импортировать функции из скриптов прямо в ноутбуках.
Конфигурация Trino (каталог lakehouse)
Файл lakehouse.properties монтируется в /etc/trino/catalog/lakehouse.properties.
Ключевые параметры:
connector.name=iceberg
# Каталог Iceberg типа JDBC (метаданные в PostgreSQL)
iceberg.catalog.type=jdbc
iceberg.jdbc-catalog.catalog-name=lakehouse
iceberg.jdbc-catalog.driver-class=org.postgresql.Driver
iceberg.jdbc-catalog.connection-url=jdbc:postgresql://postgres-iceberg:5432/iceberg
iceberg.jdbc-catalog.connection-user=iceberg
iceberg.jdbc-catalog.connection-password=iceberg
iceberg.jdbc-catalog.schema-version=V1
# Хранилище файлов Iceberg – S3 (MinIO) через hadoop-клиент
iceberg.file-system.type=hadoop
fs.native-s3.enabled=true
s3.endpoint=http://minio:9000
s3.region=us-east-1
s3.path-style-access=true
s3.aws-access-key=minioadmin
s3.aws-secret-key=minioadmin
Что это даёт:
- Trino хранит метаданные Iceberg в PostgreSQL (таблицы каталога, снапшоты, манифесты и т.п.).
- Файлы данных лежат в MinIO, в бакете
lakehouse, к которому Trino ходит поs3:///s3a://через S3-клиент.
Пример создания схемы и таблицы из Trino:
-- Схема в каталоге lakehouse (метаданные в PostgreSQL)
CREATE SCHEMA lakehouse.default;
-- Таблица Iceberg с данными в s3://lakehouse/default/test_table/
CREATE TABLE lakehouse.default.test_table (
id bigint,
name varchar
);
Конфигурация Spark (spark-defaults.conf)
spark-defaults.conf монтируется в /opt/spark/conf/spark-defaults.conf в контейнеры Spark.
Ключевые моменты:
# Iceberg Spark extensions
spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
# Каталог Iceberg для Spark (JDBC, метаданные в Postgres)
spark.sql.catalog.lakehouse=org.apache.iceberg.spark.SparkCatalog
spark.sql.catalog.lakehouse.catalog-impl=org.apache.iceberg.jdbc.JdbcCatalog
spark.sql.catalog.lakehouse.uri=jdbc:postgresql://postgres-iceberg:5432/iceberg
spark.sql.catalog.lakehouse.jdbc.user=iceberg
spark.sql.catalog.lakehouse.jdbc.password=iceberg
spark.sql.catalog.lakehouse.jdbc.driver=org.postgresql.Driver
spark.sql.catalog.lakehouse.warehouse=s3a://lakehouse/warehouse
spark.sql.catalog.lakehouse.default-namespace=default
# S3/MinIO через s3a
spark.hadoop.fs.s3a.endpoint=http://minio:9000
spark.hadoop.fs.s3a.access.key=minioadmin
spark.hadoop.fs.s3a.secret.key=minioadmin
spark.hadoop.fs.s3a.path.style.access=true
spark.hadoop.fs.s3a.impl=org.apache.hadoop.fs.s3a.S3AFileSystem
spark.hadoop.fs.s3a.connection.ssl.enabled=false
Важно: Spark и Trino используют единый JDBC-каталог lakehouse: метаданные лежат в Postgres, данные — в MinIO. Таблица, созданная в Spark, видна в Trino без дополнительной настройки.
Пример создания таблицы из Spark:
from pyspark.sql import SparkSession
spark = (SparkSession.builder
.appName("lakehouse-demo")
.getOrCreate())
# Каталог lakehouse указан явно
spark.sql("""
CREATE TABLE lakehouse.default.spark_table (
id BIGINT,
name STRING
)
USING iceberg
""")
spark.sql("INSERT INTO lakehouse.default.spark_table VALUES (1, 'Alice'), (2, 'Bob')")
Файлы окажутся в s3a://lakehouse/warehouse/default/spark_table/.
Типовой учебный сценарий
- Поднять стенд (
docker compose build, затемdocker compose up -d). - Создать бакет
lakehouseв MinIO Console (если ещё нет). - Создать таблицу из Spark, записать туда данные, показать дерево файлов Iceberg в MinIO (data/manifest/metadata).
- Прочитать ту же таблицу из Trino (проверка общего каталога).
- Создать таблицу из Trino и прочитать её из Spark.
- Обсудить архитектуру: Postgres хранит метаданные Iceberg, MinIO — данные, Spark/Trino — compute.
Smoke-тесты Spark → Trino
Быстрая проверка, что таблица, созданная в Spark, читается в Trino через общий JDBC-каталог.
-
Убедиться, что стенд запущен:
docker compose up -d. -
Скопировать скрипты внутрь контейнеров:
docker compose cp src/spark/iceberg_smoke.py spark-master:/tmp/ docker compose cp src/trino/iceberg_smoke.sql trino:/tmp/ -
Выполнить smoke из Spark:
docker compose exec spark-master /opt/spark/bin/spark-submit /tmp/iceberg_smoke.pyСкрипт создаст
lakehouse.default.spark_trino_smoke, вставит строку1, from_sparkи прочитает её. -
Прочитать ту же таблицу из Trino:
docker compose exec trino trino --file /tmp/iceberg_smoke.sqlВ выводе должны быть строки
spark_trino_smokeв списке таблиц и1, from_sparkв результате выборки. -
Очистка (опционально):
docker compose exec spark-master /opt/spark/bin/spark-sql -e "DROP TABLE IF EXISTS lakehouse.default.spark_trino_smoke"
Дальнейшее развитие
Планируемые/возможные расширения:
- Подключить Airflow и запускать Spark-job’ы поверх этого же Lakehouse.
- Вынести настройки (
MINIO_ROOT_USER,ICEBERG_*,POSTGRES_*) в.envс шаблоном для студентов. - Добавить отдельные каталоги Trino (например,
hive,tpch) для демонстрации федеративных запросов. - Добавить пример интеграции с BI-инструментом (DBeaver/Metabase/Superset) поверх Trino.
Для пошаговых учебных сценариев (лабораторных работ) см. файл HOWTO.md.
Лицензия
Материалы этого репозитория лицензированы на условиях Creative Commons Attribution 4.0 International (CC BY 4.0).
См. файл LICENSE или https://creativecommons.org/licenses/by/4.0/.