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

Меня зовут Дмитрий Штегельман, я системный инженер в VK Tech. В этой статье я расскажу об опыте миграции PaaS MS SQL Server с гигабайтами данных из Azure в VK Cloud — выстроенном процессе, подводных камнях и полученном результате.

Узелок на плечо и в путь — мигрируем


В рамках «приземления» ИТ, одному из сервисов онлайн-образования надо было перенести ИТ-инфраструктуру из облака Microsoft Azure в облако российского провайдера — VK Cloud. Причем сделать это максимально бесшовно, без влияния на конечных пользователей и, по возможности, без даунтайма.

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

  • около 70 виртуальных серверов;
  • Postgres с бинарниками внутри базы;
  • очереди сообщений на платформе Kafka;
  • in-memory database Redis;
  • MS SQL Server.

Причем основные вопросы были связаны именно с переносом MS SQL Server, которая была развернута в облаке Azure как PaaS (Platform as a Service, платформа как услуга).

Копируй и переноси — что тут сложного?


Миграция MS SQL Server с Azure выглядит довольно легко — сделал резервную копию, перенес в нужное облако на предварительно подготовленную виртуальную машину или в свой ЦОД, развернул в подготовленный инстанс, переключил ресурсы и готово. При таком сценарии даже можно обойтись без даунтайма — можно настроить репликацию из Azure и просто постепенно переливать все данные в инстанс на новой платформе.

В теории никаких сложностей быть не должно, особенно если учесть, что:

  • мигрировать в облако Azure легко — есть много инструкций и поддержка разных алгоритмов миграции.
  • перенос данных внутри Azure тоже не обременен проблемами — можно назначить создание резервных копий по расписанию, подключить AlwaysOn с запросами на чтение ко вторичной синхронной реплике, регулировать производительность с учетом динамики нагрузки в процессе переноса данных.

Но в действительности попытки любой миграции «вовне» из Microsoft Azure нередко упираются в vendor-lock и невозможность использовать классические методики миграции данных.

От иллюзии к реальности


Первое и довольно ощутимое проявление vendor-lock от Azure — невозможность вытянуть резервную копию в привычных форматах *.bak и *.trn. Вместо этого можно получить только дамп базы в формате *.bacpac — фактически файл экспорта данных. Подробнее об этой сущности можно прочитать здесь.

За неимением альтернатив был выбран этот вариант — после запуска экспорта продовая база MS SQL Server в Azure превратилась в BACPAC-файл размером 519 Гб. На его подготовку ушло 10 часов, еще час — на копирование файла в VK Cloud.

Далее появился блокер в виде невозможности использовать команду RESTORE DATABASE — вместо этого надо:

  • зайти в «SSMS»;
  • нажать «Databases»;
  • выбрать «Import Data-tier Application…»



Затем выбирается заранее скопированный файл BACPAC или назначается прямой импорт из Azure.



Тут же выбирается имя базы и расположение ее файлов, после чего стартует анализ файла.

К слову, это неожиданно длительный процесс с четким алгоритмом действий:

  • запускается изучение всех метаданных в базе;
  • начинается пересчет всех таблиц, данных в них и индексов;
  • создается пустая БД, в которой создаются метаданные;
  • отключаются индексы, а в таблицы заливаются данные;
  • после завершения миграции на таблицах с данными включаются индексы.

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





Такой подход к реализации процесса неизбежно сказывается на сроках — например, тестовый импорт занял 11 часов и два раза заканчивался провалами (ошибками вставки данных и включения индексов), после которых импорт сразу прерывался. Так удалось перенести в облако VK Cloud девовскую базу размером 18 ГБ, но для миграции работающих продуктовых инсталляций такой способ однозначно не подходил.

Палкой в колесах при миграции данных «вовне» оказалась и ограниченность функционала репликации в Microsoft Azure. Фактически механизм есть, но он позволяет создавать реплики только в рамках Azure, например, на распределенных серверах, но не в облака других вендоров или OnPrem. 



Примечательно, что в открытых источниках нет упоминания успешных кейсов по решению подобных задач. Может сложиться впечатление, что перенос PaaS SQL Server из Microsoft Azure в другое облако — нехоженая тропа. 

В итоге, были база данных MS SQL Server в Microsoft Azure в виде PaaS и IaaS AlwaysOn в VK Cloud, готовый принять базу, но сроки и надежность метода миграции полностью не устраивали. 

От ограничений к новому плану


Помимо подхода с репликацией и созданием резервных копий Microsoft Azure также позволяет использовать SQL Data Sync — это собственное решение вендора, с помощью которого можно настроить синхронизацию БД из Azure в другие среды. Но у инструмента есть ограничения, которые нужно учитывать.

  • В таблице должен быть первичный ключ, который не может быть с типом данных sql_variant, binary, varbinary, image, xml.
  • Имена таблиц не могут содержать точки и квадратные скобки, а также спецсимволы (:! " # $ % ' ( ) * + -) или пробел.
  • Если в разных схемах есть таблицы с одинаковым именем — синхронизировать можно только одну из них.
  • Нельзя реплицировать вычисляемые поля и временные столбцы.
  • Репликация поддерживает только два свойства индекса: уникальный и кластерный/не кластерный. Другие свойства (IGRORE_DYP_KEY или WHERE) не поддерживаются, целевой индекс будет без этих свойств.
  • Не поддерживаются типы данных: Filestream, SQL/CLR UDT, XMLSchemaCollection, Cursor, RowVersion, Timestamp, Hierarchyid.
  • Можно использовать только 5 групп синхронизации.
  • Длина имени синхронизированных объектов (БД, схемы, таблицы, столбцы) — не более 50 символов
  • Максимальное количество таблиц на группу синхронизации — 500.
  • Максимально допустимое количество столбцов в таблице — 1000.
  • Объем в строке данных — не более 24 Мб.

В рамках кейса ключевыми ограничениями стала возможность использования только 5 групп синхронизации и только 500 таблиц в одной группе синхронизации — то есть в рамках одной синхронизации можно было запустить только 5 джобов на 2500 таблиц в одной БД.

Подготовка SQL Data Sync и целевой платформы


Перед переносом данных предстояло подготовить целевую инфраструктуру. Для этого был снят дамп с работающего прода в Microsoft Azure, который потом был полностью очищен от данных и развернут на платформе VK Cloud в качестве целевой базы данных для синхронизации с продом в Azure.

При подготовке было важно учесть два фактора:

  • база в Azure не должна быть зашифрована — иначе можно получить нечитаемые данные в целевой БД и проблемы с постановкой БД в группу доступности AlwaysOn;
  • чтобы избежать ошибок при переносе данных, Foreign Keys нужно отключать в целевой БД на время синхронизации — включить их можно сразу после завершения миграции.

После установки сервиса SQL Data Sync по инструкции разработчика, стал вопрос его подготовки к миграции данных. 

  • На целевой сервер был установлен агент Data Sync Agent. Агент устанавливается как служба. УЗ из под которой он запускается, должна иметь доступ к целевой БД.
  • На портале Azure была создана группа синхронизации.



  • Следом была создана база синхронизации — промежуточная сущность между БД-источником и целевой платформой. Для недопущения любых конфликтов между БД были выбраны настройки «Hub win», которые исключают влияние изменений синхронизации на БД-источник.


  • Также был выбран ручной тип синхронизации — это делает процесс более контролируемым. К тому же в автоматический режим можно перейти уже после настроек.
  • Далее с помощью настроек агента было создано защищенное соединение между целевым сервером в VK Cloud и Azure — был создан агент и сгенерирован его ключ для добавления соответствующей записи на целевом сервере. 



  • Здесь же прописывается созданный в Azure ключ и регистрируется подключение к группе синхронизации. 

Синхронизация: общий алгоритм и реализация


По умолчанию процесс миграции данных с помощью утилиты SQL Data Sync выглядит следующим образом:

  • Создается группа синхронизации, прописываются таблицы, которые планируется синхронизировать. Из таблиц удаляются поля, которые не нужно синхронизировать. После этого запускается синхронизация.
  • Со стартом синхронизации данные из исходной БД начинают поступать в промежуточную БД, которая создается в Azure. Промежуточная БД — высоконагруженный сервис, поэтому для нее нужно предусматривать дополнительные ресурсы и инструменты мониторинга.
  • Далее база синхронизации трансформирует данные в batch-файлы и складывает их на диск целевого сервера. По умолчанию данные загружаются на системный диск в каталог AppData\Local\temp. В случае с большими БД это чревато заполнением системного диска и, как результат, остановкой сервера, поэтому лучше выделять под эти задачи отдельный диск.
  • После формирования batch’ей, они загружаются в целевую БД, причем не напрямую в таблицы, а сперва во временные, а из них — в целевые. 
  • Работа групп синхронизации завершается, когда заканчивается синхронизация всех таблиц, указанных в группе. Процедура запускается повторно, если данные в таблицах изменяются. Также можно включить периодический запуск по таймеру.


Условная схема миграции данных из Microsoft Azure в VK Cloud с помощью SQL Data Sync

В итоге, с учетом ограничений SQL Data Sync и стандартного алгоритма синхронизации, был разработан план миграции. Согласно ему:

  • Было оценено количество таблиц в базе без учета таблиц, которые не используются и можно не реплицировать. Таких оказалось 270.
  • Был определен объем данных в каждой из таблиц и количество строк — 7 таблиц, более 100 млн строк каждая. 
  • Выявили таблицы-константы, которые можно не реплицировать, а перенести вручную на финальном этапе миграции.

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

Проделанная подготовка позволила максимально рационально сформировать из таблиц 5 групп синхронизации для SQL Data Sync: 

  • в первые две группы попали 10 самых объемных таблиц;
  • в третью — средние (от 20 до 50 млн строк);
  • в четвертую и пятую — оставшиеся 180 таблиц.

На подготовку к синхронизации, отладку всех процессов и устранение «граблей» потребовалось около двух недель. 

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

Изначально с синхронизацией первых четырех из пяти групп проблем не возникло — в интерфейсе отображался статус Downloaded: 0 Change applied. 



Как оказалось, несмотря на уведомление утилиты, проблемы все же были.

Так, для снижения рисков, был включен запуск групп синхронизации по таймеру, чтобы каждые 20-30 минут догружать обновленные данные. В паре с ним работал скрипт, который считал количество строк в таблицах источника и приемника — это позволяло оценивать синхронизацию, если каких-то данных не хватало. Именно это и было обнаружено в четвертой группе, которая постоянно синхронизировала данные из небольших таблиц (до 20 млн строк) — получить статус «синхронизировано» не удавалось. Завершить синхронизацию группы не помогла даже двухчасовая остановка сервиса с отключением пользователей в технологическое окно.

После анализа ситуации и изучения вариантов было принято решение загрузить недостающие 30 таблиц вручную. Но тест с INSERT INTO показал, что на загрузку уйдет более двух часов, то есть недопустимо долго. Поэтому для заливки была выбрана утилита bcp (bulk copy), с которой на загрузку таблиц через csv в тестовую среду ушло всего 20 минут. Также в момент остановки сервиса с помощью bulk copy была дозагружена пятая группа синхронизации и выполнена сверка данных. После этого миграция MS SQL Server из Microsoft Azure в VK Cloud была полностью завершена.

На переключение основной инфраструктуры с MS SQL Server в Microsoft Azure на БД в VK Cloud ушло около часа — за это время также был выполнен деплой приложения, переключение других баз и DNS. 

Уже после миграции на платформе VK Cloud были проведены работы по отключению групп синхронизации, очистке промежуточных таблиц, настройке синхронной репликации AlwaysOn, перенаправлению запросов на чтение на синхронную реплику, настройке резервного копирования (полного и журнала транзакций) на S3 VK Cloud, и прочие сопутствующие работы, с которыми помогла команда облачного провайдера в рамках сопровождения после миграции.

К выводам


Миграцией ИТ-инфраструктуры сейчас сложно удивить — с этой задачей сталкивается большинство команд, которые ранее работали с иностранными инструментами или строили свои решения на базе зарубежных платформ. Но опыт миграции MS SQL Server из Microsoft Azure в VK Cloud подсветил несколько проблем и одновременно помог прийти к важным выводам:

  • Microsoft Azure накладывает жесткие ограничения на миграцию данных вовне.
  • Классические подходы не всегда уместны, особенно если время на миграцию лимитировано.
  • Не стоит игнорировать встроенные инструменты, даже если для работы с ними надо соблюдать десятки требований — в рамках кейса такой «волшебной палочкой» оказался сервис SQL Data Sync.
  • Как правило, перенос данных и сервисов — долгий процесс, который может требовать остановки основного продукта. Это надо учитывать при планировании миграции, особенно если остановка сервиса на длительный период недопустима — например, в нашем случае это привело к необходимости замены инструмента для синхронизации.
  • Проверка полноты и целостности данных после миграции — обязательная процедура. Даже если инструмент миграции показывает, что все хорошо — лучше перепроверить. Именно такая дотошность и перестраховка в нашем случае помогли не потерять 30 таблиц с данными.
  • Чем выше экспертиза, тем мягче проходит миграция, поэтому не стоит отказываться от помощи специалистов «принимающей стороны». В рамках кейса такую поддержку оказывала команда VK Cloud Professional Services, которая помогала с миграцией на каждом этапе. 

Комментарии (5)


  1. marks
    20.12.2023 09:23

    12 плюсов при 70 просмотрах? Я все понимаю, рейтинг многим компаниям важен, но не так же, ребят. Зачем так накручивать? Крупная же компания, по-другому никак? )


    1. ShteDy Автор
      20.12.2023 09:23

      Добрый день!

      Коллеги решили поддержать мой первый пост на Хабре. Никаких накруток.


  1. Sannis
    20.12.2023 09:23

    А могли бы вы кратко рассказать, не будет ли ровно таких же сложностей при переезда с VK Cloud на Azure? Или на GCP/AWS.


  1. vagon333
    20.12.2023 09:23

    Может спрошу глупость, но насколько оправдано хранение больших объемов в облаке для MS SQL Server?

    По нашим подсчетам, Prod данные большого объема экономичнее хранить на своих on-prem серверах.
    Т.е. colo от 1u до нескольких серверных racks, и далее self-hosting.

    Я в курсе, что статья от vk и, возможно, вопрос не по адресу, но прочитав сложности переноса ощущение что ребята вырвались из одного капкана ... и прыгнули в другой.


    1. ShteDy Автор
      20.12.2023 09:23

      Тут речь о том, что сервис изначально планировался на облачной инфраструктуре. Поэтому и хостился в Azure. Когда было принято решение о переносе, речи о собственных серверах не шло. К тому же в статье речь только про СУБД, про прочие сервисы окружающие его (в том числе и управляемы облаком) тут не описано, но они естественно присутствовали.