Конфигурация каталога
Мы знаем, что catalog это именованная конфигурация подключения к источнику. Осталось разобрать практику: как именно catalog описывается, что попадает в его файл, как Trino его загружает, и как добавить или удалить catalog без перезапуска кластера. Это знание прикладное — без него нельзя подключить ни один реальный источник.
Этот урок про catalog properties files, про управление секретами в них и про динамические каталоги.
Catalog properties file: анатомия
Catalog описывается одним текстовым файлом в директории etc/catalog/ установки Trino. Имя файла — без расширения — становится именем catalog. Файл etc/catalog/sales.properties создаёт catalog с именем sales.
Формат файла — простые пары ключ=значение, по одной на строку. Структура любого catalog properties file одинакова: ровно одно обязательное свойство и набор свойств, специфичных для коннектора.
Обязательное свойство — connector.name. Оно сообщает Trino, какую фабрику коннектора использовать. Всё остальное зависит от коннектора. Сравним два catalog:
# etc/catalog/tpch.properties — системный коннектор, больше ничего не нужно
connector.name=tpch
# etc/catalog/sales.properties — PostgreSQL, нужны адрес и учётные данные
connector.name=postgresql
connection-url=jdbc:postgresql://pg.internal:5432/sales
connection-user=trino_ro
connection-password=s3cr3t
# etc/catalog/lake.properties — Iceberg поверх S3-совместимого хранилища
connector.name=iceberg
iceberg.catalog.type=hive_metastore
hive.metastore.uri=thrift://metastore:9083
fs.native-s3.enabled=true
s3.endpoint=http://minio:9000
s3.region=us-east-1
Все три файла подчиняются одной схеме: connector.name плюс свойства, которые требует именно этот коннектор. Какие свойства доступны — всегда написано на странице коннектора в документации Trino. Заметьте, что имя catalog (sales, lake) никак не связано с типом коннектора — это вы выбираете сами.
connector.name у уже существующего catalog менять нельзя. Если нужно сменить тип коннектора, создаётся новый catalog с новым именем. На практике это редко требуется: чаще меняют параметры подключения внутри того же типа коннектора.
Как Trino загружает каталоги
Catalog properties files читаются при старте сервера. Для каждого файла в etc/catalog/ Trino берёт connector.name, находит зарегистрированную фабрику коннектора с этим именем (фабрики появились раньше — при загрузке плагинов) и просит её создать экземпляр коннектора, передавая остальные свойства из файла.
Здесь срабатывает разделение, которое мы вводили в уроке про коннекторы: плагин это код, catalog это его конкретное использование. Один плагин postgresql обслужит десять properties-файлов — получится десять независимых PostgreSQL-каталогов.
plugin/postgresql/ <- код коннектора, загружается один раз
etc/catalog/sales.properties <- catalog sales
etc/catalog/billing.properties <- catalog billing
etc/catalog/crm.properties <- catalog crm
Если файл содержит ошибку — неизвестный connector.name, отсутствует обязательное свойство коннектора, недостижим источник — поведение зависит от настройки catalog.management. В строгом режиме ошибка в catalog может помешать старту; в более терпимом — проблемный catalog просто не станет доступен, а остальные продолжат работать. В любом случае ошибки конфигурации catalog видны в логах сервера при старте.
Все catalog properties files должны присутствовать на каждой ноде кластера — и на coordinator, и на каждом worker. Конфигурация каталогов одинакова на всех нодах: worker должен уметь подключиться к источнику не хуже coordinator, ведь именно worker-ы читают данные. Если добавить properties-файл только на coordinator, запросы к этому catalog упадут: coordinator построит план, но worker-ы при попытке прочитать данные не найдут конфигурацию источника. На практике конфигурацию etc/ целиком раскатывают на все ноды одинаково — через образ контейнера, через систему управления конфигурацией или через примонтированный общий том.
Свойства, общие для коннекторов
Большинство свойств в properties-файле специфичны для коннектора, но есть набор настроек, которые ведут себя одинаково у многих коннекторов. Знать их полезно — они встречаются почти в каждом реальном catalog.
Для JDBC-коннекторов (PostgreSQL, MySQL, SQL Server, Oracle и других) общий каркас всегда один и тот же. Помимо обязательного connector.name, это connection-url (JDBC-строка подключения), connection-user и connection-password (учётные данные). Сверх этого JDBC-коннекторы делят группу настроек поведения:
# etc/catalog/sales.properties — типовой JDBC-catalog с общими настройками
connector.name=postgresql
connection-url=jdbc:postgresql://pg.internal:5432/sales
connection-user=trino_ro
connection-password=${ENV:PG_SALES_PASSWORD}
# Общие для JDBC-коннекторов настройки
case-insensitive-name-matching=true
metadata.cache-ttl=10m
join-pushdown.enabled=true
Что делают эти настройки. case-insensitive-name-matching управляет тем, как Trino сопоставляет имена схем и таблиц без учёта регистра — нужно, когда источник различает регистр, а пользователи пишут запросы как придётся. metadata.cache-ttl задаёт время жизни кэша метаданных: коннектор не дёргает источник за списком таблиц на каждый запрос, а помнит структуру указанное время — это снижает нагрузку на источник и ускоряет планирование. join-pushdown.enabled разрешает или запрещает проталкивать join между таблицами одного источника в сам источник.
Кэш метаданных (metadata.cache-ttl) — компромисс. Чем дольше TTL, тем меньше обращений к источнику и быстрее планирование, но тем дольше Trino не замечает изменения структуры таблиц, сделанные в обход него. Для стабильных схем TTL ставят больше, для часто меняющихся — меньше. Это типовая настройка, которую тюнят под конкретный источник.
Похожий принцип — у коннекторов object storage. Iceberg, Delta Lake, Hive делят свойства доступа к хранилищу и к metastore: тип metastore (hive.metastore или iceberg.catalog.type), его адрес, настройки нативной файловой системы для S3/Azure/GCS. Эти группы свойств одинаковы между разными коннекторами одной категории, потому что и читают они одно и то же — файлы на object storage через metastore.
Полный перечень свойств коннектора всегда на его странице в документации Trino. Но узнавать общий каркас полезно: увидев незнакомый JDBC-catalog, вы уже понимаете большую часть его файла, потому что каркас у всех JDBC-коннекторов общий.
Секреты в конфигурации
Catalog properties file часто содержит чувствительные данные — пароли, ключи доступа. Хранить пароль прямым текстом в connection-password=s3cr3t нежелательно: файл может попасть в систему контроля версий, в бэкап, в чужие руки.
Trino даёт механизм подстановки секретов из переменных окружения. Вместо литерального значения в properties-файле пишут ссылку на переменную окружения в фигурных скобках:
# etc/catalog/sales.properties — пароль не в файле, а в переменной окружения
connector.name=postgresql
connection-url=jdbc:postgresql://pg.internal:5432/sales
connection-user=trino_ro
connection-password=${ENV:PG_SALES_PASSWORD}
При загрузке catalog Trino подставит в connection-password значение переменной окружения PG_SALES_PASSWORD. Сам секрет в файле не хранится — файл можно безопасно держать в репозитории, а реальное значение приходит из окружения процесса (его задаёт оркестратор, секрет-менеджер, переменная контейнера).
Подстановка ${ENV:ИМЯ} работает для любого свойства, не только для паролей: так же выносят ключи доступа к object storage, токены, endpoint-ы, отличающиеся между окружениями. Это делает один и тот же properties-файл переносимым между dev, staging и prod — различия уходят в переменные окружения.
Статические и динамические каталоги
До сих пор мы говорили о статических каталогах: файл лежит в etc/catalog/, читается при старте. Чтобы добавить, изменить или удалить такой catalog, нужно поправить файл и перезапустить кластер. Для стабильного набора источников это нормально.
Но есть сценарии, где перезапуск неприемлем: на кластере крутятся запросы, а нужно подключить новый источник прямо сейчас. Для этого существуют динамические каталоги — возможность создавать и удалять catalog в работающем кластере без рестарта.
Динамическое управление каталогами включается настройкой catalog.management (значение, разрешающее создание/удаление, вместо статического режима по умолчанию). Когда оно включено, catalog создаётся прямо из SQL:
-- Создать catalog в работающем кластере, без рестарта
CREATE CATALOG analytics USING postgresql
WITH (
"connection-url" = 'jdbc:postgresql://pg.internal:5432/analytics',
"connection-user" = 'trino_ro',
"connection-password" = '${ENV:PG_ANALYTICS_PASSWORD}'
);
-- Удалить, когда источник больше не нужен
DROP CATALOG analytics;
CREATE CATALOG ... USING <коннектор> WITH (...) — это SQL-эквивалент properties-файла: имя catalog, имя коннектора, набор свойств. Команда выполняется на coordinator, и созданный catalog распространяется на воркеры. После CREATE CATALOG источник сразу доступен для запросов; после DROP CATALOG — недоступен. Перезапуск не нужен ни в том, ни в другом случае.
Динамические каталоги особенно полезны там, где набор источников меняется часто или непредсказуемо: мультиарендные платформы, среды, где пользователи подключают свои базы, автоматизированные системы, поднимающие источники по требованию. Для классического кластера со стабильным набором источников статических каталогов достаточно — и они проще в аудите, потому что вся конфигурация лежит файлами под версионным контролем.
Что выбрать
Сведём решение. Статические каталоги — выбор по умолчанию: конфигурация лежит файлами, она наглядна, версионируется, проходит code review. Динамические каталоги — когда набор источников по-настоящему динамичен и перезапуск кластера ради подключения источника недопустим. Многие production-кластеры обходятся только статическими; динамические добавляют гибкость ценой того, что часть конфигурации больше не живёт в файлах репозитория.
Независимо от выбора, два правила неизменны: connector.name обязателен и неизменен у существующего catalog, а секреты выносятся в переменные окружения через ${ENV:...}, а не пишутся в файл прямым текстом.
Попробуй сам
На кластере Trino потренируйтесь с конфигурацией каталогов:
- Зайдите в
etc/catalog/на сервере и откройте properties-файл системного коннектора (например,tpch.properties) и любого коннектора с подключением (например, PostgreSQL). Сравните: у первого толькоconnector.name, у второго — плюс параметры подключения. - Найдите в каком-нибудь properties-файле свойство с чувствительным значением. Если оно записано прямым текстом — продумайте, как переписать его через
${ENV:...}. - Если на кластере включено динамическое управление каталогами, выполните
SHOW CATALOGS, затемCREATE CATALOGдля нового tpch-каталога под другим именем, сноваSHOW CATALOGS, иDROP CATALOG. Убедитесь, что рестарт не понадобился. - Сформулируйте, почему catalog properties files обязаны лежать на всех нодах кластера, а не только на coordinator.