Добавить в избранное
Комментарии

Как откатить неудачный деплой за минуту

Чтение ≈ 3 мин

Пошаговый план на случай «после деплоя всё упало»: остановить кровотечение, откатить код снапшотом или симлинком, решить, что делать с миграциями, и не повторить ошибку.

картинка к записи Как откатить неудачный деплой за минуту

Деплой прошёл, smoke покраснел, в журнале исключения, пользователи пишут. В этот момент нужен не поиск бага, а возврат к рабочей версии. Поиском займётесь потом. Этот план работает, если заранее подготовлены три вещи из урока о деплое без git: снапшоты кода на сервере, файл REVISION и бэкап БД перед миграциями.

Минута 0: не чинить вперёд

Главный соблазн — «сейчас быстро поправлю и задеплою ещё раз». Это занимает 10–30 минут, и сайт всё это время лежит. Хотфикс может сломать что-то ещё. Правило простое: сначала откат, потом разбор. Исключение одно: ошибка тривиальная (опечатка в конфиге), и исправление очевидно короче отката.

Минута 1: что сейчас на проде

ssh deploy@example.com 'cat /srv/myproject/app/REVISION; ls -1dt /srv/myproject/deploy-snapshots/* | head -3'
ssh deploy@example.com 'journalctl --user -u myproject -n 50 --no-pager'

Убедитесь, что сломал именно последний деплой (sha в REVISION совпадает с только что залитым), и найдите снапшот, на который откатываться.

Минута 2: откат кода

Схема со снапшотами (rsync + hardlinks):

./scripts/push.sh --rollback
# под капотом: rsync -a --delete <последний снапшот>/ <каталог сайта>/ + рестарт сервисов

Схема releases/ + current:

ssh deploy@example.com bash -s <<'EOF'
set -euo pipefail
cd /srv/myproject
prev="$(ls -1dt releases/*/ | sed -n 2p)"
ln -sfn "$PWD/$prev" current.new && mv -Tf current.new current
systemctl --user restart myproject
echo "откат на $prev"
EOF

Если отдельного скрипта нет, а git-репозиторий под рукой, сделайте git checkout <предыдущий sha> локально и обычный деплой. Это дольше, но тоже работает.

Отдельные случаи:

  • Изменились зависимости (venv, node_modules, NuGet): если они не входят в снапшот, переустановите их по lock-файлу откаченной версии.
  • Фронт с хешированными бандлами: у пользователей могут быть открыты страницы, которые ссылаются на новые бандлы. Не удаляйте новые файлы сразу, пусть полежат до следующего деплоя.
  • Кэш: если новый код записал в кэш данные в новом формате, сбросьте только префикс приложения, не весь Redis (иначе потеряете сессии, счётчики rate-limit и данные соседних сервисов).

Минута 3: проверка

for i in $(seq 1 20); do curl -fsS -o /dev/null https://example.com/health/ && break; sleep 1; done
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/
ssh deploy@example.com 'cat /srv/myproject/app/REVISION'

Убедитесь, что REVISION показывает старый sha, ключевые страницы отвечают 200, а в журнале нет новых ошибок.

А что с базой данных

Откат кода не откатывает миграции. Варианты по степени тяжести:

  • Миграция обратно совместима (expand/contract: добавили колонку или таблицу, ничего не удалили). Старый код работает с новой схемой, БД не трогаем. Поэтому именно так и пишут миграции.
  • Миграция несовместима, но обратима. Выполните обратную миграцию на версии, которая её содержит (manage.py migrate app 0041, dotnet ef database update PreviousMigration, php artisan migrate:rollback --step=1), до отката кода, иначе в старом коде этих миграций уже нет.
  • Миграция удалила данные. Восстанавливайте из дампа, снятого перед миграцией. Если после деплоя прошло время, сначала восстановите дамп в отдельную БД и перенесите нужные таблицы или строки, а не перезаписывайте целиком: иначе потеряете заказы, сделанные за это время.
createdb myproject_before
pg_restore -d myproject_before --no-owner ~/backups/myproject/db/myproject-*-pre-migrate.dump

После аварии

  • Запишите в двух-трёх строках, что сломалось, как заметили, сколько длилось и что изменить.
  • Добавьте проверку, которая поймала бы эту поломку до прода: тест, шаг CI, пункт smoke.
  • Если откат шёл медленно или вручную, автоматизируйте его: при неудачном health-check деплой-скрипт сам переключается обратно.
  • Хотя бы раз отрепетируйте откат на тестовом сервере. Откат, который ни разу не запускали, работает так же надёжно, как бэкап, который ни разу не восстанавливали.

Шпаргалка

  • [ ] Не чинить вперёд, сначала откатить.
  • [ ] Посмотреть REVISION и журнал, найти снапшот или предыдущий релиз.
  • [ ] Откатить код одной командой, переустановить зависимости при необходимости.
  • [ ] Дождаться /health/, проверить ключевые страницы и REVISION.
  • [ ] БД: совместима — не трогать; обратима — откатить миграцию; данные потеряны — восстановить из pre-migrate дампа выборочно.
  • [ ] Короткий разбор и новая проверка, которая поймала бы проблему.
Поделиться
Понравился материал?
Проголосовало пользователей: 0Пожалуйста проголосуйте!

Комментарии

Свернуть форму

Проверяем авторизацию…