From e576f8c25644db86ea0e06e5cf2288aab3c5f827 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Mon, 24 Aug 2026 04:46:18 +0300 Subject: [PATCH] =?UTF-8?q?chore(ops):=20=D1=80=D0=B0=D0=B7=D0=B2=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B8=20crontab=20=D0=BF=D0=BE=20=D1=85=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BC=20=D0=BF=D0=BE=D0=B4=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B5=D0=B7=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Сегодняшний crontab Beget'а обслуживает ОБА контура сразу — и остающийся (Forgejo), и уезжающий (tradein/gendesign). После 30.08 это перестанет быть верным, а сам crontab об этом не узнает. Пять записей начнут ходить в контейнеры, которых на Beget больше нет: 0 5 * * * backfill_houses_dadata docker exec tradein-backend 30 5 * * * geocode_deals_from_houses docker exec tradein-backend 45 5 * * * geocode_deals_nominatim docker exec tradein-backend 30 4 * * * backup-tradein-db.sh dump из tradein-postgres 30 3 * * * ops/backup.sh dump из gendesign-postgres Падающие по ночам задачи — ещё полбеды. Хуже, что вместе с ними перестанут обновляться sentinel'ы бэкапов; сторож честно это заметит и упрётся в то, что канал оповещения не настроен (#2203: TELEGRAM_* нет ни в одном env-файле). То есть бэкапы обоих продуктовых кластеров пропадут МОЛЧА. Зеркальный и более опасный случай: если на Poincare crontab не установить вовсе, там не будет НИ ОДНОГО бэкапа — и узнать об этом неоткуда, потому что сторож пропущенных прогонов живёт в том же crontab'е. Отсутствие бэкапов обнаружилось бы в момент, когда они понадобятся. Поэтому два эталонных файла, а не инструкция в раннбуке: переход должен быть явным действием (`crontab ops/crontab-<хост>.cron`), а не «забыли поправить». Разбор по хостам: Beget — backup-forgejo.sh + его сторож + docker-prune (здесь остаются CI-раннеры, их тома и растут) Poincare — оба продуктовых бэкапа + два их сторожа + три задачи обогащения/геокодирования + СВОЙ docker-prune docker-prune нужен на обоих: на Beget он чистит тома раннеров, на Poincare образы продуктового стека. Это не «переехавшая» запись, а две разные. Заодно логи переведены с /tmp на /opt/gendesign/logs: половина записей писала в /tmp, который чистится при перезагрузке — именно поэтому историю отказов бэкапов раньше не удавалось восстановить. Времена оставлены прежние: чтобы при разборе後 переезда не гадать, что изменилось — поведение или расписание. `ops/*.cron` добавлен в paths deploy.yml: файлы не исполняются деплоем, но должны физически лежать в /opt/gendesign, иначе в окне их нечем будет установить (тот же класс, что #2887). Проверено: 11 расписаний разобраны построчно — 5 полей + команда, ошибок 0; deploy.yml остаётся валидным YAML. Refs #3059, #3057, #2203 --- .forgejo/workflows/deploy.yml | 4 +++ ops/crontab-beget.cron | 45 ++++++++++++++++++++++++++++++++ ops/crontab-poincare.cron | 48 +++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 ops/crontab-beget.cron create mode 100644 ops/crontab-poincare.cron diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml index 95df986a..12dcdf0e 100644 --- a/.forgejo/workflows/deploy.yml +++ b/.forgejo/workflows/deploy.yml @@ -39,6 +39,10 @@ on: # снова забыли бы (см. как этот самый комментарий выше был точечным про # docker-prune.sh и не спас backup.sh). Глоб закрывает класс целиком. - "ops/*.sh" + # Эталонные crontab'ы двух хостов (#3059). Деплоем не исполняются, но + # должны физически лежать в /opt/gendesign — иначе их нечем будет + # установить в окне: `crontab /opt/gendesign/ops/crontab-<хост>.cron`. + - "ops/*.cron" workflow_dispatch: # #2950: ОБЩАЯ группа с deploy-tradein.yml — не опечатка и не копипаста. diff --git a/ops/crontab-beget.cron b/ops/crontab-beget.cron new file mode 100644 index 00000000..4fa69fa5 --- /dev/null +++ b/ops/crontab-beget.cron @@ -0,0 +1,45 @@ +# crontab ОСТАЮЩЕГОСЯ хоста (Beget, 46.173.16.127) — после переезда 30.08. +# +# Устанавливать НЕ РАНЬШЕ, чем стек уедет на Selectel: +# crontab /opt/gendesign/ops/crontab-beget.cron +# crontab -l # сверить +# +# ЗАЧЕМ ЭТОТ ФАЙЛ. Сегодняшний crontab Beget'а обслуживает ОБА контура сразу: +# и остающийся (Forgejo), и уезжающий (tradein/gendesign). После переезда пять +# записей начнут ходить в контейнеры, которых на этом хосте больше нет — +# `docker exec tradein-backend ...` будет падать каждую ночь. Само по себе это +# ещё полбеды; беда в том, что вместе с ними перестанут обновляться sentinel'ы +# бэкапов, сторож это честно заметит — и упрётся в то, что канал оповещения +# не настроен (#2203: TELEGRAM_* нет ни в одном env-файле). То есть бэкапы +# пропадут молча. +# +# Разделение на два файла — чтобы этот переход был явным действием, а не +# «забыли поправить crontab». + +# ── Forgejo: остаётся здесь ───────────────────────────────────────────────── +# Конфиг лежит не в /etc/default (туда нет доступа без root), а в +# /opt/gendesign/secrets — путь передаётся переменной. +15 4 * * * FORGEJO_BACKUP_ENV_FILE=/opt/gendesign/secrets/forgejo-backup.env bash /opt/gendesign/ops/backup-forgejo.sh >> /opt/gendesign/logs/backup-forgejo.log 2>&1 + +# Сторож пропущенных прогонов для forgejo-бэкапа. Порог 26ч. +0 * * * * bash /opt/gendesign/ops/check-backup-staleness.sh /opt/gendesign/backups/forgejo/.last_success 26 "forgejo backup" >> /opt/gendesign/logs/backup-staleness.log 2>&1 + +# ── Уборка докера ─────────────────────────────────────────────────────────── +# Остаётся здесь, потому что здесь остаются CI-раннеры (#2881) — именно их +# тома и растут. На Selectel нужна СВОЯ такая же запись (см. crontab-poincare). +0 4 * * 0 bash /opt/gendesign/ops/docker-prune.sh >> /tmp/gendesign-docker-prune.log 2>&1 + +# ── ЧТО ОТСЮДА УБРАНО И ПОЧЕМУ ────────────────────────────────────────────── +# Все записи ниже переехали в ops/crontab-poincare.cron, потому что обращаются +# к контейнерам и данным, которых на Beget после переезда не будет: +# +# 30 4 * * * backup-tradein-db.sh -> dump из tradein-postgres +# 30 3 * * * ops/backup.sh -> dump из gendesign-postgres +# 0 5 * * * backfill_houses_dadata -> docker exec tradein-backend +# 30 5 * * * geocode_deals_from_houses -> docker exec tradein-backend +# 45 5 * * * geocode_deals_nominatim -> docker exec tradein-backend +# 0 * * * * staleness: backups/.last_success (main-бэкап уехал) +# 0 * * * * staleness: backups/tradein/.last_success (tradein-бэкап уехал) +# +# ⚠️ Оставить их здесь = пять падающих задач в сутки И потерянные бэкапы +# обоих продуктовых кластеров. diff --git a/ops/crontab-poincare.cron b/ops/crontab-poincare.cron new file mode 100644 index 00000000..d15c34f1 --- /dev/null +++ b/ops/crontab-poincare.cron @@ -0,0 +1,48 @@ +# crontab ПРИНИМАЮЩЕГО хоста (Selectel Poincare, 188.246.224.93) — после 30.08. +# +# Устанавливать СРАЗУ после того, как стек поднялся и смоук прошёл: +# crontab /opt/gendesign/ops/crontab-poincare.cron +# crontab -l # сверить +# +# ⚠️ САМЫЙ ОПАСНЫЙ ПРОПУСК ВСЕГО ПЕРЕЕЗДА. Если этот файл не установить, +# на новом хосте НЕ БУДЕТ НИ ОДНОГО БЭКАПА — ни tradein, ни gendesign. И узнать +# об этом будет неоткуда: сторож пропущенных прогонов (check-backup-staleness) +# сам живёт в этом же crontab'е, то есть его тоже не будет. Отсутствие бэкапов +# обнаружится в момент, когда они понадобятся. +# +# Времена оставлены те же, что были на Beget — чтобы не гадать, изменилось ли +# поведение из-за переезда или из-за нового расписания. Подгонять окна имеет +# смысл ПОСЛЕ того, как всё поедет стабильно. + +# ── Бэкапы обоих кластеров ────────────────────────────────────────────────── +# Off-box выгрузка в S3 включается через /etc/default/tradein-backup и +# /etc/default/gendesign-backup — файлы НЕ переезжают сами (в git их нет и не +# должно быть), их нужно перенести руками. Без них дампы останутся локальными, +# то есть на том же диске, что и БД, — ровно то, из-за чего заводился #2203. +30 3 * * * bash /opt/gendesign/ops/backup.sh >> /opt/gendesign/logs/gendesign-backup.log 2>&1 +30 4 * * * bash /opt/gendesign/tradein-mvp/deploy/backup-tradein-db.sh >> /opt/gendesign/logs/tradein-backup.log 2>&1 + +# Сторожа пропущенных прогонов, порог 26ч. Едут вместе со своими бэкапами: +# сторож должен жить там же, где sentinel, иначе он сторожит файл, который +# никто не обновляет, и кричит вечно. +0 * * * * bash /opt/gendesign/ops/check-backup-staleness.sh /opt/gendesign/backups/.last_success 26 "gendesign main backup" >> /opt/gendesign/logs/backup-staleness.log 2>&1 +0 * * * * bash /opt/gendesign/ops/check-backup-staleness.sh /opt/gendesign/backups/tradein/.last_success 26 "tradein backup" >> /opt/gendesign/logs/backup-staleness.log 2>&1 + +# ── Обогащение и геокодирование (ходят в tradein-backend) ─────────────────── +0 5 * * * cd /opt/gendesign/tradein-mvp && docker exec tradein-backend python -m scripts.backfill_houses_dadata --limit 100 --priority both >> /opt/gendesign/logs/dadata-backfill.log 2>&1 +30 5 * * * cd /opt/gendesign/tradein-mvp && docker exec tradein-backend python -m scripts.geocode_deals_from_houses --limit 50000 >> /opt/gendesign/logs/deals-geocode.log 2>&1 +45 5 * * * cd /opt/gendesign/tradein-mvp && docker exec tradein-backend python -m scripts.geocode_deals_nominatim --limit 5000 >> /opt/gendesign/logs/deals-nominatim.log 2>&1 + +# ── Уборка докера ─────────────────────────────────────────────────────────── +# СВОЯ запись, не «переехавшая»: на Beget она чистит тома CI-раннеров, здесь — +# образы продуктового стека. Нужны обе, на обоих хостах. +0 4 * * 0 bash /opt/gendesign/ops/docker-prune.sh >> /opt/gendesign/logs/docker-prune.log 2>&1 + +# ── Логи: /opt/gendesign/logs, а не /tmp ──────────────────────────────────── +# На Beget половина записей писала в /tmp — он чистится при перезагрузке, и +# именно поэтому историю отказов бэкапов там восстановить не удавалось. +# Каталог создать до установки crontab: mkdir -p /opt/gendesign/logs +# +# ── ЧЕГО ЗДЕСЬ НЕТ ────────────────────────────────────────────────────────── +# backup-forgejo.sh + его сторож — Forgejo остаётся на Beget +# (см. ops/crontab-beget.cron) -- 2.45.3