Обновление
Обновление Planeon означает продвижение вашей PLANEON_VERSION вперёд,
применение новых миграций и раскатку сервисов на новые образы. Порядок
ниже — не рекомендация, а обязательное требование: каждый шаг зависит от
предыдущего, а его пропуск или изменение порядка — верный способ получить
развёртывание, обслуживающее трафик со схемой, которую оно не понимает.
Порядок (никогда не менять местами)
-
Сделайте резервную копию. См. Резервное копирование и восстановление — снимите свежий дамп базы данных и убедитесь, что ваш
SECRETS_MASTER_KEYи.envзарезервированы вместе с ним. Сделайте это прежде, чем трогать что-либо ещё — это единственный путь назад, если обновление пойдёт не так. -
Поднимите
PLANEON_VERSIONв.envдо релиза, на который обновляетесь. -
Скачайте новые образы:
docker compose pull -
Явно примените миграции:
docker compose run --rm migrate -
Гейт: убедитесь, что схема актуальна, прежде чем раскатывать что-либо.
docker compose run --rm migrate statusКаждая миграция должна показывать
Applied. Не переходите к шагу 6, пока это не так — повторите шаг 4 и проверьте снова, если что-то ещё не применено. -
Раскатайте сервисы:
docker compose up -dЭто пересоздаёт пять сервисов, привязанных к версии —
api,worker,gateway,guacdиweb— на новых образах (postgresиredisне затрагиваются;caddyработает на фиксированном вышестоящем образеcaddy:2-alpine, поэтому подъёмPLANEON_VERSIONего не пересоздаёт — он меняется, только если вы правите его собственный образ или конфигурацию;migrateостаётся одноразовым и не запускается как частьup).Живые сессии рабочих столов рвутся во время обновленияПересоздание
guacdостанавливает его процесс, что обрывает каждое живое подключение к рабочему столу, туннелируемое через него (RDP, VNC, SSH). Ожидайте, что активные сессии отключатся в окно обновления; пользователи переподключатся, как только поднимется новыйguacd. Планируйте обновление с учётом этого или предварительно сливайте сессии, если жёсткое переключение недопустимо.
Почему именно такой порядок
api и worker каждый встраивает при сборке номер самой новой миграции,
которую ожидает, и каждый отказывается сообщать о готовности —
/readyz возвращает 503 с именем зависимости migrations — пока схема
базы данных не окажется на этом уровне или выше (см. Наблюдаемость →
Семантика readiness).
Применение миграций до раскатки образов сервисов означает, что схема уже
актуальна к моменту старта новых контейнеров, поэтому не возникает окна,
в котором только что раскатанный сервис висит в состоянии not ready в
ожидании миграции, которую вы ещё не применили — и нет окна, в котором
балансировщик нагрузки или оркестратор направляет трафик на контейнер,
который на самом деле ещё не готов его обслуживать.
Миграции также никогда не применяются автоматически api или worker
при старте — ни при обновлении, ни в любой другой момент. Это осознанный
инвариант платформы, а не недосмотр: он делает изменения схемы видимым и
аудируемым отдельным шагом и не даёт нескольким репликам одновременно
гонки применять миграции к одной базе данных. Вы сами запускаете
docker compose run --rm migrate каждый раз, а гейт migrate status —
это способ убедиться, что это действительно произошло, прежде чем идти
дальше.
Откат
Миграции Planeon применяются только вперёд — в production нет
обратных миграций, а файлы применённых миграций доступны только на
добавление (CI отклоняет pull request, который правит или удаляет
существующий файл). Шага вида migrate down не существует.
Если обновление нужно отменить, откатывайтесь восстановлением
резервной копии, снятой перед обновлением: остановите сервисы,
восстановите дамп базы данных, снятый на шаге 1 (см. Резервное
копирование и восстановление → Процедура
восстановления),
и разверните предыдущую PLANEON_VERSION. Именно поэтому резервная
копия на шаге 1 выше не опциональна — это единственный путь отката.
Развёртывания с несколькими worker
Если вы запускаете больше одной реплики worker (docker compose up -d --scale worker=N), обновлять их безопасно без какой-либо особой
координации. У каждой аренды задания worker есть дедлайн; если worker
останавливается посреди обновления, удерживая аренду, после её истечения
любой выживший worker забирает просроченную аренду и ставит задание в
очередь заново для другого worker (обработчики идемпотентны, поэтому
повтор с начала всегда безопасен) — задания никогда не теряются молча, а
блокировка на уровне строк (FOR UPDATE SKIP LOCKED) не даёт двум worker
выполнить одно и то же задание дважды. Реплики worker можно обновлять по
одной или все сразу той же командой docker compose up -d на шаге 6.