Files
mini-lakehouse-lab/notebooks/01_environment_and_smoke_test.ipynb
ddadmin 688c46c68b feat(module-1): доработаны материалы модуля 1 и удалён legacy-ноутбук
- Зачем:
  - нужен воспроизводимый вход в курс и единое место хранения планов по модулям.
- Что:
  - добавлены `plans/README.md`, living plan Модуля 1, `START_HERE.md` и канонический ноутбук `01_environment_and_smoke_test.ipynb`, а `cluster_smoke.py` расширен до reusable helper и CLI smoke test.
  - уточнены onboarding-материалы и окружение: добавлены Spark UI в `README.md`, ресурсы хоста и креды MinIO в `START_HERE.md`, использован `NB_GID` в `jupyter/Dockerfile`, в ноутбуке усилены самостоятельные задания и добавлены `cell id`, а пояснения в `cluster_smoke.py` переведены на русский для студентов.
  - обновлены `README.md`, `AGENTS.md` и archive howto, удалены устаревшие `spark-basic-test.ipynb` и `03_partitioning_and_schema_evolution.ipynb`.
- Проверка:
  - `python3 -m py_compile src/spark/cluster_smoke.py src/spark/__init__.py`.
  - `docker compose build spark-master` и `docker compose build jupyter`.
  - `docker compose up -d`, `docker compose exec jupyter python3 -c "from spark.cluster_smoke import create_spark_session, run_cluster_smoke; spark=create_spark_session(app_name='module-01-validation'); print(run_cluster_smoke(spark)); spark.stop()"` и `docker compose exec jupyter jupyter nbconvert --to notebook --execute /opt/work/01_environment_and_smoke_test.ipynb --output-dir /tmp --output module1-validation-2.ipynb`.
2026-03-07 00:24:40 +03:00

214 lines
8.6 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"id": "module1-intro",
"metadata": {},
"source": [
"# Модуль 1. Вход в стенд и базовая диагностика\n",
"\n",
"Этот ноутбук является канонической практикой Модуля 1.\n",
"\n",
"На выходе ты должен:\n",
"\n",
"- понимать, что стенд уже поднят на хосте;\n",
"- подключиться к Spark-кластеру из Jupyter;\n",
"- выполнить базовый smoke test;\n",
"- сопоставить сервисы стенда с их ролями;\n",
"- знать первый маршрут диагностики через `docker compose ps`, логи и UI.\n"
]
},
{
"cell_type": "markdown",
"id": "module1-before-start",
"metadata": {},
"source": [
"## Перед стартом\n",
"\n",
"Перед запуском этого ноутбука пройди шаги из `START_HERE.md`.\n",
"\n",
"Важно: `docker compose build`, `docker compose up -d`, `docker compose ps` и просмотр логов выполняются на хосте, а не внутри Jupyter.\n",
"\n",
"Ожидаемое состояние перед началом:\n",
"\n",
"- контейнеры `spark-master`, `spark-worker-1`, `spark-worker-2`, `minio`, `postgres-iceberg`, `trino`, `jupyter` уже подняты;\n",
"- открываются `Spark UI`, `Trino UI`, `MinIO Console` и `JupyterLab`;\n",
"- ты работаешь в Jupyter внутри контейнера `jupyter`.\n"
]
},
{
"cell_type": "markdown",
"id": "module1-service-map",
"metadata": {},
"source": [
"## Карта сервисов\n",
"\n",
"| Сервис | Роль |\n",
"| --- | --- |\n",
"| `MinIO` | `storage`: объектное хранилище для данных и файлов Iceberg |\n",
"| `PostgreSQL` | `catalog`: хранит метаданные JDBC-каталога Iceberg |\n",
"| `Spark` | `compute`: выполняет PySpark и Spark SQL |\n",
"| `Trino` | `compute`: читает те же таблицы через общий каталог |\n",
"| `Jupyter` | Точка входа в учебные ноутбуки |\n",
"\n",
"В этом модуле мы не строим пайплайн и не создаём Iceberg-таблицы. Задача только одна: убедиться, что среда рабочая и понятная.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "module1-create-session",
"metadata": {},
"outputs": [],
"source": [
"from spark.cluster_smoke import (\n",
" create_spark_session,\n",
" format_smoke_report,\n",
" run_cluster_smoke,\n",
")\n",
"\n",
"spark = create_spark_session(app_name=\"module-01-environment-and-smoke-test\")\n",
"spark\n"
]
},
{
"cell_type": "markdown",
"id": "module1-cluster-demo",
"metadata": {},
"source": [
"## Демонстрация: подключение к кластеру\n",
"\n",
"Сначала посмотрим на базовые признаки того, что ноутбук говорит именно с кластером, а не с локальным `local[*]` режимом.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "module1-connection-details",
"metadata": {},
"outputs": [],
"source": [
"connection_details = {\n",
" \"app_name\": spark.sparkContext.appName,\n",
" \"master_url\": spark.sparkContext.master,\n",
" \"default_parallelism\": spark.sparkContext.defaultParallelism,\n",
" \"spark_version\": spark.version,\n",
"}\n",
"connection_details\n"
]
},
{
"cell_type": "markdown",
"id": "module1-visual-check",
"metadata": {},
"source": [
"Проверь глазами:\n",
"\n",
"- `master_url` должен быть `spark://spark-master:7077`, а не `local[*]`;\n",
"- `default_parallelism` должен быть больше `1`;\n",
"- в `Spark UI` должны быть видны master и worker-ы.\n"
]
},
{
"cell_type": "markdown",
"id": "module1-smoke-explanation",
"metadata": {},
"source": [
"## Демонстрация: Spark smoke test\n",
"\n",
"Smoke test запускает распределённое вычисление на `range(0, 1_000_000)` и сверяет детерминированный результат.\n",
"\n",
"Если тест проходит, это означает минимум следующее:\n",
"\n",
"- Jupyter может создать SparkSession;\n",
"- Spark подключён к кластерному master;\n",
"- задание действительно выполняется, а не падает на первом действии.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "module1-run-smoke",
"metadata": {},
"outputs": [],
"source": [
"smoke_report = run_cluster_smoke(spark)\n",
"print(format_smoke_report(smoke_report))\n",
"smoke_report\n"
]
},
{
"cell_type": "markdown",
"id": "module1-self-check",
"metadata": {},
"source": [
"## Самостоятельное повторение\n",
"\n",
"Сделай руками и проверь себя:\n",
"\n",
"1. Открой `Spark UI`, `Trino UI`, `MinIO Console` и `JupyterLab`.\n",
"2. Сопоставь каждый сервис с одной из ролей: `storage`, `catalog`, `compute`, `entrypoint`.\n",
"3. Объясни, почему этот smoke test не должен работать в `local[*]` режиме.\n",
"4. На хосте выполни `docker compose ps` и посмотри, какие контейнеры должны быть в состоянии `Up`.\n",
"5. На хосте выполни `docker compose logs -f trino` или `docker compose logs -f spark-master`, чтобы посмотреть, где начинается первичная диагностика.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "module1-service-roles",
"metadata": {},
"outputs": [],
"source": [
"service_roles = {\n",
" # Заполни значения самостоятельно: storage, catalog, compute или entrypoint.\n",
" \"MinIO\": \"TODO\",\n",
" \"PostgreSQL\": \"TODO\",\n",
" \"Spark\": \"TODO\",\n",
" \"Trino\": \"TODO\",\n",
" \"Jupyter\": \"TODO\",\n",
"}\n",
"service_roles\n"
]
},
{
"cell_type": "markdown",
"id": "module1-checkpoint",
"metadata": {},
"source": [
"## Checkpoint\n",
"\n",
"К концу модуля ты должен уметь подтвердить:\n",
"\n",
"- стенд поднят и основные контейнеры живы;\n",
"- `Spark UI`, `MinIO Console`, `Trino UI` и `JupyterLab` открываются;\n",
"- smoke test завершился успешно и вернул ожидаемый результат;\n",
"- ты понимаешь назначение `MinIO`, `PostgreSQL`, `Spark`, `Trino`, `Jupyter`;\n",
"- ты знаешь, что первый маршрут диагностики начинается с `docker compose ps`, `docker compose logs -f <service>` и проверки UI.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "module1-stop-session",
"metadata": {},
"outputs": [],
"source": [
"spark.stop()\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}