dbt

Junior

Как развернуть dbt так, чтобы он реально запускался по расписанию в проде?

У самого dbt нет планировщика — dbt run просто выполняется один раз и завершается. Заставить его запускаться автоматически, надёжно, по расписанию — это целиком решение, которое вы принимаете вне dbt.

Читать на:
dbt Cloud Airflow / Dagster cron + раннер CI
Примерно сколько инфраструктуры планирования/оркестрации каждый вариант оставляет строить вам, от меньшего к большему — не измеренная статистика.

Запуск `dbt build` с вашего ноутбука доказывает, что проект работает. Заставить его запускаться каждое утро в 6, повторять попытку при временных ошибках хранилища и кого-то оповещать, когда это не сработало — это деплой, и dbt намеренно не имеет мнения о том, как вы это делаете.

Три реальных варианта и что каждый берёт на себя

dbt Cloud целиком владеет планировщиком, историей прогонов и логикой повторов — вы настраиваете расписание в его UI, и он делает остальное, ценой работы внутри инфраструктуры dbt Labs, а не вашей. Свой оркестратор (Airflow, Dagster, Prefect) обращается с прогоном dbt как с одной задачей в большем DAG — правильный выбор, когда dbt — один шаг среди нескольких (извлечение, загрузка, трансформация dbt, downstream-экспорт), которые нужно упорядочить и которые зависят друг от друга, а не просто запускать по часам. Обычный cron плюс раннер CI (запланированный workflow GitHub Actions, cron-задача на VM) — самый простой вариант и полностью достаточный для проекта без межинструментальных зависимостей — просто не тянитесь к нему, как только вам реально понадобятся повторы, оповещения или зависимости на уровне DAG, которые он не даёт бесплатно.

# весь "планировщик" в подходе cron/CI - dbt здесь ничего не делает 0 6 * * * cd /opt/dbt_project && dbt build >> /var/log/dbt.log 2>&1

За что вы отвечаете независимо от выбора

Две вещи, которые dbt реально не берёт на себя ни в одной из этих настроек. Во-первых, креды — profiles.yml (или конфиг подключения dbt Cloud) всё ещё нуждается в реальных кредах к хранилищу там, где прогон реально выполняется, следуя тому же паттерну env_var()-а-не- хардкода независимо от планировщика. Во-вторых, оповещение о сбое — упавший dbt build выходит с ненулевым кодом, но никого не будят, если окружающий оркестратор не настроен проверять этот код выхода и оповещать. У dbt Cloud это встроено; Airflow/Dagster нужно настроить это как часть DAG; обычному cron нужно прикрутить это явно (обёрточный скрипт, проверяющий $? и обращающийся к Slack/PagerDuty или аналогу).

Ошибка, для предотвращения которой существует этот раздел: cron-задача, которая тихо перестаёт запускаться (передеплоенная VM без crontab, случайно отключённый файл CI-workflow), не выдаёт вообще никакой ошибки — не упавший прогон, а просто отсутствие прогона. Проверки freshness на таблицах, которые она должна была обновить (см. статью про freshness в sources.yml), — вот что реально это ловит, а не сам планировщик.

Где здесь место opti-pipe, а где нет

Ни один из этих выборов планирования не меняет того, что читает opti-pipe — движок правил смотрит на run_results.json, который любой из этих вариантов производит одинаково, поскольку это собственный вывод dbt независимо от того, что запустило прогон. Чего он не может сказать — произошёл ли прогон вообще или по расписанию — это целиком работа слоя деплоя, и стоит проверять независимо (дашборд, проверка freshness, реальное оповещение), а не считать, что тишина значит «всё в порядке».

Посмотрите, как это выглядит на вашем собственном пайплайне.

Загрузите реальный event log Spark, run_results.json от dbt или экспорт метрик Flink — и получите конкретные рекомендации, которые нужно одобрить, а не ещё одно эмпирическое правило.