Learning Platform
Глоссарий Troubleshooting
Урок 14.05 · 22 мин
Средний
fault-toleranceoperationssecuritylimitations

Эксплуатация FTE: выделенный кластер, шифрование обмена, ограничения

Мы разобрали механику FTE: retry policies, exchange manager, task sizing, adaptive planning. Остался последний и самый практический слой — эксплуатация. Как FTE живёт в продакшене: на каком кластере его включать, как защитить спулённый обмен и где у режима границы, за которыми он не помогает.

Этот урок закрывает модуль практическими ответами: почему retry-policy=TASK хочет отдельный кластер, зачем спулённый обмен шифруют и что FTE не умеет в принципе.


Почему TASK хочет выделенный кластер

Главная эксплуатационная рекомендация: для retry-policy=TASK разворачивай выделенный кластер — отдельный от интерактивной нагрузки. Причина — в накладных расходах FTE, которые мы видели по всему модулю.

retry-policy=TASK материализует промежуток через exchange manager всегда, при каждом запросе, сбоя или нет. Спулинг промежутка стоит I/O и латентности: стадия-консьюмер ждёт, пока продьюсер полностью спулится, вместо старта на первых строках. Для долгого batch-запроса эта добавка теряется в часах работы. Для интерактивного запроса на полсекунды спулинг промежутка способен сам по себе превысить полезное время — пользователь получит ответ ощутимо медленнее, чем без FTE.

retry-policy задаётся на уровне кластера, в etc/config.properties. Нельзя сказать «этому запросу — TASK, тому — NONE»: вся нагрузка кластера живёт под одной политикой. Значит, кластер с TASK замедлит каждый запрос на нём, включая короткие. Если на нём же висят дашборды — они станут медленными.

Раздельные кластеры под разные политики
Интерактивный кластер: retry-policy=NONEДашборды, ad-hoc, короткие запросы. Минимальная латентность, нет накладных расходов FTE. Упавший редкий запрос дёшево перезапустить
batch уводим на отдельный кластер
Batch-кластер: retry-policy=TASKДолгие ETL, перестройки таблиц, тяжёлые отчёты. Отказоустойчивость на уровне задач. Накладные расходы спулинга теряются в часах работы

Отсюда типовая продакшен-архитектура: интерактивный кластер с retry-policy=NONE (быстрые дашборды и ad-hoc) и отдельный batch-кластер с retry-policy=TASK и настроенным exchange manager (отказоустойчивый ETL). Каждая нагрузка — на кластере с подходящей именно ей политикой.

Airflow: оркестрация batch-пайплайнов
NOTE

Маршрутизировать запросы между такими кластерами помогает Trino Gateway (ему посвящён отдельный урок в модуле про безопасность и деплой): он даёт клиентам единый URL и направляет интерактивные запросы на NONE-кластер, а batch — на TASK-кластер по правилам маршрутизации. Так разделение кластеров остаётся прозрачным для пользователей.


Шифрование спулённого обмена

FTE создаёт то, чего в классическом Trino не было, — промежуточные данные запроса, лежащие в хранилище. Это вопрос безопасности. Промежуток — это реальные данные запроса: значения после фильтров, ключи и строки join, частичные агрегаты. Если они оседают в S3/GCS незашифрованными, любой, у кого есть доступ к бакету, может их прочитать.

Поэтому FTE по умолчанию шифрует спулённый обмен. За это отвечает свойство fault-tolerant-execution.exchange-encryption-enabled — и по умолчанию оно true. Шифрование включено из коробки, отключать его в продакшене не следует.

Механика устроена аккуратно: на каждый запрос генерируется отдельный случайный ключ шифрования. Промежуток запроса шифруется этим ключом перед записью в хранилище и расшифровывается при чтении. Ключ живёт ровно столько, сколько запрос. Запрос завершился — ключ больше не нужен. Свой ключ на каждый запрос означает, что компрометация данных одного запроса не открывает данные других.

Шифрование спулённого обмена: ключ на запрос
Промежуток запросаРеальные данные: значения после фильтров, ключи и строки join, частичные агрегаты. До exchange manager — в памяти воркера
шифрование ключом запроса
Зашифрованный спул в хранилищеВ S3/GCS промежуток лежит зашифрованным. Свой случайный ключ на каждый запрос: компрометация одного запроса не вскрывает другие
расшифровка при чтении
Консьюмер читает промежутокСтадия-консьюмер расшифровывает промежуток тем же ключом запроса. Ключ живёт ровно столько, сколько сам запрос
# etc/config.properties — шифрование спулённого обмена FTE
# Дефолт true; в продакшене оставляем включённым
fault-tolerant-execution.exchange-encryption-enabled=true
DANGER

Не отключай fault-tolerant-execution.exchange-encryption-enabled в продакшене. Без шифрования промежуточные данные всех запросов оседают в объектном хранилище в открытом виде. Это утечка: фрагменты чувствительных данных — после WHERE-фильтров, в join-ключах — становятся доступны любому с доступом к спул-бакету. Накладные расходы шифрования малы по сравнению с этим риском.


Границы FTE: что режим не умеет

FTE мощный, но не всемогущий. Понимать его границы так же важно, как механику, — иначе на него возлагают надежды, которые он не оправдает.

FTE покрывает только инфраструктурные сбои. Режим ретраит сбои инфраструктуры: упавший воркер, потерянная нода, сбой железа, обрыв сети, вытеснение пода Kubernetes. Только это.

FTE не ретраит ошибки пользователя. Запрос с синтаксической ошибкой SQL, обращение к несуществующей таблице, деление на ноль, нарушение типов — такие запросы FTE не делает «отказоустойчивыми». И это правильно: такой запрос неверен по сути, повторять его бессмысленно — он упадёт с той же ошибкой хоть сто раз. FTE ретраит инфраструктуру, а не логику запроса.

Не все коннекторы поддерживают FTE. FTE-режим совместим не с каждым коннектором. Перед тем как полагаться на FTE с конкретным источником данных, это нужно проверить по документации той версии Trino, что развёрнута, — поддержка коннекторов в FTE расширяется со временем, и список меняется между релизами.

Класс ситуацииFTE помогает
Воркер упал по OOMДа — инфраструктурный сбой
Нода потеряна, сбой железаДа — инфраструктурный сбой
Под Kubernetes вытесненДа — инфраструктурный сбой
Обрыв сети между нодамиДа — инфраструктурный сбой
Синтаксическая ошибка в SQLНет — ошибка пользователя
Обращение к несуществующей таблицеНет — ошибка пользователя
Деление на ноль, нарушение типовНет — ошибка пользователя
Коннектор без поддержки FTEНет — проверять по документации
WARNING

Частое заблуждение: «включили FTE — Trino стал отказоустойчив как Spark, теперь не упадёт никогда». Нет. FTE спасает от сбоев инфраструктуры, но запрос всё равно упадёт от собственной ошибки, от исчерпания лимита попыток ретраев, от неподдерживаемого коннектора. FTE снижает класс рисков, а не отменяет падения как явление.


Эксплуатационный чек-лист FTE

Соберём практику модуля в список — что проверить, разворачивая FTE в продакшене:

  1. Профиль нагрузки. Кластер batch (долгие ETL, отчёты)? -> retry-policy=TASK. Кластер с множеством мелких запросов? -> retry-policy=QUERY. Интерактив? -> retry-policy=NONE, FTE не нужен.
  2. Отдельный кластер под TASK. Не вешай retry-policy=TASK на тот же кластер, что обслуживает дашборды, — он замедлит каждый запрос. Batch — на выделенном кластере.
  3. Exchange manager на всех нодах. Для TASKetc/exchange-manager.properties идентичен на координаторе и всех воркерах; exchange.base-directories указывает на нодонезависимое хранилище (S3/GCS/Azure/HDFS), не на локальный диск.
  4. Шифрование включено. fault-tolerant-execution.exchange-encryption-enabled оставь true.
  5. Объём спул-хранилища. Рассчитай под пиковый промежуток одновременно идущих FTE-запросов; опционально настрой lifecycle policy бакета как страховку от мусора.
  6. Совместимость коннекторов. Проверь по документации текущей версии, что коннекторы твоих источников поддерживают FTE.
  7. Параметры ретраев. При необходимости настрой query-retry-attempts / task-retry-attempts-per-task и параметры backoff под свой кластер.

Пройдя этот список, ты получаешь то, ради чего затевался весь модуль: кластер, на котором долгий batch-запрос переживает сбой воркера, не начиная с нуля, — при честном понимании цены и границ режима.


Попробуй сам

Доведи FTE-кластер до продакшен-готовности на тестовом стенде.

  1. Возьми batch-кластер из прошлых уроков (retry-policy=TASK, exchange manager на MinIO). Проверь, что fault-tolerant-execution.exchange-encryption-enabled не выключен.
  2. Запусти долгий batch-запрос и во время исполнения убей воркер (docker kill) — убедись, что запрос пережил сбой за счёт переисполнения задач.
  3. Теперь проверь границу режима: запусти запрос с заведомой ошибкой пользователя — например, SELECT * FROM nonexistent_table или запрос с делением на ноль. Убедись, что FTE его НЕ спасает — он падает сразу, без ретраев. Прочитай текст ошибки.
  4. Продумай раздельную архитектуру: какой кластер ты дашь дашбордам и какой ETL, какие retry-policy пропишешь каждому и почему retry-policy нельзя задать на уровне отдельного запроса.

Цель — закрепить, что FTE спасает от инфраструктурных сбоев, но не от ошибок пользователя, и что retry-policy=TASK — это режим выделенного batch-кластера.


Проверка знанийKnowledge check
Почему для retry-policy=TASK рекомендуется выделенный кластер, отдельный от интерактивной нагрузки? И почему FTE не делает запрос с синтаксической ошибкой SQL отказоустойчивым?
ОтветAnswer
retry-policy=TASK материализует промежуточные данные обмена через exchange manager всегда — при каждом запросе, независимо от того, случился сбой или нет. Спулинг промежутка стоит I/O и латентности: стадия-консьюмер ждёт, пока продьюсер полностью спулится, вместо того чтобы начать на первых же строках. Для долгого batch-запроса эта добавка теряется в часах работы, но для интерактивного запроса на полсекунды спулинг промежутка способен сам по себе превысить полезное время. При этом retry-policy задаётся на уровне кластера, в config.properties, — нельзя назначить одному запросу TASK, а другому NONE: вся нагрузка кластера живёт под одной политикой. Значит, кластер с TASK замедлит каждый запрос на нём, включая короткие дашбордные. Поэтому batch с retry-policy=TASK выносят на выделенный кластер, а интерактив оставляют на отдельном кластере с retry-policy=NONE — каждая нагрузка получает подходящую ей политику. FTE не делает запрос с синтаксической ошибкой SQL отказоустойчивым, потому что FTE покрывает только инфраструктурные сбои — упавший воркер, потерянную ноду, сбой железа или сети, вытеснение пода Kubernetes. Синтаксическая ошибка — это ошибка пользователя, запрос неверен по сути. Повторять его бессмысленно: он упадёт с той же самой ошибкой хоть сто раз подряд, потому что проблема не в инфраструктуре, а в самом тексте запроса. FTE ретраит инфраструктуру, а не логику запроса — и это правильное поведение, иначе режим бесконечно повторял бы заведомо нерабочие запросы.

Проверьте понимание

Результат: 0 из 0
Аналитический
Вопрос 1 из 4. Почему для retry-policy=TASK рекомендуется выделенный кластер, отдельный от интерактивной нагрузки?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5