Blue-green миграция сайта между Linux-серверами без простоя: rsync, PostgreSQL и DNS (2026) | AdminWiki

Blue-green миграция сайта между Linux-серверами без простоя: rsync, PostgreSQL и DNS (2026)

11 сентября 2026 18 мин. чтения
Содержание статьи

Blue-green миграция сайта между Linux-серверами: старый сервер (blue) обслуживает трафик, новый (green) готовится параллельно и получает запросы в момент переключения. Простой сводится к времени распространения DNS-записи: при TTL 60 секунд это 1-2 минуты, при TTL 300 секунд - до 5 минут. Данные не теряются, потому что база на green догоняет blue через потоковую репликацию, а файлы синхронизируются rsync.

Схема работает и для статики, и для приложений с PostgreSQL. Дальше: подготовка окружения, перенос файлов через rsync, синхронизация базы через pg_dump/pg_restore или pg_basebackup с replication slot, выпуск TLS-сертификата до смены DNS, проверки через /etc/hosts и curl --resolve, порядок переключения трафика и план отката. Три обязательные таблицы: чек-лист до миграции, сравнение blue и green по метрикам, проверки после переключения.

Что такое blue-green миграция и когда она оправдана

Blue-green это схема переезда, при которой инфраструктура существует в двух экземплярах. Blue, текущий продакшен, принимает весь трафик. Green, целевой сервер, поднимается рядом, синхронизирует данные и проходит проверки. Переключение выполняется одной сменой DNS A-записи на IP green. Пока резолверы обновляют кэш, оба сервера отвечают пользователям корректно, потому что данные на них совпадают.

Подход оправдан, когда есть контроль над DNS-зоной, доступ к обоим серверам и возможность держать прод на старом сервере до последнего момента. Второй сервер в этот период стоит денег: при аренде VPS с 4 vCPU, 8 ГБ RAM и 160 ГБ NVMe это обычно 2-5 тысяч рублей в месяц, и переплата длится от нескольких дней до двух недель. Эти расходы дешевле, чем час простоя интернет-магазина с оборотом 300 тысяч рублей в сутки.

Ключевые метрики планирования: RPO (сколько данных допустимо потерять) и RTO (сколько времени сервис может быть недоступен). Для статического сайта RPO равен нулю автоматически, потому что файлы синхронизируются rsync. Для приложения с базой RPO 0 достижим только через потоковую репликацию и promote с нулевым lag.

Чем blue-green отличается от обычного переезда с простоем

Обычный переезд: останавливаем nginx и php-fpm, копируем файлы, снимаем дамп базы, разворачиваем на новом сервере, меняем DNS, запускаем. Простой измеряется десятками минут, при базе в 200 ГБ легко уходит в часы. Заказы, созданные в момент остановки, теряются: приложение уже не принимает данные.

Blue-green переносит тяжёлые операции в подготовительную фазу. Полный rsync на 50 ГБ по каналу 1 Гбит/с занимает 8-12 минут, но выполняется заранее, пока сайт работает. Финальный инкрементальный прогон передаёт только изменившиеся файлы: обычно 50-500 МБ, это секунды или единицы минут. Единственное окно, когда запись останавливается, длится столько, сколько нужно на догон WAL и promote базы: от 2 до 30 секунд при нулевом lag.

Откат отличается ещё сильнее. При обычном переезде после смены DNS вернуться к старому серверу сложно: данные разъехались. При blue-green blue остаётся нетронутым 24-48 часов, и откат это обратная смена A-записи.

Два сценария: статический сайт и приложение с изменяемой БД

Статика: лендинг, документация, сайт на Hugo или Jekyll, файлы под nginx. Переносится в два шага, rsync и DNS. Базы нет, вопроса синхронизации тоже нет. Окно простоя равно нулю: старый сервер отдаёт контент до смены записи, новый сразу после.

Приложение с PostgreSQL сложнее. Файлы переносятся так же, но база живёт своей жизнью: пользователи пишут данные постоянно. Здесь нужен один из двух путей: дамп с краткой остановкой записи или потоковая репликация на основе pg_basebackup и replication slot с последующим promote. Второй путь даёт RPO 0 и окно read-only в секунды. Оба разбираются ниже с командами и критериями выбора.

Чек-лист подготовки к миграции: что сделать до первого rsync

Подготовка занимает больше времени, чем сам перенос. Минимум 48 часов уходит только на снижение TTL. Полный план с разбором стратегий и резервных копий собран в руководстве по миграции серверов от планирования до запуска.

Снижение TTL DNS заранее: почему это делают за сутки

TTL кэшируется резолверами на срок, который был указан в записи на момент запроса. Если A-запись имела TTL 86400 и вы снизили его до 300 в день переключения, часть резолверов будет держать старый IP ещё сутки. Правильный порядок: за 24-48 часов до окна миграции изменить TTL на 60-300 секунд, дождаться истечения старых кэшей, и только потом работать с переключением.

dig +ttl +noall +answer example.com A
dig @1.1.1.1 example.com A +short
dig @8.8.8.8 example.com A +noall +answer

Проверяйте несколько публичных резолверов: 1.1.1.1, 8.8.8.8, 9.9.9.9. Значение TTL в ответе должно уменьшаться по мере истечения кэша. Не забывайте про AAAA-запись: если она указывает на старый сервер, а IPv6 на green не настроен, часть клиентов после переключения получит таймаут.

Подготовка целевого сервера: паритет окружения

Классическая причина падения после переключения: на green стоит php-fpm 8.2, на blue 8.1, или PostgreSQL 16 против 15. Приложение, собранное под старую версию, ломается на новой, и отладка съедает всё окно миграции. Сверьте версии до переноса файлов.

nginx -v
php-fpm -v
psql --version
cat /etc/os-release
systemctl list-units --type=service --state=running

Сравните не только версии, но и конфигурацию: /etc/nginx/nginx.conf, sites-available, php.ini, php-fpm pool, юниты systemd, лимиты в /etc/security/limits.conf, права на /var/www, политики SELinux или AppArmor. На Debian и Ubuntu проверьте getenforce и aa-status. Расхождение по правам даёт 403 на green при полностью рабочем blue.

Firewall: откройте 80 и 443 на green до переключения, иначе после смены DNS сайт не откроется. Проверьте nft list ruleset или ufw status. Синхронизация времени через chrony или systemd-timesyncd нужна для TLS и логов: расхождение в 5 минут ломает проверку сертификатов на стороне клиента.

Если green поднимается в облаке, выбирайте машину с нужным числом vCPU и диском NVMe: Timeweb Cloud даёт серверы, VDS/VPS и базы данных с оплатой за фактические ресурсы, что удобно для двухнедельного переезда без покупки железа.

ПунктЗачемКак проверить
Инвентаризация сервисов и портовНе забыть про cron, очереди и второстепенные демоныss -tulpn, systemctl list-units
Фиксация версий ПОПаритет ОС, nginx, php-fpm, PostgreSQLnginx -v, psql --version, cat /etc/os-release
Бэкап файлов и базыТочка возврата, если пострадают оба сервераpg_dump -Fc, копия на отдельный хост или в объектное хранилище
SSH-доступ на greenРабота без пароля, автоматизация rsyncssh -o BatchMode=yes green 'uptime'
Порты 80 и 443 в firewall greenСайт откроется сразу после смены DNSnft list ruleset, ufw status
Синхронизация времениВалидность TLS и корректные метки в логахchronyc tracking, timedatectl
Мониторинг на оба сервераВидеть метрики green до и после переключенияАгент node_exporter, проверка графиков в Grafana или Zabbix
План откатаВернуть трафик за минуты при сбоеЗаписанный порядок шагов, доступ к DNS-панели у дежурного
Окно миграции и уведомлениеСогласовать с бизнесом и поддержкойПисьмо стейкхолдерам, дежурный на связи
Снижение TTL DNSПереключение за минуты, а не за суткиdig +ttl example.com A на нескольких резолверах

Перенос файлов через rsync: первый прогон и инкрементальная синхронизация

Первый прогон выполняется за дни до переключения, когда нагрузка низкая. Он переносит основной объём данных.

rsync -aHAX --delete --numeric-ids --info=progress2 \
  -e "ssh -p 22" \
  /var/www/ deploy@green:/var/www/

Флаги: -a сохраняет права, время, владельцев и символические ссылки, -H переносит жёсткие ссылки, -A ACL, -X расширенные атрибуты, --delete удаляет на green файлы, которых нет на blue (важно при удалённых плагинах и старых сборках), --numeric-ids переносит UID/GID числами, что критично при разных наборах пользователей. Ключ --info=progress2 показывает общий прогресс, а не список каждого файла.

Полный перенос 50 ГБ по каналу 1 Гбит/с занимает 8-12 минут. Второй прогон перед переключением идёт по тому же набору флагов и передаёт только разницу. Нагрузку на диск старого сервера ограничивают через --bwlimit=50M при узком канале или ionice -c2 -n7 перед командой. Пример регулярной синхронизации с логом и разбор типичных ошибок есть в статье про перенос данных на новый сервер с минимальным даунтаймом.

Что исключать из синхронизации и почему

/var/www/site/var/cache/
/var/www/site/var/log/
/var/www/site/var/tmp/
/var/www/site/node_modules/
/var/www/site/.git/
*.log
*.pid
*.sock
rsync -aHAX --delete --numeric-ids \
  --exclude-from=/root/rsync-exclude.txt \
  /var/www/ deploy@green:/var/www/

Кэш и логи генерируются заново, их перенос тратит время и приводит к битым файлам состояния. Каталог node_modules собирается на месте: перенос 300 тысяч мелких файлов по SSH идёт дольше, чем npm ci. Исключение из правила: каталог загрузок пользователей (uploads, media, storage/app/public) переносится всегда, потери там недопустимы.

Проверка целостности после rsync

Сухой прогон показывает, что осталось синхронизировать, и ничего не меняет на диске.

rsync -aHAXn --delete --numeric-ids --itemize-changes \
  --exclude-from=/root/rsync-exclude.txt \
  /var/www/ deploy@green:/var/www/

Пустой вывод означает полное совпадение. Если строки есть, смотрите на первый символ: > значит файл передаётся на green, d значит удаляется. Дополнительно сравните контрольные суммы критичных файлов.

find /var/www/site/config -type f -exec md5sum {} \; | sort -k2 | md5sum
ssh green "find /var/www/site/config -type f -exec md5sum {} \; | sort -k2 | md5sum"

Проверьте владельца и права на ключевых каталогах: ls -la /var/www/site, stat -c '%U:%G %a' /var/www/site/storage. Разница в правах обычно и даёт 500 после переключения.

Синхронизация PostgreSQL: pg_dump/pg_restore или потоковая репликация

Выбор между двумя подходами определяется объёмом базы и допустимым RPO.

  • pg_dump + pg_restore: база до 50-100 ГБ, допустимо окно read-only 5-30 минут, простая настройка.
  • Потоковая репликация: база от 100 ГБ, RPO близко к нулю, окно остановки записи секунды, нужны настройка standby, WAL streaming и replication slot.

Вариант 1: pg_dump и pg_restore для небольших баз

pg_dump -Fc -Z6 -f /backup/site_$(date +%F).pgc -U postgres site_db
pg_restore -d site_db -j 4 --no-owner --no-privileges /backup/site_2026-09-11.pgc

Флаг -Fc даёт custom format: сжатие, выборочное восстановление таблиц, параллельный разбор через -j. Текстовый дамп восстанавливается одним потоком и на базе в 40 ГБ может идти часами. Перед финальным дампом приложение переводится в режим read-only: настройкой в админке, флагом в конфиге или командой для базы.

ALTER DATABASE site_db SET default_transaction_read_only = on;
-- после восстановления на green
ALTER DATABASE site_db SET default_transaction_read_only = off;

Проверка после восстановления: число строк в ключевых таблицах, значения sequence, внешние ключи.

SELECT relname, n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC LIMIT 20;
SELECT last_value FROM orders_id_seq;
SELECT conname FROM pg_constraint WHERE contype='f' AND NOT convalidated;

Sequence это классические грабли: дамп переносит текущее значение, но если после снятия дампа на blue были вставки, на green sequence отстанет и приложение получит duplicate key. После переключения выполните:

SELECT setval('orders_id_seq', (SELECT MAX(id) FROM orders));

Вариант 2: потоковая репликация PostgreSQL на новый сервер

Репликация держит green в актуальном состоянии и позволяет переключиться за секунды. На blue создаётся роль репликации и физический слот.

CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'strong_password';
SELECT * FROM pg_create_physical_replication_slot('green_slot');

В pg_hba.conf на blue разрешаем подключение replicator с IP green.

host replication replicator 10.0.0.12/32 scram-sha-256

На green база разворачивается из базовой копии.

systemctl stop postgresql
rm -rf /var/lib/postgresql/16/main/*
pg_basebackup -h 10.0.0.10 -D /var/lib/postgresql/16/main \
  -U replicator -P -R -X stream -S green_slot
systemctl start postgresql

Флаг -R создаёт standby.signal и прописывает primary_conninfo в postgresql.auto.conf. В postgresql.conf на green проверьте hot_standby = on, тогда база принимает read-only запросы. До promote сервер работает только на чтение: любые INSERT завершатся ошибкой cannot execute INSERT in a read-only transaction.

Контроль replication lag и критерий готовности к переключению

-- на blue
SELECT client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn,
       pg_wal_lsn_diff(sent_lsn, replay_lsn) AS lag_bytes
FROM pg_stat_replication;
-- на green
SELECT pg_last_wal_replay_lsn(), pg_is_in_recovery();

lag_bytes = 0 и state = streaming означают, что green применил все изменения. pg_is_in_recovery() возвращает t, пока база в режиме standby. Переключение выполняйте только при нулевом lag и отсутствии ошибок в логах: journalctl -u postgresql -n 100 --no-pager. Слот репликации нельзя удалять до promote, иначе blue удалит WAL, который ещё не доехал до green, и standby отстанет навсегда.

TLS-сертификат на новом сервере: выпуск и проверка до переключения

Если сертификат выпущен только на blue, после смены DNS браузеры покажут предупреждение: имя не совпадает или цепочка неполная. Сертификат на green нужен до переключения.

DNS-01 challenge: выпуск сертификата без переключения DNS

HTTP-01 challenge требует, чтобы домен уже указывал на green. DNS-01 обходит это ограничение: certbot кладёт TXT-запись _acme-challenge.example.com, и валидация проходит, пока трафик ещё идёт на blue.

certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d example.com -d www.example.com \
  --preferred-challenges dns-01

Для Route53 применяется плагин --dns-route53, для других провайдеров есть отдельные плагины или ручной режим --manual с --preferred-challenges dns. Проверьте TXT-запись до истечения валидации.

dig +short TXT _acme-challenge.example.com @1.1.1.1
systemctl list-timers | grep certbot
systemctl status certbot.timer

Тестовый прогон обновления выполняйте с флагом --dry-run, чтобы не потратить лимиты Let's Encrypt на повторные выпуски.

Проверка сертификата и цепочки

openssl s_client -connect 10.0.0.12:443 -servername example.com -showcerts /dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

В SAN должны быть оба имени: example.com и www.example.com. Дата notAfter должна покрывать минимум 30 дней после окна миграции. Проверка через HTTP-клиент по IP green без правки DNS:

curl -vI https://example.com/ --resolve example.com:443:10.0.0.12

Ответ должен содержать HTTP/2 200 и строку с TLS 1.3 или 1.2. HSTS включайте только после успешного переключения: заголовок Strict-Transport-Security браузер запоминает на месяцы, и откат на HTTP станет невозможен для уже обученных клиентов.

Тестирование green-сервера через /etc/hosts и curl --resolve

До смены DNS green нужно проверить так, как его увидит пользователь: с настоящим Host-заголовком, TLS и полным стеком приложения. Полная методика с готовыми скриптами описана в материале про тестирование миграции данных.

Способ 1: правка /etc/hosts на рабочей машине.

echo "10.0.0.12 example.com www.example.com" | sudo tee -a /etc/hosts
curl -I https://example.com/

Способ 2: curl --resolve, без изменения системы. Удобен для скриптов и одновременной проверки с нескольких машин.

curl -sS -o /dev/null -w "%{http_code} %{time_total}\n" \
  --resolve example.com:443:10.0.0.12 https://example.com/

Способ 3: временный staging-домен stage.example.com с A-записью на green. Он хорош тем, что позволяет прогнать внешние сервисы: платёжные вебхуки, интеграции по API, проверки uptime-мониторинга.

Список smoke-тестов для статики и для приложения с БД

for u in / /about/ /catalog/ /contacts/ /sitemap.xml /robots.txt /nonexistent-page; do
  printf "%s -> " "$u"
  curl -s -o /dev/null -w "%{http_code}\n" --resolve example.com:443:10.0.0.12 "https://example.com$u"
done

Ожидаемые коды: 200 для страниц, 404 для несуществующей. Для приложения добавьте вход в личный кабинет, оформление тестового заказа, работу форм, ключевые API-эндпоинты, выгрузку отчёта. Проверьте, что статика (css, js, img) отдаётся с нужными заголовками Cache-Control и Content-Encoding: gzip или br.

Логи после тестов: tail -n 200 /var/log/nginx/error.log и лог приложения. Ноль новых ошибок уровня error это критерий допуска к переключению.

Проверка записи в БД на green до переключения

Standby база не принимает запись. Тестировать INSERT до promote нельзя, вы получите ошибку. Варианты: создать отдельную тестовую базу на green и прогнать сценарии там, либо выполнить promote в тестовом окне, проверить запись и поднять репликацию заново. Второй путь рискован, если blue уже начал писать.

BEGIN;
INSERT INTO smoke_test (note, created_at) VALUES ('green check', now());
SELECT * FROM smoke_test WHERE note = 'green check';
ROLLBACK;

После promote повторите этот блок на рабочей базе и сравните план запроса через EXPLAIN (ANALYZE, BUFFERS) с blue: расхождение по времени выполнения больше чем в 2 раза сигнал о проблемах с индексами или статистикой. Обновите статистику командой ANALYZE VERBOSE.

Сравнение старого и нового серверов по измеримым параметрам

Решение о переключении принимается по цифрам. Снимите метрики с обоих серверов в одинаковых условиях: одна нагрузка, один набор URL, одно время суток.

Как снять метрики с обоих серверов

# latency, 10 прогонов по каждому URL
for i in $(seq 10); do
  curl -s -o /dev/null -w "%{http_code} %{time_total}\n" --resolve example.com:443:10.0.0.12 https://example.com/
done
# ресурсы
uptime; free -m; df -h /; iostat -x 1 3
# база
psql -c "SELECT pg_database_size('site_db');"

Error rate считайте из логов nginx за одинаковый интервал: awk '$9 ~ /^5/ {c++} END {print c+0}' /var/log/nginx/access.log. Пропускную способность между клиентом и сервером измерьте через iperf3 -c, конфигурацию CPU и RAM зафиксируйте через lscpu | grep -E 'Model name|CPU\(s\)' и dmidecode -t memory | grep -E 'Size|Speed'.

ПараметрBlue (старый)Green (новый)Критерий готовности
ОС и ядроUbuntu 22.04, ядро 5.15Ubuntu 24.04, ядро 6.8Версия не ниже blue, тесты пройдены
nginx1.18.01.24.0nginx -t проходит, набор модулей совпадает
PostgreSQL15.616.3Дамп восстановлен, кодировка и collation те же
CPU и RAM4 vCPU, 8 ГБ8 vCPU, 16 ГБНе меньше blue по ядрам и памяти
Диск160 ГБ SATA, свободно 12 ГБ160 ГБ NVMe, свободно 90 ГБСвободно минимум 20% и не меньше 20 ГБ
Latency p95, главная240 мс190 мсНе выше blue более чем на 20%
Error rate 5xx за час0.02%0.00%Не выше значений blue
Replication lagн/д0 байтСтрого 0 перед promote
TLS и срок сертификатаTLS 1.2/1.3, 60 днейTLS 1.2/1.3, 85 днейДействует минимум 30 дней после окна
Воркеры php-fpmpm.max_children = 20pm.max_children = 20Значения совпадают или выше
Пропускная способность канала400 Мбит/с900 Мбит/сНе ниже blue
NTP-смещение+0.002 с+0.004 сМеньше 0.1 с

Если хотя бы один параметр хуже blue, устраните расхождение до переключения. Добавить ресурсы green можно в панели облака за минуты, а разбираться с деградацией на живом трафике придётся в спешке.

Переключение трафика: DNS, promote БД и порядок действий

Порядок шагов зависит от того, есть ли на green пишущая база. Общее правило одно: база должна быть готовой принимать запись раньше, чем DNS начнёт указывать на green.

Порядок для статического сайта

  1. Финальный инкрементальный rsync, проверка сухим прогоном.
  2. Перезагрузка nginx на green: nginx -t && systemctl reload nginx.
  3. Smoke-тесты через curl --resolve по всему списку URL.
  4. Смена A-записи (и AAAA, если IPv6 поддерживается) на IP green в DNS-панели.
  5. Проверка резолва через dig @1.1.1.1 example.com и открытие сайта в браузере.
  6. Откат при проблемах: вернуть A-запись на IP blue. При TTL 60 секунд трафик вернётся за 1-2 минуты.

Порядок для приложения с PostgreSQL

  1. Убедиться, что lag = 0 и state = streaming в pg_stat_replication.
  2. Остановить запись на blue: приложение в read-only, фоновые задачи (cron, очереди) на паузе.
  3. Дождаться, пока реплика применит последний WAL: lag_bytes = 0 повторно.
  4. Promote на green: pg_ctl promote -D /var/lib/postgresql/16/main или SELECT pg_promote();
  5. Проверить на green: pg_is_in_recovery() возвращает f, база принимает INSERT.
  6. Переключить DNS на IP green.
  7. Снять read-only на green, вернуть фоновые задачи.
  8. Проверить запись из приложения и данные мониторинга.

Окно read-only в этом сценарии длится от 2 до 30 секунд при нулевом lag. Главная ошибка: переключить DNS до promote. Приложение на green получит read-only базу, и пользователи увидят ошибки записи.

Не удаляйте replication slot и не трогайте blue до завершения проверок: слот нужен для разбора расхождений и для отката.

Проверки после переключения и план отката

Первые 30 минут после смены DNS решают, нужен ли откат. Прогоните проверки из таблицы и зафиксируйте результат. Мониторинг должен видеть green: CPU, RAM, диск, 5xx, latency, состояние базы.

ПроверкаКритерий успехаДействие при ошибке
DNS резолвится в новый IPdig на трёх резолверах отдаёт IP greenПроверить TTL и панель DNS, вернуть старую запись при сбое
HTTPS без предупрежденийБраузер показывает замок, SAN совпадаетПеревыпустить сертификат, при сбое переключить обратно
Ключевые URL200 для главной, каталога, контактовПроверить логи nginx, откатить DNS на blue
АвторизацияТестовый пользователь входит, сессия сохраняетсяПроверить права каталогов сессий и ключи приложения
Запись в БДINSERT проходит, данные читаютсяПроверить pg_is_in_recovery и права роли, при сбое вернуть blue
Replication lagНе растёт, ошибок в логах нетПроверить слот и канал, при откате восстановить репликацию
Error rate 5xxНе выше значений blueРазобрать top-10 ошибок в access.log
Latency p95В пределах 20% от blueПроверить воркеры, кэш, индексы базы
МониторингGreen виден в дашборде, алерты активныПереустановить агент, обновить цели в Prometheus
Фоновые задачиCron и очереди выполняютсяЗапустить юниты на green, выключить их на blue

Как откатиться за минуты

Откат для статики: смена A-записи на IP blue. Потери нулевые, потому что контент не менялся. Откат для приложения: сначала вернуть DNS на blue, затем разобраться с базой. Если green уже принял записи, их переносят на blue точечно: pg_dump нужных таблиц или логическая репликация обратно. Поэтому окно read-only сокращают до секунд, а проверку записи делают сразу после promote.

Перед откатом зафиксируйте состояние: SELECT pg_current_wal_lsn() на green, список последних записей в критичных таблицах, вывод journalctl по обоим серверам. Эти данные нужны для разбора причин.

Когда можно выключать старый сервер

Blue остаётся в резерве минимум 24-48 часов: TTL у части резолверов и клиентов может быть больше, и остаточный трафик придёт даже после переключения. Проверьте логи blue: если за последние 6 часов нет запросов, кроме health-check мониторинга, трафик перетёк.

tail -n 1000 /var/log/nginx/access.log | awk '{print $1}' | sort -u | wc -l

Перед выключением снимите финальный бэкап базы и файлов на blue, переведите его в режим без записи, и только потом останавливайте юниты. Держите снимок диска или снапшот минимум неделю: откат через сутки после переключения тоже иногда нужен.

Типичные ошибки и как их избежать

Разбор провалов миграции с чек-листом рисков собран в отдельной статье про риски и скрытые сложности миграции. Ниже конкретика по двум самым болезненным участкам.

Ошибки при работе с PostgreSQL

  • Нет replication slot: blue переработал WAL, standby отстал навсегда. Слот создаётся до pg_basebackup.
  • Promote без проверки lag: потеря последних транзакций. Ждите lag_bytes = 0.
  • Дамп в текстовом формате: восстановление базы 40 ГБ идёт часами. Используйте -Fc и pg_restore -j.
  • Забыли про sequence: дубли ключей при первой же вставке. Выполните setval после восстановления.
  • Read-only на blue не включён, приложение продолжает писать, часть данных теряется при promote.
  • Кодировка и collation: база на green создана с другой локалью, индексы по тексту работают иначе. Сверьте SHOW lc_collate; и SHOW server_encoding;

Ошибки при работе с DNS и TLS

  • TTL снижен в день переключения: старые кэши живут сутки, часть пользователей идёт на blue, часть на green.
  • Забыли AAAA-запись: IPv6-клиенты получают таймаут. Проверьте dig AAAA example.com.
  • Сертификат только на blue: после переключения предупреждение в браузере и падение конверсии.
  • HSTS включён до переключения: браузеры запомнили правило, откат на HTTP невозможен.
  • Кэш и логи не исключены из rsync: битые файлы состояния и лишние гигабайты.
  • Мониторинг не переведён на green: сбой замечают пользователи, а не дежурный.
  • Blue выключен через час: остаточный трафик от резолверов с длинным TTL теряется.

Критерий go/no-go простой: lag = 0, доля 5xx не выше blue, все smoke-тесты пройдены, сертификат валиден, план отката под рукой, blue не тронут. Если хотя бы один пункт не выполняется, окно миграции переносится, а не растягивается на живом трафике.

Поделиться:
Сохранить гайд? В закладки браузера