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

Перенос сайта на более мощный сервер без простоя возможен только в одной схеме: старый узел продолжает обслуживать запросы, пока новый проходит проверку и получает актуальные данные. Простая смена IP или восстановление резервной копии почти всегда оставляет окно недоступности — от нескольких минут до времени, необходимого для восстановления базы.
Сначала выберите схему миграции
Ниже предполагается веб-приложение на Linux, PostgreSQL 16 и Nginx 1.24 или новее. Перед приложением есть постоянная точка входа: балансировщик, reverse proxy или другой сервер с неизменным публичным адресом. Пользователь обращается к ней, а не напрямую к старому VPS.
| Схема | Что происходит | Цена и риск |
|---|---|---|
| Изменить размер текущего VPS | Провайдер переносит тот же диск на более крупный тариф | Проще всего, но перерыв зависит от провайдера. Нет полноценного отката на старую конфигурацию. |
| Новый сервер за постоянным proxy | Старый и новый узлы работают параллельно, затем меняется upstream | Лучший вариант для предсказуемого переключения. Нужно синхронизировать базу, файлы и фоновые задачи. |
| Blue-green | Синяя среда обслуживает трафик, зелёная полностью готовится к замене | Быстрый откат, но временно оплачиваются два сервера и требуется дисциплина работы с данными. |
Для миграции без простоя выбирайте второй или третий вариант. DNS не считается постоянной точкой входа: часть клиентов будет использовать старый IP до окончания TTL, а часть DNS-резолверов может кэшировать запись дольше заявленного срока.
Без простоя переносится не сервер, а трафик. Если у вас нет отдельной точки, через которую можно переключить запросы, сначала создайте её.
Что проверить до начала
Составьте карту состояния приложения. Миграция ломается не на копировании файлов, а на забытом состоянии: сессиях в локальных файлах, загрузках пользователей, очереди задач или cron, который запускается одновременно на двух узлах.
- Опишите версии ОС, веб-сервера, языка, runtime, расширений и PostgreSQL. На новом сервере сначала добейтесь совместимости, а уже потом переносите данные.
- Отдельно перечислите базу, файлы загрузок, каталоги с кэшем, очереди, хранилища сессий, сертификаты и переменные окружения.
- Проверьте, что у вас есть резервная копия базы и файлов. Восстановите копию на отдельном тестовом узле: наличие файла backup не доказывает, что из него можно запустить приложение.
- Зафиксируйте показатели до миграции: время ответа, долю ошибок 5xx, загрузку CPU, память, диск, количество соединений с базой и длину очередей.
- Назначьте окно наблюдения и человека, который сможет вернуть трафик на старый узел. Даже беспростойный cutover требует плана отката.
Сноска. Cutover — момент переключения рабочего трафика с одного узла или окружения на другое. В хорошей схеме он меняет один управляемый маршрут, а не десятки DNS-записей и конфигураций вручную.
Рабочий порядок миграции
1. Подготовьте новый сервер
Создайте узел с нужным объёмом CPU, памяти, диска и запасом под рост. Установите те же версии системных компонентов, что и на старом сервере, либо заранее проведите отдельное обновление и протестируйте его. Не переносите вместе с приложением старые временные каталоги и неизвестные системные настройки.
Добавьте новый узел в закрытый контур. Разрешите входящий трафик только от постоянного proxy и необходимые соединения от старого сервера, например для репликации базы. Открывать PostgreSQL всему интернету не нужно.
Проверка: новый сервер отвечает на внутренний адрес, приложение запускается с тестовой конфигурацией, а health-check возвращает успешный статус без доступа к пользовательскому трафику.
2. Перенесите код и постоянные файлы
Код лучше собрать из того же коммита, что работает на старом сервере. Пользовательские загрузки синхронизируйте отдельно. Команда ниже подходит для каталога, где приложение не меняет файлы во время копирования:
rsync -aHAX --numeric-ids --delete \
--exclude='cache/' \
--exclude='tmp/' \
/srv/app/uploads/ \
deploy@NEW_SERVER:/srv/app/uploads/
Замените NEW_SERVER на адрес нового узла, а пути — на реальные каталоги. Флаг --delete удаляет на приёмнике файлы, которых нет в источнике, поэтому сначала выполните пробный запуск без него и проверьте список изменений. Не копируйте секреты в командную строку и не отправляйте каталог с ними через общий архив.
Проверка: на новом сервере открываются несколько старых загрузок, права владельца совпадают с пользователем процесса приложения, а свободного места хватает для роста каталога.
3. Синхронизируйте базу данных
Для PostgreSQL 16 при минимальном простое используйте логическую репликацию или механизм, который предоставляет ваш управляемый сервис. Сначала новый сервер получает исходную копию, затем применяет изменения, пришедшие со старого. Конкретные команды зависят от версии, схемы, провайдера и требований к расширениям, поэтому настройку выполняйте по официальной документации PostgreSQL, а не по случайному скрипту из интернета.
До переключения проверьте три вещи: репликация не отстаёт, новые таблицы и последовательности присутствуют на новом узле, а приложение может подключиться к нему с теми же кодировками и часовым поясом. Репликация не решает проблему файловых загрузок, очередей и внешних интеграций — их состояние нужно переносить отдельно.
Не включайте запись одновременно в старую и новую базы без заранее спроектированной стратегии разрешения конфликтов. Двойная запись часто создаёт расхождения, которые обнаруживаются уже после переключения.
4. Подключите новый узел к proxy
Сначала добавьте новый сервер как неактивный или тестовый upstream. Пример фрагмента для Nginx 1.24+:
upstream app_backend {
server OLD_SERVER:8080;
# Новый узел подключается для проверки, но не получает рабочий трафик
server NEW_SERVER:8080 backup;
}
server {
listen 443 ssl;
server_name example.com;
location / {
proxy_pass http://app_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Это только пример маршрутизации, а не готовая конфигурация с TLS и правилами безопасности. Перед применением проверьте конфигурацию штатной командой Nginx и выполните мягкую перезагрузку. В рабочем варианте health-check должен проверять не только процесс, но и готовность приложения обслуживать запросы.
Проверка: запрос к тестовому домену или внутреннему маршруту попадает на новый сервер, возвращает ожидаемый статус и не создаёт ошибок в логах.
5. Переключите трафик и фоновые задачи
Перед cutover дождитесь нулевого или приемлемого отставания репликации. Затем остановите запись на старом приложении либо переведите его в режим обслуживания записи, дождитесь обработки текущих запросов и убедитесь, что финальные изменения дошли до новой базы. После этого направьте proxy на новый узел.
- Заморозьте деплой и изменения конфигурации.
- Остановите cron, workers и обработчики очередей на старом сервере.
- Проверьте отставание базы и финальную синхронизацию загрузок.
- Переключите upstream на новый сервер.
- Выполните сценарии входа, оформления заказа, загрузки файла и фоновой операции.
- Только после проверки включите workers и cron на новом узле.
Проверка: новые записи появляются в новой базе, очередь не обрабатывается двумя группами workers, а метрики ошибок и задержек остаются в пределах допусков, заданных до миграции.
Что ломается чаще всего
- Сессии хранятся на старом сервере. Пользователей начнёт выбрасывать после переключения. Вынесите сессии в общее хранилище или предусмотрите контролируемое обновление сессий.
- Загрузки синхронизировали один раз. Файл, загруженный между первым rsync и cutover, не попадёт на новый узел. Нужна повторная синхронизация после остановки записи или общее объектное хранилище.
- Запустили cron на двух узлах. Письма, списания и очистка данных могут выполниться дважды. До переключения отключите фоновые процессы на старом сервере.
- Новый сервер отвечает, но приложение не готово. Процесс жив, однако нет соединения с базой, миграций схемы или нужного расширения. Health-check должен проверять зависимые компоненты.
- Откатили только proxy. Если новая база уже принимала записи, возврат трафика на старую без обратной синхронизации приведёт к потере или расхождению данных.
Где подход ломается
Схема с двумя узлами не даёт магического нулевого простоя для stateful-систем. Она требует отдельного решения для WebSocket-соединений, локальных файлов, платежных callback-запросов, очередей и внешних сервисов, которые ограничивают IP-адреса. Если приложение пишет в локальный диск или хранит состояние в памяти процесса, сначала сделайте его состояние общим либо примите короткое окно обслуживания.
Не называйте миграцию беспростойной, если пользователи не видят 502, но теряют операции. Для проверки учитывайте не только доступность главной страницы, но и успешность бизнес-сценариев: авторизация, запись в базу, загрузка, письмо и фоновая обработка.
Что делать дальше
Оставьте старый сервер доступным, но не возвращайте ему рабочие записи сразу после cutover. Наблюдайте минимум один полный цикл фоновых задач и период пикового трафика: ошибки 5xx, p95 задержки, подключения к базе, отставание очередей, заполнение диска и стоимость ресурсов.
После подтверждённого результата сохраните план миграции как runbook: кто переключает proxy, какие команды выполняются, какие метрики проверяются и при каком условии начинается откат. Следующим шагом настройте регулярную проверку восстановления резервных копий и автоматический health-check — именно они превращают разовый переезд в воспроизводимую операцию.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: Nginx documentation: HTTP load balancing, PostgreSQL 16 documentation: Logical Replication
Частые вопросы
Можно ли обойтись без балансировщика и просто поменять DNS?
Как перенести PostgreSQL без остановки записи?
Что делать с файлами, которые пользователи загружают во время миграции?
Нужно ли держать старый сервер после переключения?
Что будет, если новый сервер не выдержит нагрузку?
Нужно ли менять DNS TTL перед миграцией?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.