Перенос образа виртуальной машины между облачными хостерами или устанавливаем Windows Server на Digital Ocean

Перенос образа виртуальной машины между облачными хостерами или устанавливаем Windows Server на Digital Ocean

К примеру, Digital Ocean не предоставляет возможности загрузить свой образ виртуалки, более того, так же нельзя подключить ISO-образ для установки (правда, есть KVM — и на том спасибо). Поэтому придётся пойти хитрым путём и делать всё через ssh. Основная идея — на новой виртуалке отмонтировать корневую файловую систему, залить файлы/образ от старой, обновить настройки grub, обновить настройки сети и fstab, перезагрузить. Самое неочевидное в первом шаге. Можно отмонтировать / и на живой системе, это реально, хоть и муторно. Гораздо проще добавить ssh сервер и пару утилит в initramdisk и сделать всё оттуда, т.к. на этом этапе загрузки ОС корневая система еще не примонтирована. Собственно, вся статья — это демонстрация утилиты для включения ssh сервера в ramdisk + два разобранных примера.

Перенос сервера Debian из Xen-а c паравиртуализацией на Digital Ocean.

Важно чтобы на DigitalOcean виртуалка была с возможностью менять ядро с самой виртуалки (В панели управления DigitalOcean, во вкладке Kernel должно быть написано что меняйте ядро внутри хоста). Источник на Xen:

Там стоит nginx с такой вот демо страницей

Шаг 1. Подготовка сервера-источника к переносу

Можно ничего не подготавливать, просто выключить сервер-источник и отдавать файлы/образ из гипервизора, но это не интересно и, к тому же, источник вполне может быть не на виртуалке, а на голом железе. Поэтому, первым шагом мы перемонтируем корневую файловую систему (и, соответственно, так же подключенные ФC, если есть) в read-only. Перемонтировать в read-only гораздо проще чем отмонтировать целиком — достаточно просто прибивать демоны, которые могут что-то писать.

Смотрим что осталось. Нам интересны строчки где колонка FD заканчивается на w или u

Ага, остался rsyslog

Если получилось — то хорошо, если нет — то дальше искать кто держит файлы открытыми на запись. Как правило, достаточно выключить все дополнительно установленные демоны + syslog.

Шаг 2. Отмонтирование корневой ФС на сервере-получателе

Получателем у нас будет Ubuntu 16.04. В теории абсолютно не важно что на получателе будет стоять до переноса, т.к. это всё перезатрётся, просто утилита для автоматизации настройки initramdisk работают с ubuntu/debian. Итак, свежесозданная ubuntu 16.04 на DigitalOcean:

Пингуем IP адрес получателя и следим на TTL. Как только TLL в ответах поменяется — это значит что initramdisk загрузился и ждёт подключений. По умолчанию он долго ждать не будет, если через 15 секунд никто не подключился то загрузка пойдёт дальше.

Подключаемся по ssh и получаем shell. В моём случае авторизация у root-а по ключу, но будет работает и по паролю, даже если в sshd_config стоит 'PermitRootLogin without-password' (потому как в initramdisk стоит dropbear, а не sshd).

Собственно, один раздел.

Шаг 3. Перенос данных

Можно перенести все данные либо через dd (естественно если размер диска получателя не меньше чем источника), либо через rsync. dd будет предпочтительней если на файловой системе мало свободного места либо ну очень много мелких файлов.

Вариант с dd по ssh: Вариант с dd без шифрования, но с компрессией:

Из соседней консоли можно постоянно слать сигнал USR1 на dd чтобы видеть как идут дела:

Вариант с rsync:

На получателе пересоздаём файловую систему и монтируем её:

Файловая система ext3, а не ext4 только потому что на источнике ext3. Теперь с сервера-источника:

(Аккуратней со слешами в конце, они должны быть)

Шаг 4. Проверка ядра, проверка /etc/fstab, настройка сети, обновление настроек grub

На получателе монтируем свежескопированную ФС и делаем chroot туда:

Проверяем что ядро установлено (это нужно если ОС источника была на xen с паравиртуализацией)

Обновляем настройки сети в /etc/network/interfaces

Тут есть небольшой подводный камень: в некоторых случаях на некоторых ядрах интерфейсы могут называться по-другому. К примеру, в Ubuntu он может называться ens3, а на ядре Debian уже eth0. Лучше просто на всякий создать записи для обоих вариантов. Либо можно в /etc/default/grub дописать настройки ядра чтобы оно не использовало ens наименования (заменить/добавить строчку GRUB_CMDLINE_LINUX):

+ удалить файл /etc/udev/rules.d/70-persistent-net.rules чтобы ядро начало считать интерфейсы с eth0

Сама корневая фс в /etc/fstab (Устройство называется теперь vda1 + удалить своп)

Можно и через blkid узнать UUID и вписать его:

Все, можно всё отмонтировать и перезагрузить:

После перезагрузки проверяем что веб-страница открывается с нового IP:

Установка Windows Server 2012r2 на DigitalOcean

Шаг 1. Подготовка источника

С Windows у нас дела обстоят немного сложней, поэтому я сначала делал виртуалку в VmWare, и потом её переносил из гипервизора. При установке указывал что ОС будет Linux, драйвер диска Lsi SAS. Установленный Windows сервер нужно приготовить к переносу:

Загрузка драйверов для KVM

Скачиваем fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso (https://pve.proxmox.com/wiki/Windows_VirtIO_Drivers), распаковываем, устанавливаем Tools и для каждого inf файла для нашей версии выполняем

(Или сразу для всех )

Немного костыльной магии

Костыли это потому что по-хорошему это нужно делать через unattended.xml. Создаем файл c:\firstrun.bat, и пишем туда следующее, попутно заменяя mac/ip/маску/шлюз/пароль тем, что у нас есть на виртуалке приёмнике:

Далее в консоли добавляем этот скрипт на автозапуск и делаем sysprep в audit:

Образ готов, при следующей загрузке он начнёт себя конфигурировать.

Шаг 2. Отмонтирование корневой ФС в источнике, переразметка партиций

Загружаемся в ramdisk как в предыдушем примере, двигаем корневую ФС, создаём новые разделы в начале диска, обновляем настроки grub:

Первый раздел — загрузочный для Windows, 350Мб, второй — сама Windows, третий, соответственно, Linux. Откуда эти числа взялись — будет понятно на следующем шаге, пока что можно сначала сделать два раздела случайного размера (но чтобы последний сектор был не меньше размера образа Windows) и потом уже их пересоздать из Ubuntu когда будет скопирован образ на файловую систему Ubuntu. В конечном итоге важно чтобы разделы для Windows были на тех же местах и такого же размера, что и в образе-источнике. Я оставил так много на корневую ФС потому как я буду временно туда класть vmdk файл. В теории можно сразу писать его через pipe на раздел. Теперь копируем Ubuntu (она-то до сих пор лежит в начале диска), 25Гб с /dev/vda начиная с 2048 сектора в /dev/vda3:

(skip и count в 8 раз уменьшенные потому как блок не 512, а 4096) Обязательно обновляем настройки grub и правим /etc/fstab если нужно (/dev/vda1 заменить на /dev/vda3):

Шаг 3. Любым образом копируем vmdk файл на опять загрузившуюся убунту

Хорошо, если vmdk файл сразу представляет собой образ диска (если нет — то нужно сконвертировать в raw через «qemu-img convert -p -f vmdk original.vmdk -O raw converted.raw»)

Вот, собственно, откуда берутся значения для /dev/vda1 и /dev/vda2 для предыдущего шага.

Копируем Windows с образа в разделы:

(skip и count так же умешьненные в 8 раз) Можно попытаться примонтировать /dev/vda1 и /dev/vda2 для того, чтобы проверить что всё ок, и, если нужно, поправить настройки в костыльном скрипте.

Обновляем grub, смотрим что он увидел Windows:

Теперь включаем Windows на следующую перезагрузку, это удобно если что-то пойдёт не так, то вернуться можно выключив и включив виртуалку:

Т.к. образ подготовленный через sysprep + костыльный скрипт, то Windows захочет 2 раза перезагрузится с интервалом в несколько минут. Т.е. еще 2 раза придётся залогинится в ubuntu и запустить последние 2 команды.

Шаг 4. Загрузка Windows по-умолчанию

Вместо того, чтобы включать windows в дефаулт в grub лучше просто добавить в /etc/rc.local:

— если Windows перестанет загружаться, то можно успеть залогинится в Ubuntu и сделать «killall sleep».

📎📎📎📎📎📎📎📎📎📎