Перейти к основному содержимому

Обновление

Обновление Planeon означает продвижение вашей PLANEON_VERSION вперёд, применение новых миграций и раскатку сервисов на новые образы. Порядок ниже — не рекомендация, а обязательное требование: каждый шаг зависит от предыдущего, а его пропуск или изменение порядка — верный способ получить развёртывание, обслуживающее трафик со схемой, которую оно не понимает.

Порядок (никогда не менять местами)

  1. Сделайте резервную копию. См. Резервное копирование и восстановление — снимите свежий дамп базы данных и убедитесь, что ваш SECRETS_MASTER_KEY и .env зарезервированы вместе с ним. Сделайте это прежде, чем трогать что-либо ещё — это единственный путь назад, если обновление пойдёт не так.

  2. Поднимите PLANEON_VERSION в .env до релиза, на который обновляетесь.

  3. Скачайте новые образы:

    docker compose pull
  4. Явно примените миграции:

    docker compose run --rm migrate
  5. Гейт: убедитесь, что схема актуальна, прежде чем раскатывать что-либо.

    docker compose run --rm migrate status

    Каждая миграция должна показывать Applied. Не переходите к шагу 6, пока это не так — повторите шаг 4 и проверьте снова, если что-то ещё не применено.

  6. Раскатайте сервисы:

    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.