BitVPS
Миграция VPS на новый сервер без простоя: переключение, DNS и откат
Руководство по миграции

Миграция VPS на новый сервер без простоя: переключение, DNS и откат

Почти любой план миграции неправильно распределяет время. Копирование данных — та часть, которую все репетируют, и та, что почти никогда не подводит. Простой возникает совсем в другом месте: резолвер по-прежнему отдаёт старый адрес спустя сутки после того, как вы изменили запись; база данных незаметно приняла ещё двадцать минут записи уже после того, как вы сняли дамп; сертификат существовал только на диске, который вы вот-вот уничтожите; платёжный шлюз внёс в белый список IP-адрес, который никто не записал. Ни одна из этих проблем не является технически сложной. Все они — проблемы планирования, и все решаются, если делать всё в таком порядке, который оставляет вам путь к отступлению. Это руководство и есть такой порядок — репетируйте на новой машине, пока старая всё ещё обслуживает запросы, переключайтесь по заранее написанному runbook и держите откат, у которого есть срок годности, а не просто надежда.

Никакого KYC — никогда DMCA игнорируется Без журналов трафика Готов за 60 секунд

Копирование данных — лёгкая часть. Что на самом деле вызывает простой

Спросите кого-нибудь, сколько займёт его миграция, и он оценит именно передачу данных. Двести гигабайт по гигабитному каналу — это примерно сорок минут, плюс час про запас. Эта цифра обычно верна и почти никогда не является той цифрой, которая имеет значение, потому что передача идёт, пока старый сервер всё ещё отвечает на запросы. Никто не простаивает во время копирования. Простой наступает в промежутке между новая машина работает правильно и интернет с этим согласен, а длину этого промежутка определяют кэши, которые вам не подконтрольны.

Четыре сценария отказа объясняют большинство реальных аварий при миграции, и ни один из них не связан с пропускной способностью канала. DNS-запись, чей time-to-live всё ещё составлял сутки на момент изменения, — и заметная часть мира продолжает подключаться к уже выключенной машине. База данных, принявшая запись после того, как с неё сняли дамп, — новый хост начинает жизнь с незаметно устаревшей копией, и какие именно двадцать минут пропали, вы узнаёте из жалобы клиента. TLS-сертификат и его ACME-ключ аккаунта, существовавшие только на старом диске, — новый хост показывает каждому браузеру несовпадение имени. И исходящая интеграция — платёжный процессор, приём по SFTP у банка, API партнёра, база данных у стороннего провайдера, — внесённая в белый список по IP-адресу, которая отказывает молча, в максимально неудобный момент, дальше всего отстоящий от вызвавшего это изменения.

Стоит называть вещи своими именами в отношении этой фразы, которую использует каждый. «Миграция без простоя» почти всегда означает несколько секунд отклонённых соединений, которых не заметил ни один человек, — и это совершенно достойная цель. По-настоящему нулевой простой требует, чтобы обе машины корректно обслуживали запросы одновременно, а это требует приложения, способного существовать в виде двух машин сразу: никакого локального состояния сессии, никакого локального каталога загрузок, который есть только на одной стороне, и базы данных, которая либо реплицируется, либо вообще живёт где-то отдельно. Большинство самостоятельно размещённых стеков этой планке не соответствуют, и честный план — это короткая, контролируемая, отрепетированная заморозка, а не архитектурный проект, который вы не планировали начинать.

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

Инвентаризация: части сервера, которых нет в вашем репозитории

Ваш репозиторий развёртывания описывает приложение. Он не описывает машину. Где-то между первым apt install и сегодняшним днём сервер накапливает слой, который никогда не видела система контроля версий: пакеты, установленные вручную для исправления одной проблемы, systemd-юнит, который кто-то написал второпях, cron-задача под сервисным аккаунтом, правила файрвола, настройки sysctl, локаль, часовой пояс, файл подкачки, TLS-сертификаты, SSH-ключи хоста, роли и права базы данных, а также каталог с медиафайлами, которого нет в репозитории именно потому, что его туда положили пользователи. Миграция означает намеренное воспроизведение этого слоя, а единственный способ сделать это намеренно — сначала записать его.

Пять команд покрывают почти всё. dpkg --get-selections в Debian и Ubuntu, либо dnf repoquery --userinstalled в Rocky и Alma, дают набор пакетов. systemctl list-unit-files --state=enabled даёт всё, что настроено на запуск при загрузке, — а это более точный вопрос, чем «что сейчас запущено», потому что сюда попадает и то, что в данный момент упало. crontab -l -u для каждой учётной записи в /etc/passwd, плюс содержимое /etc/cron.d и каждый юнит .timer, даёт запланированные задачи. nft list ruleset или ufw status numbered даёт файрвол. А ss -tulpn даёт то, что реально слушает порты, — так вы обнаруживаете сервис, о существовании которого забыли. Запишите все пять результатов в файлы и скопируйте их с машины, а не на неё.

А ещё есть инвентаризация, которую никто не записывает и которая кусается спустя недели: всё, где угодно, что доверяет вашему текущему IP-адресу. Платёжные шлюзы с белыми списками IP. Управляемая база данных у другого провайдера, чьи правила доступа называют старый адрес. SMTP-релей, аутентифицирующийся по сети. Сервис мониторинга, отправитель webhook'ов, который постит только на известные адреса, файрвол коллеги. Проверьте через grep свою конфигурацию и документацию на предмет старого адреса, затем проверьте панель управления каждого стороннего сервиса, за который вы платите. Всё это ломается уже после переключения, асинхронно, в тот момент, когда интеграция в следующий раз сработает, — именно поэтому это так часто диагностируют как «в то же время сломалось что-то ещё».

Наконец, зафиксируйте саму DNS-зону. Экспортируйте её либо как минимум запишите каждый тип записи, значение и TTL, потому что миграция — это именно тот момент, когда кто-то замечает запись, которая была ошибочной два года, и услужливо исправляет её посреди всего остального.

Что инвентаризироватьГде это хранитсяЧто сломается, если это забыть
Пакеты, установленные вручнуюБаза данных пакетовСервис отказывается запускаться на новом хосте из-за отсутствующей библиотеки, про установку которой никто не помнит.
Включённые юниты и таймерыsystemdФоновая работа молча останавливается: ни резервных копий, ни продления сертификатов, ни воркера очереди.
Cron-задачи по пользователямcrontab каждой учётной записиНочные задачи исчезают, и это замечают только в конце месяца.
Набор правил файрволаnftables или ufwЛибо порт остаётся закрытым и приложение выглядит сломанным, либо открыто всё подряд.
TLS-сертификаты и ACME-ключ аккаунтаКаталог сертификатовБраузеры показывают несовпадение имени, а продления начинают новый аккаунт с нуля.
Роли и права базы данныхГлобальные настройки сервера, а не дампДанные восстанавливаются нормально, но приложение не может в них залогиниться.
Белые списки IP у сторонних сервисовПанели чужих сервисовПлатежи, webhook'и и API партнёров отказывают часами или днями позже.
DNS-зона с TTLУ вашего DNS-провайдераВы не можете понять, какие записи ещё нужно перенести и как долго они кэшируются.

Сначала снизьте TTL DNS — и разберитесь, почему это нужно делать за несколько дней

Рекурсивный резолвер кэширует ответ на срок time-to-live, который ему выдали, и не обязан спрашивать снова до истечения этого срока. Отсюда следствие, на котором почти все спотыкаются в первый раз: снижение TTL записи с 86400 до 300 абсолютно ничего не даёт для резолвера, закэшировавшего старый ответ десять минут назад. Этот резолвер будет держать суточный ответ ещё двадцать три часа пятьдесят минут и только потом узнает о вашем новом пятиминутном TTL. Поэтому низкий TTL нужно опубликовать минимум за один полный старый TTL до того, как вы собираетесь что-либо переносить. Если ваши записи живут на суточном TTL, первое действие миграции происходит за два дня до переключения, и это изменение в одну строку.

Сделайте это для каждой записи, указывающей на машину, а не только для той, что у вас в голове. A-запись и AAAA-запись — адрес IPv6, всё ещё указывающий на старый хост, это прекрасно запутывающий баг, потому что dual-stack-клиенты будут молча предпочитать именно его, и заденет это только часть ваших пользователей. MX-записи. Любой CNAME перед ними — помните, что клиент, идущий по цепочке, подчиняется TTL каждого звена в ней, так что пятиминутная A-запись за суточным CNAME всё равно фактически держится сутки. И если вы заодно меняете DNS-провайдера, не делайте это на той же неделе: делегирование NS и glue-записи кэшируются родительской зоной по собственному расписанию, и если совместить оба изменения, при поломке вы не поймёте, какое из них виновато.

Проверяйте, а не предполагайте. dig +noall +answer example.com A показывает, что сейчас держит резолвер, и сколько времени у этого осталось; запрос напрямую к вашему авторитативному серверу через dig @ns1.example.net example.com A показывает, что вы реально опубликовали. Если два ответа расходятся, вы смотрите на кэш, и число рядом с записью — это ровно то время, которое вам осталось ждать.

Стоит заложить время на два нюанса. Некоторые резолверы «зажимают» TTL: часть провайдерских и корпоративных форвардеров навязывает минимальный TTL независимо от того, что вы опубликовали, — формально это не рекомендуется, но встречается сплошь и рядом. А согласно RFC 8767 резолвер может намеренно отдавать устаревший ответ, если не может достучаться до ваших авторитативных серверов, — отличное поведение для отказоустойчивости и неудобное как раз в тот день, когда вам нужно, чтобы изменение распространилось. С учётом обоих факторов закладывайте длинный хвост, измеряемый часами, иногда — сутками, после того как основная масса трафика уже переехала. Этот хвост не проблема, пока старая машина продолжает отвечать корректно, — собственно, ради этого она и остаётся включённой. RFC 2181 — справочник о том, как должны себя вести TTL, когда реализации расходятся.

КогдаДействиеПочему именно тогда
T минус 7 днейИнвентаризация старого сервера; написание runbookВсё найденное здесь меняет план, поэтому это должно произойти до того, как план зафиксирован.
T минус 3 дняРазвёртывание нового VPS; первое восстановление; репетицияОставляет время пересобрать машину повторно, если репетиция найдёт пробелы.
T минус 2 дняСнижение TTL записей A, AAAA и MX до 300Должен пройти один полный старый TTL, прежде чем низкое значение окажется во всех кэшах.
T минус 1 деньПервый проход rsync; запуск репликации базы данныхДолгий и не требующий присутствия, пока старый сервер всё ещё несёт продакшн-трафик.
T нольЗаморозка записи, финальная синхронизация, проверка, переключение DNSЕдинственное необратимое окно; оно короткое, потому что всё перечисленное выше уже произошло.
T плюс 1 часНаблюдение за обоими access-логамиЗатухание трафика на старом хосте — ваш реальный измеритель истечения кэшей.
T плюс 7 днейВывод старого хоста из эксплуатации; возврат TTL обратноСрок отката истёк; постоянный TTL в 300 секунд стоит задержки без всякой выгоды.

Репетируйте на новой машине, пока старая всё ещё обслуживает трафик

Самая ценная привычка во всём этом процессе — чтобы новая машина существовала и работала за несколько дней до того, как это станет важно. VPS на практике — это почасовая аренда: на наших тарифах сервер оживает примерно через шестьдесят секунд после подтверждения оплаты, нет ни платы за настройку, ни контракта, так что трёхдневная репетиция на тарифе за $8.50 обходится примерно в доллар. Это на редкость дёшевый способ превратить каждую неизвестную величину вашей миграции в известную ещё до того, как начнётся отсчёт времени.

Тестируйте по имени хоста, а не по IP. Если просто открыть в браузере адрес нового сервера, вы получите virtual host по умолчанию, несовпадение SNI, предупреждение сертификата и набор маршрутов, который может вообще не походить на продакшн, — и это с готовностью убедит вас, что всё работает, хотя это не так. Правильный инструмент — переопределение резолвера. curl --resolve привязывает одно имя хоста к одному адресу для отдельной команды, так что curl --resolve example.com:443:203.0.113.10 https://example.com/ задействует настоящее имя, настоящее TLS-рукопожатие и настоящий virtual host на новой машине, пока весь остальной мир всё ещё достаётся до старой. Для интерактивного тестирования одна строка в hosts-файле вашей рабочей станции делает то же самое для браузера.

Репетиция надёжно ловит именно тот накопленный незадокументированный слой из предыдущего раздела. Демон, который работает ещё с последней перезагрузки, но на самом деле не включён в автозагрузку. Cron-задача, которая рассчитывает на локальный транспорт почты, чтобы сообщать об ошибках. Владелец файлов, переживший копирование в виде чисел, но означающий на машине с другим /etc/passwd совсем другое. Захардкоженный адрес в конфигурационном файле. База данных, созданная с одним набором символов на версии, где значение по умолчанию было другим. Минорная версия Python или PHP, в которой что-то нужное вам было объявлено устаревшим. Исправление каждой такой мелочи стоит десять минут во время репетиции и час диагностики во время переключения.

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

rsync дважды: долгий проход, пока всё работает, и короткий — в окне переключения

Именно двухпроходная схема делает окно обслуживания коротким. Первый проход идёт при полностью живом сервисе и может занимать сколько угодно — часы, всю ночь, через выходные. Второй проход идёт во время заморозки и переносит только то, что изменилось после первого, а это при обычной нагрузке — небольшая доля данных и предсказуемое число минут. Вы меняете долгое копирование без присмотра на короткое — под присмотром, и этот обмен почти всегда того стоит.

Флаги имеют больше значения, чем принято думать. rsync -aHAX --numeric-ids — это база: -a для архивного режима, -H для сохранения хардлинков — что критически важно для хранилищ Maildir и дедуплицированных деревьев резервных копий, где их потеря может кратно увеличить использование диска, — -A для POSIX ACL, -X для расширенных атрибутов вроде меток SELinux и file capabilities, и --numeric-ids, чтобы ID пользователя копировался как число, а не разрешался через базу пользователей источника и переразрешался через другую базу на приёмнике. Добавьте --info=progress2 для одной вменяемой строки прогресса и --partial, чтобы прерванная передача возобновлялась, а не начиналась заново. Не используйте -z, если канал не является по-настоящему медленным: сжатие уже сжатых медиафайлов и зашифрованных архивов просто переносит узкое место на CPU.

Используйте --delete только во втором проходе. В первом проходе это способ выстрелить себе в ногу без единого плюса, потому что на приёмнике ещё нечего удалять. Во втором проходе это необходимо: без этого файл, который вы удалили на старом сервере между двумя проходами, будет жить на новом вечно, — вот так миграция начинает отдавать контент, который был намеренно убран.

Чего делать не стоит — это гнать rsync'ом всю корневую файловую систему целиком. Это популярный короткий путь, и в итоге получается машина, о которой никто не может рассуждать. Даже если исключить /proc, /sys, /dev, /run и /tmp, вы получаете систему, чьи ядро и initramfs пришли с одного хоста, чьи имена сетевых интерфейсов выведены из другого железа, чей /etc/machine-id теперь задублирован сразу на двух живых машинах, и чей накопленный за пять лет дрейф конфигурации вы только что заплатили за то, чтобы сохранить. Переносите данные и конфигурацию, которые вы инвентаризировали; операционную систему ставьте заново из шаблона. Это лишний час, зато чистая современная база, и новый сервер становится машиной, которую вы понимаете, а не копией той, которую вы не понимали.

Проверяйте копию, а не доверяйте коду возврата. После обоих проходов запустите ту же команду ещё раз с -n --checksum --itemize-changes: это сухой прогон, который сравнивает содержимое, а не метки времени, и выводит по одной строке на каждое отличие. Тишина — вот результат, который вам нужен, и это куда более сильное доказательство, чем совпадение du -s на обеих сторонах.

База данных — это та часть, с которой rsync вам не поможет

Копирование каталога живой базы данных на уровне файлов даёт вам рваную копию: часть страниц записана, часть — нет, и никакой гарантии, что хоть что-то из этого образует согласованную границу транзакции. InnoDB вполне может восстановиться после этого и выглядеть нормально, а это хуже, чем явный отказ, потому что вы узнаете правду только в тот день, когда восстановление не сработает. Есть ровно две честные стратегии — снять транзакционно согласованный дамп или настроить репликацию, — и выбор между ними — это выбор того, сколько простоя вы готовы себе купить.

Для пути с дампом на MySQL и MariaDB команда mysqldump --single-transaction --routines --triggers --events даёт согласованный снимок без блокировки всего сервера, но тут стоит знать два нюанса: согласованность гарантируется только для транзакционных таблиц, так что одна-единственная устаревшая таблица MyISAM незаметно ломает эту гарантию, и любой DDL-запрос, выполненный во время дампа, тоже её ломает. В PostgreSQL pg_dump -Fc обрабатывает каждую базу данных по отдельности, а pg_dumpall --globals-only берёт на себя ту половину, о которой все забывают, — роли, пароли, права и tablespace'ы живут на уровне кластера, а не внутри отдельной базы, так что восстановление без них даёт идеальные данные, в которые приложение не может залогиниться.

Число, которое определяет длину вашего окна, — это не размер дампа, а дамп плюс передача плюс восстановление плюс пересборка индексов, и последнее из этого обычно оказывается самым большим. Измеряйте это во время репетиции на реальном датасете, а не оценивайте на глаз. Несколько гигабайт — это минуты; сто гигабайт с солидным индексированием могут занять часы, и в этот момент путь с дампом перестаёт быть жизнеспособным для живого сервиса, а репликация становится не оптимизацией, а единственным ответом.

Путь репликации переворачивает стоимость с ног на голову: вы делаете работу заранее, и переключение становится тривиальным. Настройте реплику на новом хосте за несколько дней — репликацию на основе GTID для MySQL и MariaDB, pg_basebackup и потоковый standby для PostgreSQL, либо логическую репликацию, если заодно меняется мажорная версия. Дайте ей догнать источник и оставаться в актуальном состоянии. Тогда переключение выглядит так: остановить запись на primary, дождаться, пока реплика не сообщит нулевое отставание, повысить её, направить на неё приложение. Это секунды, и это единственный подход, который по-честному заслуживает фразы «почти нулевой простой».

Не забывайте о состоянии, которого нет в базе данных. Redis, Valkey и Memcached хранят сессии, счётчики ограничения частоты запросов и очереди; поисковый индекс в Elasticsearch, OpenSearch или Meilisearch хранит производную копию ваших данных. Для каждого из них явно решите, переносить его или пересобирать заново. Инстанс Redis, хранящий сессии, стоит перенести через BGSAVE и копию получившегося файла — если только вы не готовы разлогинить всех разом. Поисковый индекс почти всегда быстрее переиндексировать на новом хосте, чем перенести, — но переиндексация требует времени, так что запускайте её во время репетиции, а не во время заморозки.

СтратегияПростой при переключенииРабота до окнаКогда это верный выбор
Файловое копирование работающего каталога данныхОтсутствует, а данные могут оказаться поврежденыОтсутствуетНикогда. Указано здесь потому, что это первое, что все пробуют.
Согласованный дамп и восстановлениеДамп плюс передача плюс восстановление плюс переиндексацияИзмерьте один раз во время репетицииДатасеты достаточно небольшие, чтобы измеренный итог укладывался в допустимые рамки.
Дамп, восстановление, затем воспроизведение дельтыМинутыЗаранее настроенное хранение binlog или WALДатасеты среднего размера, где полноценная реплика — это больше настройки, чем хочется.
Реплика, повышаемая при переключенииСекундыРепликация работает без отставания уже несколько днейВсё крупное и всё, где долгая заморозка недопустима.
Остановить базу данных, скопировать файлы «вхолодную»Время копированияОтсутствуетНебольшие внутренние сервисы, для которых час простоя реально ничего не стоит.

TLS-сертификаты, SSH-ключи хоста и идентичности, которые нельзя просто перевыпустить

У выпуска сертификата есть проблема курицы и яйца, причём именно в самый неудобный момент. Проверка HTTP-01 подтверждает владение именем, забирая файл по этому имени, а для этого имя уже должно указывать на проверяемую машину — а до переключения оно на неё не указывает. Есть три выхода, и выбрать один из них нужно осознанно. Скопировать каталог сертификатов целиком — это работает сразу и полностью законно, ведь это ваш собственный ключ. Использовать вместо этого проверку DNS-01, которая подтверждается публикацией TXT-записи и поэтому работает на машине, на которую пока никто не указывает, — и это в любом случае единственный вариант для wildcard-сертификата. Либо смириться с коротким окном после переключения DNS, в течение которого новый хост запрашивает собственный сертификат, — это нормально для личного сайта и совсем не нормально для чего-либо с пользователями.

Если копируете — копируйте всё целиком. Сертификаты и приватные ключи — очевидная часть; а вот ACME-ключ аккаунта — та часть, которую обычно забывают, и без него клиент на новом хосте при первом же продлении зарегистрирует совершенно новый аккаунт. Внешне всё будет выглядеть рабочим, а вы незаметно потеряете историю аккаунта и всё связанное с ним состояние. Сохраняйте также владельца и права доступа — приватные ключи с правами 600, каталог архива с правами 700, — потому что копия, расширяющая права на ключ, — это исход хуже, чем сама миграция, которой вы опасались.

Не планируйте перевыпускать сертификат раз за разом и смотреть, что получится. Лимиты частоты Let's Encrypt ограничивают количество дублирующих сертификатов для одного и того же набора имён хостов в неделю, и две неудачные репетиции плюс реальный выпуск — на удивление лёгкий способ упереться в потолок именно в тот день, когда ждать уже нельзя. Направляйте репетиции в staging-окружение; production-эндпоинт приберегите для настоящего дела.

SSH-ключи хоста — это ещё одна идентичность в игре, и здесь правильный ответ по-настоящему зависит от того, почему вы переезжаете. Копирование /etc/ssh/ssh_host_* делает миграцию невидимой: known_hosts у каждого клиента по-прежнему совпадает, и ни одна автоматизация не останавливается на предупреждении об отпечатке. Это удобно, и это правильный выбор для рядового переезда между провайдерами, которым вы доверяете. Это неправильный выбор, если причина, по которой вы уезжаете, в том, что вы больше не доверяете старому хосту или старому провайдеру, — у любого, кто имел доступ к этому диску, был и приватный ключ хоста, и, забрав его на новый сервер, вы забираете с собой и саму проблему. В этом случае сгенерируйте свежие ключи, опубликуйте новый отпечаток через канал, который не является сервером, и попросите клиентов выполнить ssh-keygen -R для старой записи. О том, где живут ключи и как они выбираются, смотрите руководство OpenSSH sshd.

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

Переключение: те десять минут, для которых нужен письменный порядок действий

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

Порядок, который работает. Первое — остановите запись на старом хосте: страница технического обслуживания, флаг «только чтение» или просто остановка приложения, пока веб-сервер продолжает отвечать страницей-заглушкой. Второе — выполните финальный проход rsync с --delete. Третье — завершите шаг с базой данных: либо измеренный вами дамп-передача-восстановление, либо остановите запись на primary, подтвердите нулевое отставание репликации и повысьте реплику. Четвёртое — запустите сервисы на новом хосте и дайте им время устояться: пулы соединений, воркеры очередей и загрузка сертификатов на холодном старте всегда занимают больше времени, чем кажется. Пятое — проверьте. Шестое — и только после успешной проверки — измените DNS-записи. Седьмое — оставьте старый хост работающим.

Проверка должна что-то реально значить. Получение главной страницы доказывает лишь то, что веб-сервер жив, и больше ничего. Используйте curl --resolve с реальным именем хоста на маршруте, который затрагивает базу данных и возвращает что-то, на чём можно строить утверждения, — health-эндпоинт, проверяющий доступность базы, доступность кэша и свободное место на диске, стоит написать хотя бы ради этого одного случая. Затем откройте access-лог нового хоста и убедитесь, что ваш запрос в нём есть. Этот последний шаг звучит педантично, но именно он ловит ситуацию, в которой переопределение резолвера не сработало, и вы только что тщательно проверили старый сервер.

После переключения DNS следите за обоими access-логами бок о бок. Трафик на новом хосте растёт; трафик на старом хосте затухает по мере истечения кэшей, и именно эта кривая затухания — единственное честное измерение того, насколько на самом деле длинный хвост. Когда лог старого хоста выравнивается почти до нуля, миграция закончена. Пока этого не произошло, старая машина обязана продолжать вести себя корректно для пользователей, которые всё ещё до неё достучатся, — поэтому она остаётся включённой и в режиме «только чтение», а не выключается в порыве энтузиазма. Если приложение нельзя перевести в режим «только чтение», то старый хост, отдающий устаревшие данные несколько часов, обычно наносит меньше вреда, чем старый хост, отвечающий отказом в соединении, — но это решение нужно принять заранее, а не по ходу дела.

Меняйте одну вещь. Не мажорную версию операционной системы и хост одновременно. Не DNS-провайдера и записи одновременно. Не версию PHP и машину одновременно. Каждое одновременное изменение умножает число гипотез, которые придётся проверять, когда что-то пойдёт не так в три часа ночи, а обновление, которое вам хотелось заодно втиснуть, никуда не денется и на следующей неделе — на машине, к которой теперь можно откатиться.

Почта, rDNS и репутация, которая не переезжает вместе с вами

Если сервер отправляет почту, у миграции есть вторая половина, не имеющая никакого отношения к самой миграции. IP-адрес несёт репутацию отправителя, эта репутация нарабатывается неделями, и она не переезжает вместе с вами. Это самый частый способ, которым технически безупречная миграция оборачивается неделей жалоб пользователей, и все меры смягчения нужно начинать до переключения, а не после.

Первой ломается запись SPF. Политика с механизмом ip4:, называющим старый адрес, начинает давать сбой в ту же секунду, как вы начинаете слать почту с нового, а поскольку по RFC 7208 такие политики — это DNS-записи, у них есть собственный TTL, который нужно заложить в план. Добавьте новый адрес в SPF до переключения, держите оба адреса в списке во время пересечения и уберите старый при выводе из эксплуатации. DKIM переезжает без проблем, если вы скопируете приватный ключ вместе с остальной конфигурацией, ведь публичная половина уже опубликована. DMARC изменений не требует, но стоит убедиться, что адрес для отчётов всё ещё существует на машине, которую вот-вот уничтожат.

Обратный DNS не опционален для хоста, отправляющего почту. PTR-запись на новом адресе обязана существовать и обязана совпадать с именем, которое сервер объявляет в HELO или EHLO, иначе значительная доля получателей отклонит письмо уже на этом основании. На наших тарифах PTR редактируется прямо из панели, так что это чекбокс, а не тикет в поддержку, — настройте её во время репетиции, убедитесь, что она разрешается, и подтвердите, что прямая запись совпадает в обратную сторону. Затем проверьте новый адрес по основным чёрным спискам прежде, чем отправлять хоть что-то: переиспользованные адреса иногда оказываются уже занесены в список, и узнать об этом из собственного тестового письма ничего не стоит, а узнать от клиента стоит очень дорого. Важнее всего здесь Spamhaus.

Для приёма почты держите оба хоста доступными. Добавьте новый сервер как MX с приоритетом 10, а старый оставьте с приоритетом 20 на неделю, вместо того чтобы удалять его: отправители повторяют попытки, некоторые из них закэшировали вашу MX-запись, и почтовый сервер, тихо принимающий письма на старом хосте, — это намного лучше, чем bounce. Затем, прежде чем уничтожить старую машину, слейте и опустошите её очередь — postqueue -f, чтобы принудительно запустить попытку доставки, и mailq, чтобы убедиться, что результат пуст. Сообщения, застрявшие в очереди на сервере, который вы вот-вот удалите, — это не отложенные сообщения. Они пропали безвозвратно. Руководство по самостоятельно размещённому почтовому серверу целиком разбирает сторону доставляемости.

Когда старый провайдер уже выключил машину

Не любая миграция бывает плановой. Приостановка после жалобы на злоупотребление, карта, у которой истёк срок, аккаунт, заблокированный по причине, которую никто не станет объяснять, — общее у всего этого то, что теперь вы мигрируете с машины, в которую не можете войти, и удобный порядок действий, описанный выше, больше не работает. Стоит заранее знать, что обычно всё ещё возможно сделать, потому что окно, в котором это возможно, часто оказывается коротким.

Пока инстанс приостановлен, но ещё не удалён, часто остаются доступны три пути — в порядке убывания полезности. Панель управления может по-прежнему предлагать скачать снимок или резервную копию — и это решает всю проблему в один шаг. Аварийный (rescue) или восстановительный (recovery) режим может по-прежнему загрузить live-образ с подключённым вашим диском, позволяя примонтировать файловую систему и скопировать по сети всё важное. А аварийная консоль может по-прежнему подключаться, даже когда сеть отключена, — этого достаточно, чтобы прочитать конфигурационные файлы, восстановить ключ или записать, что было установлено, — но это не путь для базы данных, так что не стройте на этом план. Пробуйте их именно в этом порядке и пробуйте немедленно: срок хранения после приостановки — это политика, а не право, и он часто измеряется днями.

Есть предел, который не решит ни один тикет в поддержку, и об этом стоит сказать прямо, потому что это прямое следствие той модели, которую продаёт этот сайт. У хостинга, который никогда не собирал личность, — включая этот, — нет способа доказать, что вы владелец аккаунта, кроме как обладать учётными данными этого аккаунта. В этом весь смысл хостинга без KYC, и в этом же его цена: никто не может восстановить вам доступ на основании фотографии паспорта, потому что никакой паспорт никогда ни к чему не привязывался. Руководство о хостинге без KYC целиком разбирает этот компромисс; операционное следствие простое: ваш план восстановления доступа не может опираться на чью-то добрую волю.

Аварийная последовательность — это та же плановая, только без окна пересечения. Поднимите новый хост из резервной копии, хранившейся не на сервере. Проверьте его как положено, по имени хоста, потому что искушение пропустить проверку сильнее всего именно тогда, когда у вас уже простой. Затем сразу переключайте DNS — дисциплина TTL по-прежнему действует, только теперь вы платите за хвост кэша простоем, а не тратите его как окно пересечения, и это самый ясный аргумент в пользу того, чтобы держать TTL скромными на постоянной основе, а не только как шаг миграции. Ожидайте на какое-то время ухудшение работы почты и предупредите людей заранее, а не объясняйтесь потом.

Урок обобщается далеко за пределы этого одного неудачного дня. Резервная копия, которая живёт на самом сервере, — это не резервная копия; это вторая копия того, что вы вот-вот потеряете. Важное свойство в том, что копия находится в другом месте, шифруется ещё до того, как покидает сервер, доступна только на дозапись (append-only), чтобы скомпрометированный или приостановленный хост не мог удалить собственную историю, и — та часть, которую все пропускают, — хотя бы раз реально восстановлена на одноразовый инстанс, чтобы вы точно знали, что восстановление работает. Чек-лист по защите разбирает, как настроить это на новой машине; а если вы читаете этот раздел потому, что уже слишком поздно, — настройте это на машине, на которую переезжаете, сегодня же, прежде чем делать что-либо ещё.

Откат: определите триггер и назначьте ему срок годности

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

Ограничение, которое вообще определяет, что значит откат, — это запись. С момента, когда новый хост принимает свою первую запись, возврат назад означает либо отбросить эти записи, либо воспроизвести их на старой машине. Так что на самом деле вы выбираете между двумя разными вещами. Откат, сделанный до первой записи, — это просто изменение DNS, и занимает он минуты. Откат, сделанный после дня продакшн-трафика, — это миграция в обратном направлении, со всеми теми же шагами, и занимает она столько же, сколько описано в этом руководстве. Знайте в любой момент времени, какой из двух у вас на руках, и учтите, что второй вариант намного проще, если база данных старой машины по-прежнему способна принять восстановление, а не была перепрофилирована под что-то другое.

Держите старый сервер примерно неделю: включённым, в режиме «только чтение», с всё ещё низким TTL DNS и мониторингом, по-прежнему на него направленным. На самом младшем тарифе эта страховка обходится примерно в два доллара, и это не та цифра, которая должна влиять на решение. А влиять должно то, что недели достаточно, чтобы еженедельные cron-задачи, примерно ежемесячные отчёты и интеграция, срабатывающая только по пятницам, успели хотя бы раз отработать на новом хосте, — а это именно те сбои, которые двухдневное окно упускает полностью.

Затем выводите машину из эксплуатации осознанно. Убедитесь, что access-лог старого хоста был плоским целые сутки. Снимите с него последнюю резервную копию и храните её дольше, чем вам кажется нужным. Отзовите всё, чем он владел: API-ключи, deploy-ключи, пользователей базы данных, его записи в чужих белых списках IP, его проверки мониторинга, его запись в SPF, его MX-запись. Уничтожьте инстанс. И наконец, верните TTL DNS к чему-то разумному — постоянный TTL в 300 секунд означает, что резолверы будут перепроверять запись двадцать раз в час до конца жизни сайта, а это не даёт вам ничего после завершения миграции и стоит немного задержки на каждый холодный запрос. Час — разумное постоянное значение; сутки вполне подходят для записей, которые вы не ожидаете менять быстро.

Миграция в том порядке, в котором её нужно выполнять

За неделю — инвентаризируйте старую машину и напишите runbook: пакеты, включённые юниты, crontab'ы, файрвол, слушающие сокеты, роли базы данных и всех сторонних провайдеров, внёсших старый адрес в белый список. За три дня — разверните новый VPS, восстановите на него данные и отрепетируйте всё целиком по имени хоста с переопределением резолвера, — затем пересоберите его ещё раз только по инвентаризации, чтобы доказать, что инвентаризация реальна. За два дня — снизьте TTL записей A, AAAA и MX до 300, чтобы полный старый TTL успел истечь до того момента, когда вам понадобится низкое значение.

За день — запустите первый проход rsync с -aHAX --numeric-ids, пока продакшн продолжает работать, и поднимите репликацию базы данных либо измерьте окно дампа на реальном датасете. В этом же проходе разберитесь с сертификатами — скопируйте каталог сертификатов вместе с ACME-ключом аккаунта либо переключитесь на DNS-01, — и настройте PTR-запись и новую запись SPF на новом адресе прежде, чем с него уйдёт хоть одно письмо.

В окне переключения: заморозьте запись, выполните финальный rsync с --delete, завершите шаг с базой данных, запустите сервисы, проверьте по реальному имени хоста на маршруте, затрагивающем базу данных, убедитесь, что запрос попал в лог нового хоста, и только тогда переключайте DNS. Оставьте старый хост включённым и в режиме «только чтение». Следите за обоими access-логами, пока старый не выровняется.

Через неделю: убедитесь, что еженедельные задачи отработали на новом хосте, снимите последнюю резервную копию со старого, отзовите его ключи и записи в белых списках повсюду, уничтожьте его и верните TTL обратно. Если вы хотите, чтобы новая машина была не просто новее, а лучше той, что вы оставили, первые пятнадцать минут защиты — естественный следующий шаг, и сделать это намного проще на сервере, который ещё не успел накопить собственный незадокументированный слой. Если вы всё ещё выбираете, где обосноваться, руководство по юрисдикциям разбирает, чем на самом деле различаются Исландия, Нидерланды, Румыния и Швейцария, — а запустить целевую машину можно примерно за минуту, чтобы начать репетицию уже сегодня.

Быстрые ответы

Часто задаваемые вопросы

Сколько реально длится простой при миграции VPS?
Для небольшого сайта с базой данных, дамп которой снимается за пару минут, отрепетированное переключение обычно означает от двух до десяти минут заморозки записи, за которыми следует хвост в несколько часов, пока часть резолверов ещё шлёт трафик на старую машину. Если вместо дампа повышается реплика базы данных, окно заморозки измеряется секундами. Определяющая переменная — не ваша пропускная способность, а то, снизили ли вы TTL DNS достаточно заблаговременно и продолжал ли старый сервер отвечать в течение хвоста.
Действительно ли нужно сначала снижать TTL DNS, или можно просто поменять запись?
Запись можно поменять в любой момент, но резолверы, уже закэшировавшие старый ответ, продолжат его использовать до конца выданного им TTL, — а это на записи с суточным TTL по умолчанию означает, что на старую машину ещё до суток может приходить трафик. Снижение TTL помогает только в том случае, если оно опубликовано минимум за один полный старый TTL до самого изменения, поэтому это первое действие миграции, а не последнее. Если ждать нельзя, изменение всё равно сработает; вы просто заплатите за хвост кэша более долгим окном пересечения, что нормально до тех пор, пока старый хост остаётся включённым.
Можно ли просто перенести rsync'ом всю корневую файловую систему на новый VPS?
Можно, и обычно оно даже загружается, — и всё равно это неправильный подход. В итоге вы получаете машину, чьи ядро и initramfs пришли с другого железа, чьи имена интерфейсов могут не совпадать, чей /etc/machine-id теперь общий с живым сервером, и которая тащит на себе весь дрейф конфигурации, накопленный старой машиной. Ставьте ОС заново из шаблона и переносите rsync'ом данные и конфигурацию, которые вы инвентаризировали. Лишний час покупает вам сервер, о котором вы реально можете рассуждать.
Как перенести базу данных MySQL или PostgreSQL, не потеряв запись?
Два варианта. Снять согласованный дамп — mysqldump --single-transaction для InnoDB, либо pg_dump плюс pg_dumpall --globals-only для ролей и прав, которые не лежат ни в одной конкретной базе, — и смириться с заморозкой длиной в дамп плюс передачу плюс восстановление плюс переиндексацию. Либо настроить реплику на новом хосте за несколько дней, затем остановить запись, дождаться нулевого отставания и повысить её — это сокращает заморозку до секунд. Никогда не копируйте работающий каталог данных на уровне файлов: в результате получается рваный снимок, который может выглядеть рабочим.
Стоит ли копировать SSH-ключи хоста и TLS-сертификаты на новый сервер?
Сертификаты — да: копируйте весь каталог целиком, включая ACME-ключ аккаунта, сохраняя права 600 на приватных ключах, либо переключитесь на проверку DNS-01, чтобы новый хост мог выпустить сертификат ещё до того, как на него указывает DNS. Ключи хоста — вопрос оценки: их копирование делает переезд невидимым для клиентов и автоматизации, что правильно для рядовой миграции, но неправильно, если вы уезжаете потому, что больше не доверяете старому провайдеру, — ведь у любого, кто имел доступ к этому диску, был и ключ. Что бы вы ни выбрали, никогда не держите обе машины живыми с одним и тем же ключом хоста и одним и тем же именем хоста, разрешающимся в обе.
Сломается ли моя почта при переезде на новый IP-адрес?
Доставляемость временно просядет, потому что репутация принадлежит адресу, а не вам. Обновите SPF, включив новый адрес, до переключения и держите оба адреса в списке во время пересечения, скопируйте приватный ключ DKIM, чтобы опубликованный публичный ключ по-прежнему проходил проверку, настройте PTR-запись на новом адресе так, чтобы она совпадала с вашим именем HELO, и проверьте адрес по основным чёрным спискам прежде, чем что-либо отправлять. Держите старый хост как MX с более низким приоритетом примерно неделю, чтобы повторным попыткам и закэшированным запросам было куда приземлиться, и опустошите его очередь перед уничтожением.
Мой старый провайдер приостановил сервер до того, как я успел сделать резервную копию, — можно ли хоть что-то восстановить?
Иногда, и окно для этого короткое. Пока инстанс приостановлен, а не удалён, пробуйте в таком порядке: скачать снимок или резервную копию из панели, загрузиться в аварийном (rescue) или восстановительном (recovery) режиме с подключением вашего диска, и аварийную консоль, которая часто подключается, даже когда сеть отключена, и которой достаточно для восстановления конфигурации и ключей, но не базы данных. Чего не может ни один провайдер, никогда не собиравший личность, — включая нас, — так это подтвердить, кто вы, и вернуть аккаунт, потому что никакой личности никогда и не привязывалось для проверки. Именно поэтому резервная копия обязана жить где угодно, только не на самом сервере.
Как долго нужно держать старый сервер и можно ли позже переехать между юрисдикциями?
Держите его примерно неделю, включённым и в режиме «только чтение», чтобы еженедельные cron-задачи и интеграция, срабатывающая только по пятницам, успели хотя бы раз отработать на новом хосте. На самом младшем тарифе это стоит пару долларов. Переезд между юрисдикциями позже работает точно так же: наши четыре региона — Исландия, Нидерланды, Румыния и Швейцария — предлагают одинаковые тарифы по одинаковым ценам, так что смена юрисдикции — это миграция между двумя вашими собственными серверами без контракта, который нужно расторгать, и без платы, которую нужно вносить.
Применить

Нагрузки, к которым относится это руководство

Каждая карточка открывает страницу с рекомендациями по размеру и FAQ системного администратора.

Читать дальше

Другие руководства

Сопутствующие материалы, продолжающие там, где это руководство заканчивается.

Чек-лист безопасности Чек-лист безопасности VPS: первые пятнадцать минут на новом сервере

Чек-лист безопасности VPS: первые пятнадцать минут на новом сервере

Восемь изменений, которые реально снижают риск на новом VPS, — в правильном порядке. И почему заблокировать себе доступ куда вероятнее, чем дождаться взлома.

16 мин чтения Читать руководство
Гид по доставляемости Свой почтовый сервер на VPS: порт 25, PTR и почему письма всё равно попадают в спам

Свой почтовый сервер на VPS: порт 25, PTR и почему письма всё равно попадают в спам

Свой почтовый сервер на VPS настроить просто, с доставляемостью сложнее. Что проверяют получатели, как работают SPF, DKIM и DMARC и когда self-hosting не подходит.

15 мин чтения Читать руководство
Помощник в принятии решений Выбор юрисдикции: Исландия, Нидерланды, Румыния, Швейцария

Выбор юрисдикции: Исландия, Нидерланды, Румыния, Швейцария

Прямое сравнение четырёх офшорных локаций по параметрам, которые действительно важны: толерантность к DMCA, закон о хранении данных, охват пиринга, задержка и цена.

8 мин чтения Читать руководство
Руководство покупателя VPS или выделенный bare-metal: когда переходить

VPS или выделенный bare-metal: когда переходить

Практический разбор того, когда KVM перестаёт быть достаточным и bare-metal начинает окупаться — с конкретными порогами, а не маркетинговыми текстами.

9 мин чтения Читать руководство
Номер Что на самом деле значит «no-KYC хостинг» в 2026

Что на самом деле значит «no-KYC хостинг» в 2026

Точный разбор термина, который использует каждый сайт хостинга, ориентированного на приватность — что такое KYC, откуда он взялся, чего не собирают провайдеры без KYC и каковы честные ограничения этой модели.

8 мин чтения Читать руководство

Прочитали достаточно? Развернуть за 60 секунд

Без верификации email, без удостоверения, без аккаунта. Выберите тариф, оплатите любой криптовалютой, получите root.