Skip to content

Руководство пользователя LakeHouse

Введение

LakeHouse (ЛКХ) — это современная платформа для работы с большими данными, построенная на принципе разделения вычислительных ресурсов (compute) и хранилища (storage).

Целевая аудитория: Дата-инженеры, аналитики данных и все специалисты, участвующие в процессах загрузки и обработки данных.

Текущий статус: Платформа находится на стадии пилотной эксплуатации. Состав сервисов и их конфигурация могут изменяться.

Быстрый старт

  1. Получите доступы к вашему неймспейсу в LakeHouse
  2. Изучите основные сервисы через KubeSphere
  3. Начните работу с JupyterHub для отладки кода
  4. Создайте первый ETL-проект по инструкции ниже

Архитектура и концепция

Основные отличия от Hadoop

Аспект Hadoop LakeHouse
Архитектура Связанные compute и storage Раздельные compute и storage
Масштабируемость Вертикальная (добавление узлов) Горизонтальная (независимое scaling)
Управление ресурсами Жесткое выделение Эластичное распределение
Стоимость Капитальные затраты Операционные затраты

Ключевые компоненты стека LakeHouse:

  • Compute: Kubernetes, Spark, StarRocks
  • Storage: S3-совместимое объектное хранилище
  • Табличный формат: Apache Iceberg
  • Оркестрация: Airflow 2.0

Эндпоинты сервисов

Платформенные сервисы

Сервис URL Назначение
Ozone http://s3balancer.ozone.company.local:9878 S3-совместимое хранилище
Iceberg REST proxy-adapter-rest-fixture.platform-ldap.svc.cluster.local:8000 REST-каталог Iceberg

Сервисы тенанта

Сервис URL шаблон Аутентификация
JupyterHub jupyterhub.{tenant_name}.starrocks-rnd.bd-cloud.company.local Keycloak (личные учетные данные)
CloudBeaver cloudbeaver.{tenant_name}.starrocks-rnd.bd-cloud.company.local Логин: {tenant_name}, пароль из секретов
Spark History spark.{tenant_name}.starrocks-rnd.bd-cloud.company.local -
StarRocks FE starrocks-fe-service.{tenant_name}.svc.cluster.local:9030 Пароль из секретов

Подключение к Iceberg

Правила именования

Для создания базы данных без указания location:

  • Название БД должно содержать {tenant_name}_
  • Пример: newtenant_database, rndteam_analytics

При указании location:

s3a://{tenant_name}/{database_name}/{table_name}

Где: - tenant_name - имя бакета - database_name - должно начинаться с {tenant_name}_

Настройка Spark сессии

Базовые настройки OAUTH и S3

import pyspark
import pyspark.sql

# Конфигурация подключения
configuration = {
    "spark.sql.extensions": "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions",
    "spark.sql.defaultCatalog": "wh",

    "spark.sql.catalog.wh": "org.apache.iceberg.spark.SparkCatalog",
    "spark.sql.catalog.wh.type": "rest",
    "spark.sql.catalog.wh.io-impl": "org.apache.iceberg.aws.s3.S3FileIO",
    "spark.sql.catalog.wh.uri": "http://proxy-adapter-rest-fixture.platform-ldap.svc.cluster.local:8000",

    "spark.sql.catalog.wh.s3.endpoint": "",
    "spark.sql.catalog.wh.s3.access-key-id": "",  # s3_access_key из секретов
    "spark.sql.catalog.wh.s3.secret-access-key": "",  # s3_secret_key из секретов
    "spark.sql.catalog.wh.s3.path-style-access": "true",
    "spark.sql.catalog.wh.s3.region": "us-east-1",

    "spark.sql.catalog.wh.rest.auth.type": "com.dremio.iceberg.authmgr.oauth2.OAuth2Manager",
    "spark.sql.catalog.wh.rest.auth.oauth2.client-id": "",  # client_id из keycloak
    "spark.sql.catalog.wh.rest.auth.oauth2.client-secret": "",  # client_secret из keycloak
    "spark.sql.catalog.wh.rest.auth.oauth2.grant-type": "password",
    "spark.sql.catalog.wh.rest.auth.oauth2.resource-owner.username": "",  # личный логин
    "spark.sql.catalog.wh.rest.auth.oauth2.resource-owner.password": "",  # личный пароль
    "spark.sql.catalog.wh.rest.auth.oauth2.issuer-url": "http://keycloak.platform-ldap.svc.cluster.local:80/realms/platform-ldap/",
}

# Создание сессии
spark_conf = pyspark.SparkConf().setMaster("local[*]")
for k, v in configuration.items():
    spark_conf = spark_conf.set(k, v)

spark = pyspark.sql.SparkSession.builder.config(conf=spark_conf).getOrCreate()

Настройка eventlog для S3

eventlog_config = {
    "spark.eventLog.dir": f"s3a://{tenant_name}/eventlog",
    "spark.hadoop.fs.s3a.access.key": "AWS_ACCESS_KEY",  # из секретов ozone
    "spark.hadoop.fs.s3a.secret.key": "AWS_SECRET_KEY",  # из секретов ozone
    "spark.hadoop.fs.s3a.impl": "org.apache.hadoop.fs.s3a.S3AFileSystem",
    "spark.hadoop.fs.s3a.endpoint": "",  # из секретов ozone
    "spark.hadoop.fs.s3a.path.style.access": "true",
    "spark.hadoop.fs.s3a.multiobjectdelete.enable": "false"  # обязательно для Ozone
}

Работа с Spark

Запуск в Kubernetes

import os
import socket

KUBERNETES_SERVICE_HOST = os.environ['KUBERNETES_SERVICE_HOST']
HOSTNAME = socket.gethostname()
HOST_IP = socket.gethostbyname(HOSTNAME)

k8s_config = {
    "spark.master": f"k8s://https://{KUBERNETES_SERVICE_HOST}:443",
    "spark.kubernetes.namespace": tenant_name,
    "spark.kubernetes.authenticate.serviceAccountName": "spark",
    "spark.driver.host": HOST_IP,
    "spark.driver.memory": "2g",
    "spark.driver.cores": "1",
    "spark.executor.instances": "2",
    "spark.kubernetes.executor.container.image": "registry.company.local/datafactory/spark-integration-test:1.0.17"
}

Подключение к Hadoop кластерам

Подготовка конфигурации

  1. Получите конфиги кластера:
  2. First: https://git.company.local/hdp/clusters/first/-/tree/config
  3. Second: https://git.company.local/hdp/second/-/tree/config
  4. Rnd: https://git.company.local/hdp/rnd/-/tree/config

  5. Настройте переменные окружения:

import os
os.environ["SPARK_CONF_DIR"] = "/home/jovyan/conf/"
os.environ["HADOOP_CONF_DIR"] = "/home/jovyan/conf/"

Конфигурация Hive и HDFS

hive_config = {
    "spark.sql.catalog.spark_catalog": "org.apache.iceberg.spark.SparkSessionCatalog",
    "spark.sql.catalog.spark_catalog.type": "hive",
    "spark.sql.catalog.spark_catalog.uri": "thrift://first-ha.company.local:9083",
    "spark.sql.catalog.spark_catalog.warehouse": "hdfs://ha",
    "spark.sql.catalog.spark_catalog.warehouse.dir": "/apps/hive/warehouse",

    "spark.hadoop.security.authentication": "kerberos",
    "spark.hadoop.security.authorization": "true",
    "spark.hadoop.hive.metastore.kerberos.principal": "hive/_HOST@company.local",
    "spark.hadoop.hive.metastore.uris": "thrift://first-ha.company.local:9083",
    "spark.hadoop.fs.defaultFS": "hdfs://namenode01.company.local:8020",
    "spark.kerberos.access.hadoopFileSystems": "hdfs://namenode01.company.local:8020",

    "spark.kubernetes.kerberos.krb5.path": "/home/jovyan/conf/krb5.conf"
}

Интеграция с StarRocks

Создание внешнего каталога

CREATE EXTERNAL CATALOG IcebergRest
PROPERTIES (
    "aws.s3.access_key" = "",
    "aws.s3.secret_key" = "",
    "aws.s3.endpoint" = "",
    "aws.s3.enable_path_style_access" = "true",
    "aws.s3.region" = "us-east-1",

    "type" = "iceberg",
    "iceberg.catalog.type" = "rest",
    "iceberg.catalog.uri" = "http://proxy-adapter-rest-fixture.platform-ldap.svc.cluster.local:8000",
    "iceberg.catalog.io-impl" = "org.apache.iceberg.aws.s3.S3FileIO",

    "iceberg.catalog.security" = "OAUTH2",
    "iceberg.catalog.oauth2-token-refresh-enabled" = "true",
    "iceberg.catalog.credential" = "client_id:client_secret",
    "iceberg.catalog.oauth2-server-uri" = "http://keycloak.platform-ldap.svc.cluster.local:80/realms/platform-ldap/protocol/openid-connect/token",

    "client.factory" = "com.starrocks.connector.iceberg.IcebergClientFactory"
);

Работа с данными в StarRocks

-- Использование каталога
SET CATALOG IcebergRest;

-- Создание базы данных (должно содержать имя тенанта)
CREATE DATABASE IF NOT EXISTS newtenant_database;
USE newtenant_database;

-- Создание таблицы
CREATE TABLE newtenant_database.test_table (
    country_code STRING,
    id INT,
    numb DOUBLE
);

Доступ к данным

Получение секретов в KubeSphere

  1. Перейдите в ваш проект в KubeSphere
  2. Выберите ConfigurationSecrets
  3. Для просмотра значений секрета нажмите MoreEdit Settings

Основные секреты:

  • ozone - доступы к S3-хранилищу
  • keycloak - client_id и client_secret для OAuth
  • cloudbeaver - пароль для доступа к CloudBeaver
  • starrocks - пароль для доступа к StarRocks

Работа с JupyterHub

Обновление сервера

Для применения изменений или обновления окружения:

  1. FileHub Control Panel → перезапустите сервер
  2. Или удалите pod через KubeSphere

Важно: Сохраняйте важные файлы перед перезапуском, используя систему контроля версий.

Настройка отображения

При проблемах с отображением ячеек:

  1. SettingsSettings EditorNotebook
  2. Настройте параметры:
  3. Number of cells to render outside the viewport
  4. The maximum number of output cells to be rendered in the output area
  5. Windowing mode: none (при необходимости)

Подключение к StarRocks через CloudBeaver

  1. Создайте новое подключение типа MySQL
  2. В настройках драйвера укажите:
authenticationPlugins: com.mysql.cj.protocol.a.authentication.MysqlClearPasswordPlugin
defaultAuthenticationPlugin: com.mysql.cj.protocol.a.authentication.MysqlClearPasswordPlugin
disabledAuthenticationPlugins: com.mysql.cj.protocol.a.authentication.MysqlNativePasswordPlugin
sslMode: REQUIRED
useSSL: true
verifyServerCertificate: false
  1. Авторизуйтесь под своей учетной записью

Работа с KubeSphere

Назначение: Визуальное управление ресурсами кластера.

Основные возможности:

  • Просмотр и управление подами
  • Мониторинг потребления ресурсов
  • Управление секретами и конфигурациями
  • Просмотр логов приложений

Работа с секретами:

  1. Перейдите в раздел ConfigurationSecrets
  2. Выберите нужный секрет
  3. Нажмите на иконку глаза для просмотра значений

Разработка ETL-проектов

Создание проекта

Используйте EverProject с шаблоном Kubernetes:

cookiecutter https://git.company.local/platform/everproject-templates.git
# Выберите: ci_templates = Kubernetes

Настройка GitLab CI/CD

Ключевые настройки:

  • Использование runner-ов с тегами docker и dmz
  • Настройка переменных для доступа к S3
  • Деплой DAG-файлов в S3 bucket

Docker-образы

Используйте базовые образы Spark для обеспечения совместимости:

FROM registry.company.local/platform/docker-images/spark/spark3.5:1.0.0

# Копирование приложения
COPY app /app
COPY requirements.txt .

# Установка зависимостей
RUN pip install -r requirements.txt

WORKDIR /app

Решение проблем

Kerberos аутентификация

Включение debug-логирования:

{"spark.driver.extraJavaOptions": "-Dsun.security.krb5.debug=true"}

Проблема с путем к krb5.conf:

{
    "spark.driver.extraJavaOptions": "-Djava.security.krb5.conf=/path/to/krb5.conf",
    "spark.executor.extraJavaOptions": "-Djava.security.krb5.conf=/opt/spark/conf/krb5.conf"
}

StarRocks: ошибка 403 ExpiredSignatureError

Причина: Проблемы с обновлением OAuth токена.

Решение: Пересоздайте внешний каталог (данные не будут удалены).

Spark: отображение Iceberg таблиц

Проблема: Не видны Iceberg таблицы при использовании нескольких каталогов.

Решение: Настройте spark_catalog как SparkSessionCatalog:

{
    "spark.sql.catalog.spark_catalog": "org.apache.iceberg.spark.SparkSessionCatalog",
    "spark.sql.catalog.spark_catalog.type": "hive"
}

Запись данных через Spark DataFrame

data.writeTo("prod.db.table") \
    .tableProperty("location", f"s3a://{tenant_name}/table_name") \
    .createOrReplace()

Регистрация существующих таблиц

spark.sql("""
CALL spark_catalog.system.register_table(
    table => 'db.tbl',
    metadata_file => 'path/to/metadata/file.json'
)
""")

Частые ошибки и решения

Ошибка: Table not found

# Проверка существования таблицы
if spark.catalog.tableExists("myproject_analytics.sales"):
    # Операции с таблицей
    pass
else:
    print("Таблица не существует")

Ошибка: Permission denied

# Проверка доступов в S3
aws s3 ls s3://myproject/myproject_analytics/ --endpoint-url http://bigdata-dn-0214.company.local:9878

Ошибка: Schema mismatch

# Принудительное приведение схемы
df.writeTo("myproject_analytics.sales").option("mergeSchema", "true").append()

Полезные ссылки