- Зачем: - нужно убрать устаревший учебный маршрут из student-facing документов, но сохранить старые лабораторные как reference-материал. - Что: - HOWTO.md перенесен в docs/archive/legacy_howto.md и помечен как архивный legacy-документ. - README.md больше не отправляет студента в устаревший HOWTO и ссылается на актуальную программу курса. - Проверка: - просмотрен git diff -- README.md HOWTO.md docs/archive/legacy_howto.md. - проверен git diff --cached --stat перед коммитом.
Учебный 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:
-
Актуальная структура курса описана в
docs/course_program.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.
Актуальная структура курса описана в docs/course_program.md. Старый HOWTO сохранён как архивный материал в docs/archive/legacy_howto.md.
Лицензия
Материалы этого репозитория лицензированы на условиях Creative Commons Attribution 4.0 International (CC BY 4.0).
См. файл LICENSE или https://creativecommons.org/licenses/by/4.0/.