Клонирование живой системы

Бывает, возникает необходимость произвести какие-то серьезные изменения в системе, результат которых неочевиден, либо просто надо посмотреть, к чему это вообще приведет.

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

Рассмотрим ситуацию, когда у нас нет возможности создать резервную копию виртуалки, либо у нас и не виртуалка вовсе, а нам надо поднять в виртуалке (или не виртуалке) клон.

Работы будем проводить на Ubuntu Linux 12.04.

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

Итак, поехали.

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

Вариантов копирования контента может быть несколько. Начиная с подключения диска будущего клона (назовем его destination) к исходному серверу (назовем его source), и копирования всего локально, заканчивая копированием данных по сети. Я остановлюсь на варианте копирования по сети, когда инициатором копирования является исходный сервер. Для этого способа необходимо, чтобы с source был доступен по сети destination.

Работать непосредственно в консоли загруженной с livecd системы не совсем удобно. Лучше подключиться удаленно, и работать в терминале в комфортных условиях. Убеждаемся, что destination доступен по сети, на destination открываем терминал, ставим openssh-server, выставляем пользователю ubuntu пароль:

sudo apt-get update
sudo apt-get install openssh-server
sudo passwd ubuntu

Смотрим, какой у destination ip:

ifconfig | grep "inet addr"

Теперь мы можем подключиться к нашей системе удаленно с source:

ssh ubuntu@destination_ip

Переносить данные будем при помощи rsync. Для того, чтобы корректно передать аттрибуты файлов, копировать будем из-под рута. Зададим руту на destination пароль, после чего передадим на destination публичный ключ, чтобы организовать беспарольный вход.

На destination задаем пароль:

sudo passwd root

Передаем с source на destination публичный ssh-ключ. Говорим из-под пользователя root на source:

ssh-copy-id destination_ip

Если пара ключей на исходном сервере отсутствует, ее надо сгенерировать, после чего повторить попытку передачи ключа:

ssh-keygen
ssh-copy-id destination_ip

Теперь при заходе на destination по ssh нам не придется вводить пароль.

Все дальнейшие действия на обеих системах выполняем из-под рута.

Смотрим на source, как и какие файловые системы у нас подмонтированы

root@ServerSource:~# df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/SYSTEM-ROOT   14G  1.9G   12G  15% /
udev                     487M  4.0K  487M   1% /dev
tmpfs                    199M  228K  199M   1% /run
none                     5.0M     0  5.0M   0% /run/lock
none                     498M     0  498M   0% /run/shm
/dev/sda1                236M   94M  130M  42% /boot

Видим, что настоящих файловых систем всего две: собственно корневая и /boot. Остальные файловые системы виртуальные.
Далее, смотрим, как у нас монтируется своп:

root@ServerSource:~# grep swap /etc/fstab
/dev/mapper/SYSTEM-SWAP none            swap    sw              0       0

Своп располагается в LVM-томе /dev/mapper/SYSTEM-SWAP. Смотрим его размер:

root@ServerSource:~# lvscan
  ACTIVE            '/dev/SYSTEM/SWAP' [1.86 GiB] inherit
  ACTIVE            '/dev/SYSTEM/ROOT' [13.90 GiB] inherit

Размер свопа — два гига.

Итак, у нас должно быть три тома: один, монтирующийся в /boot, находится непосредственно на диске. Два других (ROOT и SWAP) расположены в группе томов SYSTEM.

Во-первых, нам надо на destination установить пакет lvm2 для работы с LVM:

apt-get install lvm2

Разбиваем диск на destination

По большому счету, нам не надо придерживаться тех же размеров томов, которые были на source. Нам необходимо, чтобы данные, находящиеся на source, вместились в соответствующие тома на destination. Поэтому разбивать можно «на глазок».

Диск на destination должен содержать три раздела: под загрузчик, под /boot, и под группу томов SYSTEM.

Разбиваем диск.

Создаем на диске таблицу разделов GPT:

parted /dev/vda mklabel gpt

Создаем раздел для размещения системных данных загрузчика GRUB:

parted /dev/vda mkpart biosgrub 0% 10M

Устанавливаем на этот раздел метку «bios_grub» для того, чтобы загрузчик понял, где располагать свои данные при установке:

parted /dev/vda set 1 bios_grub on

Создаем раздел под /boot размером 256M:

parted /dev/vda mkpart boot 10M 266M

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

parted /dev/vda mkpart system 266M 100%

Смотрим, что у нас получилось:

root@ubuntu:~# parted /dev/vda print
Model: Virtio Block Device (virtblk)
Disk /dev/vda: 34.4GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start   End     Size    File system  Name      Flags
 1      1049kB  10.5MB  9437kB  ext4         biosgrub  bios_grub
 2      10.5MB  266MB   256MB                boot
 3      266MB   34.4GB  34.1GB               system

Не обращаем внимания на то, что у первого раздела на диске указан тип файловой системы «ext4«. Это просто информационное поле, и возиться с ним мы сейчас не будем.

В /dev/vda1 будут располагаться системные данные загрузчика GRUB. /boot у нас будет расположен в /dev/vda2, а группа томов SYSTEM — в /dev/vda3.

Создаем группу томов SYSTEM:

vgcreate SYSTEM /dev/vda3

Создаем логический том SWAP объемом 2G:

lvcreate -n SWAP -L 2G SYSTEM

Создаем логический том ROOT, и выделяем под него все оставшееся свободное пространство в группе томов SYSTEM:

lvcreate -n ROOT -l +100%Free SYSTEM

Смотрим, что у нас получилось:

root@ubuntu:~# lvscan
  ACTIVE            '/dev/SYSTEM/SWAP' [2.00 GiB] inherit
  ACTIVE            '/dev/SYSTEM/ROOT' [29.76 GiB] inherit
root@ubuntu:~#

Форматируем разделы. /dev/vda2 и /dev/SYSTEM/ROOT, как ext4, и /dev/SYSTEM/SWAP, как своп:

mkfs.ext4 /dev/vda2
mkfs.ext4 /dev/SYSTEM/ROOT
mkswap /dev/SYSTEM/SWAP

Структура нашей будущей файловой системы такова: /dev/SYSTEM/ROOT монтируется в корень (/), и /dev/vda2 монтируется в /boot.

Для того, чтобы скопировать данные с source, нам надо подмонтировать в правильном порядке целевые файловые системы к destination. Монтировать будем в каталог /mnt:

mount /dev/SYSTEM/ROOT /mnt    # монтируем /dev/SYSTEM/ROOT в /mnt
mkdir /mnt/boot                # создаем будущую точку монтирования /boot
mount /dev/vda2 /mnt/boot      # монтируем туда /dev/vda2

Вот так у нас сейчас выглядят подмонтированные к destination файловые системы:

root@ubuntu:~# df -h
Filesystem               Size  Used Avail Use% Mounted on
/cow                    1002M  149M  854M  15% /
udev                     993M  4.0K  993M   1% /dev
tmpfs                    401M  720K  401M   1% /run
/dev/sr0                 712M  712M     0 100% /cdrom
/dev/loop0               676M  676M     0 100% /rofs
tmpfs                   1002M   16K 1002M   1% /tmp
none                     5.0M     0  5.0M   0% /run/lock
none                    1002M   84K 1002M   1% /run/shm
/dev/mapper/SYSTEM-ROOT   30G  172M   28G   1% /mnt
/dev/vda2                236M  6.1M  218M   3% /mnt/boot

Видим, что наш будущий корень подмонтирован в /mnt, а будущий /boot подмонтирован в /mnt/boot.

Готовимся к копированию данных.

В современном Линуксе многие точки монтирования содержат виртуальные файловые системы, которые монтируются по определенным правилам при старте системы. Содержимое этих точек нам копировать не надо, надо лишь создать каталоги под них.

Смотрим на source, какие каталоги надо исключить при копировании:

root@ServerSource:~# mount
/dev/mapper/SYSTEM-ROOT on / type ext4 (rw,errors=remount-ro)
proc on /proc type proc (rw,noexec,nosuid,nodev)
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
none on /sys/fs/fuse/connections type fusectl (rw)
none on /sys/kernel/debug type debugfs (rw)
none on /sys/kernel/security type securityfs (rw)
udev on /dev type devtmpfs (rw,mode=0755)
devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
tmpfs on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755)
none on /run/lock type tmpfs (rw,noexec,nosuid,nodev,size=5242880)
none on /run/shm type tmpfs (rw,nosuid,nodev)
/dev/vda1 on /boot type ext4 (rw)
root@ServerSource:~#

Исключаем «/proc«, «/sys«, «/dev» и «/run«.

Запускаем синхронизацию

На source выполняем:

rsync -aHAXv --progress --numeric-ids --exclude "/proc/*" --exclude "/sys/*" --exclude "/dev/*" --exclude "/run/*" / destination_ip:/mnt

Смотрим, есть ли в fstab на source инструкции монтировать том по UUID:

root@ServerSource:~# cat /etc/fstab | grep -i uuid
# device; this may be used with UUID= as a more robust way to name devices
UUID=2f577cee-dba0-4dc9-a535-846ff451ec59 /boot           ext4    defaults        0       2
root@ServerSource:~#

Есть. На destination смотрим, какой UUID у нас теперь для /boot:

root@ubuntu:/mnt# blkid /dev/vda2
/dev/vda1: UUID="2b39fd7e-cea7-4a13-8d2e-e2635686bcd5" TYPE="ext4"
root@xubuntu:/mnt#

Прописываем корректный UUID в файле /mnt/etc/fstab

Перезагружаем destination

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

Грузимся в режиме восстановления («Rescue a broken system«).

На этапе выбора корневой файловой системы в качестве рута выбираем /dev/SYSTEM/ROOT:

screen01

Запускаем shell в контексте клонированной системы:

screen02

Смотрим список подмонтированных файловых систем.
В нашем случае произошел сбой, и файловая система /boot отображается некорректно подмонтированной — у нее неверно указан размер раздела, плюс отсутствуют данные в самом разделе. Отмонтируем ее и примонтируем обратно:

screen03

При отмонтировании может возникнуть ошибка, как показанно на скриншоте. Не обращаем внимания.

Прописываем загрузчик:

grub-install /dev/vda

Обновляем конфигурацию загрузчика:

update-grub

Все

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

0 комментариев:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *