Пайплайны по расписанию рядом с вашими API
Запускайте serverless cron-задачи как пайплайны по расписанию: история запусков рядом с HTTP-вызовами, настраиваемые ретраи, общие секреты и логи — ночная работа использует те же функции, что и ваши REST-эндпоинты.
Обновлено: 2026-06-28
Кратко
Суть ответа
Пайплайны по расписанию рядом с вашими API. Один и тот же ID функции может обслуживать HTTP-маршрут и шаг пайплайна по расписанию — без дублирования деревьев кода.
Когда подходит
- Ночной ETL
- Ротация сертификатов или токенов
- Периодический опрос интеграций
На что обратить внимание
- Таймеры повышают надёжность срабатывания, но не дают изоляции зависимостей и общих секретов и логов, которыми уже пользуются ваши HTTP-обработчики.
- Всё равно нужно одно место для ретраев, истории запусков и алертов — иначе задачи по расписанию остаются невидимыми рядом с продакшен-API.
Нагрузка и где ломается
Почему hosted cron и crontab подводят
- Crontab на VPS: вывод уходит в почту root; встроенных ретраев нет
- systemd timers: надёжное срабатывание, но разрозненные логи и секреты вручную
- Kubernetes CronJob: надёжные примитивы, но накладные расходы кластера для маленьких команд
Cron-задачи падают тихо, когда их единственный вывод уходит в почту root или в случайные лог-файлы, которые никто не читает.
Если расписания живут только на VPS, на вас расхождение окружений, расползание секретов и отладка в духе «кто перезапускал cron?» — каждый инцидент превращается в археологию по SSH.
Записи crontab живут вне версионируемого пайплайна деплоя, и никто не знает, какой бинарник запускался прошлой ночью.
Перекрывающиеся запуски портят общее состояние, если нет защиты skip-if-running, — пайплайнам по расписанию нужна та же строгость, что и обработчикам вебхуков.
Когда простых рецептов недостаточно
Почему одних таймеров недостаточно
Таймеры повышают надёжность срабатывания, но не дают изоляции зависимостей и общих секретов и логов, которыми уже пользуются ваши HTTP-обработчики.
Всё равно нужно одно место для ретраев, истории запусков и алертов — иначе задачи по расписанию остаются невидимыми рядом с продакшен-API.
Как помогает Inquir
Одна платформа для API и расписаний
Один и тот же ID функции может обслуживать HTTP-маршрут и шаг пайплайна по расписанию — без дублирования деревьев кода.
Cron-выражения проверяются при сохранении пайплайна; воркер хранит nextRunAt для каждого пайплайна, поэтому правки перепланируются аккуратно, а история запусков остаётся доступной для запросов.
Сравнение
crontab, systemd timers, Kubernetes CronJob и Inquir
Выбор планировщика зависит от зрелости эксплуатации и того, где уже живёт остальной стек. Таблица сравнивает четыре типичных подхода к повторяющейся бэкенд-работе — не edge-cron и не субсекундные тики.
| Критерий | crontab | systemd timers | Kubernetes CronJob | Пайплайны Inquir по расписанию |
|---|---|---|---|---|
| Настройка и сопровождение | Правка crontab на хосте; выражение не проверяется при сохранении | Unit- и timer-файлы; надёжнее срабатывание, но упаковка всё ещё на уровне хоста | YAML-манифесты и работающий кластер — даже для одной ночной задачи | Cron на триггере пайплайна; выражение проверяется при сохранении |
| История запусков | Перенаправление stdout в файл или почту root — без структурированного аудита | journalctl по unit; при росте числа задач — grep по сервисам | Логи подов и статус Job; хранение зависит от стека логирования кластера | Записи вызовов рядом с HTTP-выполнениями — доступны без SSH |
| Ретраи при сбое | Нет — следующее срабатывание и есть единственный неявный ретрай | OnFailure= может перезапустить unit; политики ретраев на запуск в продуктовом UI нет | backoffLimit у Job; настраивается в манифесте, не рядом с историей API | Число ретраев и задержка на каждом шаге пайплайна |
| Секреты | .env на сервере или inline в shell — общие для всех задач на хосте | EnvironmentFile в unit; ротация по-прежнему вручную на каждом хосте | Kubernetes Secrets — нативно для кластера, но отдельно от авторизации на шлюзе приложения | Секреты воркспейса, общие с HTTP-маршрутами — без параллельного .env на сервере |
| Изоляция между задачами | Один UNIX-пользователь и окружение интерпретатора — конфликты зависимостей типичны | Можно запускать от разных пользователей; всё равно одна машина, общее ядро | Под на запуск — сильная изоляция, когда кластер уже оправдан | Контейнер на вызов — та же модель изоляции, что у синхронных HTTP-обработчиков |
| Версионирование вместе с кодом | Строки crontab часто живут вне пайплайна деплоя | Unit-файлы могут лежать в git; расхождение между хостами всё равно случается | Манифесты в git/GitOps — отлично, когда K8s уже control plane | Бандлы функций и конфиг пайплайна версионируются вместе с деплоем платформы |
| Многошаговые воркфлоу | Shell-скрипты с цепочкой команд — непрозрачные точки сбоя | Отдельные unit или bash в ExecStart — ручная оркестрация | Один контейнер на CronJob; для DAG нужны Argo/Workflows или аналоги | Графы пайплайнов с рёбрами — extract, transform, load как узлы-функции |
| Перекрытие / долгие прогоны | Ручной flock или надежда — параллельные запуски портят общее состояние | Настройки concurrency на unit — логику всё равно пишете сами в обработчике | concurrencyPolicy Forbid/Replace в спецификации CronJob | Защита skip-if-running и ключи идемпотентности в обработчике или в дизайне пайплайна |
| Когда уместно | Одна VPS, один инженер, скрипты уже работают и редко падают | Linux-команды эксплуатации на systemd, готовые копать journal | Продукт уже на Kubernetes с GitOps и логированием кластера | Пайплайны по расписанию и REST на одной платформе — история и ретраи без YAML кластера |
Что вы получаете
Расписание, ретраи и наблюдаемость
Проверка cron
Выражения расписания проверяются при сохранении, поэтому некорректные записи отсекаются сразу.
Шаг воркера и перекрытия
Проектируйте нагрузку минутного масштаба и добавляйте защиту skip-if-running для долгих задач.
История выполнений
Ответ на вопрос «задача отработала?» без grep — история запусков лежит рядом с HTTP-вызовами.
Алерты по запускам
Подключите мониторинг к доле ошибок или SLO по длительности для задач по расписанию.
Что дальше
Чеклист миграции
Безопасно перенесите одну повторяющуюся задачу из shell в пайплайн по расписанию.
Вынести обработчик из shell-скрипта
Перенесите логику скрипта в версионируемую функцию.
Проверить функцию и задать расписание пайплайна
Сначала проверьте вывод функции. В визуальном редакторе пайплайнов соедините узел cronTrigger с этой функцией и сохраните расписание.
Добавить защиту от перекрытий и алерт
Не дайте параллельным запускам портить данные и показывайте сбои сразу.
Пример кода
Типовые паттерны cron-задач
Обработчики по расписанию получают метаданные пайплайна в event. Два типовых паттерна: инкрементальная синхронизация с курсором-отметкой (безопасно ретраить) и генерация отчёта с веерной рассылкой.
export async function handler(event) { // Read cursor from env so re-runs do not re-process old records const since = process.env.SYNC_CURSOR ?? new Date(Date.now() - 86_400_000).toISOString(); const records = await source.fetchUpdatedSince(since); await destination.upsertBatch(records); // idempotent by record ID const newCursor = records.at(-1)?.updatedAt ?? since; // Update cursor in your config/store for next run return { synced: records.length, cursor: newCursor }; }
export async function handler(event) { const rows = await buildReport(); await storage.upload(rows, { key: `reports/${new Date().toISOString().slice(0, 10)}.csv` }); // Fan out — each recipient gets a separate pipeline step await Promise.all( recipients.map((r) => global.durable.startNew('send-report', undefined, { recipientId: r.id, rowCount: rows.length })), ); return { rows: rows.length, notified: recipients.length }; }
Когда подходит
Выбирайте этот сценарий, когда…
Когда это уместно
- Ночной ETL
- Ротация сертификатов или токенов
- Периодический опрос интеграций
Когда лучше выбрать другое
- Субсекундные периодические задачи — сначала проверьте таймеры платформы
Частые вопросы
Частые вопросы
Что если запуск cron длится дольше интервала?
Используйте ключи идемпотентности, распределённые локи или защиту skip-if-running внутри обработчика, чтобы перекрывающиеся запуски не портили общее состояние.
Чем это лучше crontab на одной машине?
Вы получаете версионируемые бандлы функций, изоляцию контейнера на каждый вызов, сохранённые записи вызовов и ту же модель секретов, что у HTTP-функций, — плюс многошаговые графы, когда одно расписание должно разветвляться.
Какой часовой пояс у cron-выражений?
Зафиксируйте часовой пояс, который ожидает команда (для бэкендов часто UTC), и учитывайте переход на летнее время, если расписание привязано к бизнес-часам.