Эксплуатация: безопасность, мониторинг, FTE — обзор
Платформа RetailScope построена и оттюнена. Но построенная платформа и эксплуатируемая платформа — разные вещи. Этот финальный урок переводит RetailScope из «работает на моём docker-compose» в «работает в продакшене»: добавляем безопасность, мониторинг, fault-tolerant режим для тяжёлых нагрузок. И в конце — обзор всего пути курса.
Эксплуатация — это то, что отличает учебный проект от системы, которой доверяют бизнес-данные. Три её опоры: данные защищены, состояние видно, отказы не роняют работу.
Безопасность: закрыть платформу
В нашем docker-compose RetailScope открыта настежь: HTTP без шифрования, без аутентификации, креды открытым текстом. Для локального обучения это нормально, для продакшена недопустимо. Закрываем по слоям.
TLS/HTTPS — базовый слой. Без шифрования канала учётные данные и сами данные идут по сети открытым текстом. Большинство методов аутентификации в Trino вообще требуют TLS.
Аутентификация — проверка, кто подключается. Trino поддерживает PASSWORD (в том числе через файл паролей или LDAP), LDAP, OAUTH2, KERBEROS, JWT, CERTIFICATE. Для RetailScope разумен PASSWORD через LDAP или OAUTH2 — интеграция с корпоративными учётными записями. Включается на координаторе; вместе с ней настраивают shared secret для внутренней коммуникации.
Авторизация — что пользователю разрешено. Аутентификация says «это аналитик Иванов», авторизация решает, к каким каталогам, схемам и таблицам у Иванова доступ. Варианты: file-based access control (правила в JSON), Apache Ranger, Open Policy Agent. Для RetailScope file-based access control обычно достаточно: например, дашбордному пользователю выдают доступ только на чтение слоя marts, а на raw — нет.
Управление секретами. Креды PostgreSQL и ключи S3, которые мы в уроке развёртывания записали в .properties открытым текстом, в продакшене так не хранят. Trino поддерживает механизм secrets и подстановку чувствительных значений из переменных окружения.
Web UI координатора показывает тексты SQL-запросов, имена пользователей, структуру данных — это чувствительная информация. В продакшене Web UI закрывают аутентификацией наравне с самим Trino. Открытый Web UI на проде — это утечка: любой, кто до него дотянется, видит, кто какие данные запрашивает.
Мониторинг: сделать состояние видимым
Web UI показывает «сейчас» и забывает прошлое. Эксплуатируемой платформе нужен непрерывный мониторинг с историей и алертами — это машинная наблюдаемость из модуля 15.
Для RetailScope собираем минимальный, но рабочий мониторинг:
- Источник метрик — OpenMetrics-эндпойнт
/metricsна координаторе и воркерах. Он отдаёт JMX-метрики Trino в формате, который понимает Prometheus. - Сбор и хранение — Prometheus периодически делает scrape
/metricsи хранит метрики как временные ряды. - Визуализация и алерты — Grafana строит дашборды поверх Prometheus.
Что выносим на дашборд эксплуатации RetailScope и на какие алерты подписываемся:
| Метрика | Сигнал, требующий внимания |
|---|---|
| Running / queued queries | Очередь устойчиво растёт — кластеру не хватает ёмкости |
| Heap воркеров | Стабильно выше 85% — риск OOM |
| GC pause time | Длинные или частые паузы — деградация |
| Failed queries rate | Скачок относительно фона |
| Worker count | Просадка — воркеры отваливаются |
| Cache hit rate | Низкий — filesystem caching не работает |
Сюда же — event listeners. Для RetailScope подключаем OpenLineage event listener: он даёт долговременную историю запросов и data lineage — какие витрины из каких источников собраны. Это закрывает аудит и impact-анализ, которых нет в Web UI.
Fault-tolerant execution для тяжёлых нагрузок
По умолчанию Trino stateless: сбой воркера роняет запрос целиком — нет состояния, чтобы продолжить. Для дашбордов RetailScope это терпимо: запросы короткие, перезапустить дёшево. Но пересборка больших витрин — длинный запрос; уронить его на 40-й минуте из-за одного воркера обидно.
Для таких нагрузок есть fault-tolerant execution (FTE). Идея: промежуточные данные обмена спулятся во внешнее хранилище и могут быть переиспользованы — при сбое воркера Trino повторяет не весь запрос, а только потерянную часть.
FTE настраивается двумя вещами. Retry policy — что ретраить:
retry-policy=NONE— по умолчанию, без отказоустойчивости.retry-policy=QUERY— ретрай запроса целиком; хорош для кластера множества мелких запросов.retry-policy=TASK— ретрай отдельных задач; для больших batch-запросов; требует exchange manager.
Exchange manager — где спулятся промежуточные данные. Для retry-policy=TASK он обязателен. Файл etc/exchange-manager.properties на всех нодах:
exchange-manager.name=filesystem
exchange.base-directories=s3://retailscope/exchange-spool
Для RetailScope разумная стратегия — не включать FTE на основном кластере. Дашбордам FTE добавляет задержку и не нужен, а retry-policy=TASK рекомендуется на выделенном кластере. Практичное решение: основной кластер с retry-policy=NONE для интерактивной нагрузки, и при необходимости отдельный кластер с retry-policy=TASK под тяжёлую пересборку витрин.
FTE покрывает только инфраструктурные сбои — упал воркер, потеряна нода. Ошибку в самом запросе — синтаксис SQL, нехватка прав, деление на ноль — FTE не ретраит и не должен: повтор заведомо неверного запроса бессмысленен. И FTE — это компромисс: отказоустойчивость в обмен на задержку и спулинг промежуточных данных. Поэтому его включают там, где цена сбоя длинного запроса высока, а не «на всякий случай».
От docker-compose к продакшен-развёртыванию
Платформа RetailScope разворачивалась на docker-compose — это правильно для разработки и обучения, но продакшен требует ещё одного шага. Стоит понять, что именно меняется, а что нет.
Не меняется топология. Координатор, воркеры, каталоги, разделение хранения и вычислений — вся архитектура переносится один в один. Это и было смыслом выбора docker-compose: та же структура, что отлаживалась локально, идёт в прод.
Меняется оркестратор. В продакшене Trino обычно разворачивают на Kubernetes — для этого есть официальный Helm chart. Воркеры становятся репликами деплоймента, и их число можно менять автоматически: автоскейлинг (через HPA или KEDA) добавляет воркеры под нагрузку и убирает в простое. Это прямое продолжение того, что мы видели при ручном добавлении контейнера-воркера, — только теперь масштабированием управляет кластер.
Появляется важная эксплуатационная деталь — graceful shutdown. Когда воркер надо вывести (при обновлении версии, при автоскейл-вниз), его нельзя просто убить: на нём могут исполняться задачи. Trino поддерживает graceful shutdown — воркер переводится в состояние SHUTTING_DOWN, перестаёт принимать новые задачи, доводит до конца текущие и только затем останавливается. Без этого каждое обновление кластера роняло бы запросы. На Kubernetes graceful shutdown интегрируют с жизненным циклом пода.
Для совсем больших инсталляций перед кластерами Trino ставят Trino Gateway — балансировщик и маршрутизатор для нескольких кластеров. Он даёт клиентам единый URL, распределяет нагрузку и позволяет обновлять кластеры без простоя (blue/green): запросы переключаются на новый кластер, старый гасится через graceful shutdown. Для RetailScope на старте это избыточно — один кластер достаточен, — но это естественный следующий шаг роста платформы.
Обзор: путь курса на одном проекте
RetailScope собрал воедино весь курс. Пройдём путь и увидим, где какой модуль проявился.
| Этап RetailScope | Какие знания курса применены |
|---|---|
| Постановка и архитектура | Trino как query engine, не БД; федерация vs ETL |
| Развёртывание кластера | MPP-архитектура: координатор, воркеры, discovery; конфигурация |
| Каталоги и коннекторы | Модель catalog-schema-table; Connector SPI |
| Загрузка в Iceberg | Lakehouse, формат таблиц, snapshots, обслуживание |
| Федеративный слой | Коннекторы RDBMS, pushdown, антипаттерны федерации |
| Тюнинг | Жизненный цикл запроса, CBO, статистика, dynamic filtering |
| Память и ресурсы | Модель памяти, resource groups, изоляция нагрузки |
| Эксплуатация | Безопасность, наблюдаемость, fault-tolerant execution |
Главное, что должно остаться после курса, — не список фактов, а модель мышления. Trino — распределённый SQL-движок без своего хранилища: он не база данных, а слой исполнения поверх чужих данных. Его скорость — от MPP, pipelined-исполнения и колоночных векторизованных операторов, а не от кеширования. Запрос проходит путь от SQL-текста через AST, анализ, логический план, оптимизатор, фрагментацию на стадии — к задачам, сплитам, драйверам, операторам. И тюнинг — это всегда измерить, найти узкое место, применить рычаг, измерить снова.
С этой моделью любая новая возможность Trino — новый коннектор, новый тип, новая фича релиза — ложится на готовый каркас. Релизы Trino выходят каждые одну-четыре недели; курс дал не снимок версии 481, а каркас, на который наматывается всё остальное.
Попробуй сам
Финальное задание — провести ревизию эксплуатационной готовности RetailScope.
- Пройдите по своему развёртыванию и составьте список всего, что небезопасно для продакшена: HTTP вместо HTTPS, отсутствие аутентификации, креды в
.properties, открытый Web UI. Для каждого пункта напишите, какой механизм Trino его закрывает. - Включите OpenMetrics: откройте
/metricsна координаторе и выпишите 5 метрик, которые вы бы вынесли на дашборд эксплуатации, и пороги алертов для них. - Подключите OpenLineage event listener в режиме CONSOLE, выполните построение витрины
mart_sales_enrichedи найдите в логах события lineage — какие входные датасеты у витрины. - Решите для RetailScope: каким нагрузкам нужен FTE, а каким нет, и почему вы бы вынесли FTE на отдельный кластер, а не включили на основном.
- Итоговое: пройдите по таблице «этап — знания курса» и для каждого этапа RetailScope назовите по памяти один ключевой факт или решение, которое вы теперь понимаете глубже, чем в начале курса.
Цель — закрыть проект осознанием полного цикла: от пустого каталога до защищённой, наблюдаемой, отказоустойчивой платформы — и увидеть, как весь курс сложился в одну работающую систему.