Рубрики
Администрирование

Клонирование сервера CentOS с помощью dump/restore

Всем привет!
В данной заметке я расскажу о своем опыте клонирования сервера под управлением CentOS. Сама процедура в общем-то обычная и логичная, но есть некоторые моменты, про которые необходимо знать и помнить при переносе системы с одного железа на другое.

Постановка задачи

Имеется физический эталонный сервер с CentOS 5.5 на борту (впрочем версия ОС не имеет особо значения), на котором установлено и настроено программное обеспечение.
Так же имеется некоторое количество других серверов, разных конфигураций, на которые требуется поставить все то же самое, что стоит на эталонном сервере.
Отличие серверов только в настройках сети и конфигурации некоторого ПО.

Немного теории

В общем то, для решения данной задачи есть много разных способов, среди них такие как:

  1. dump/restore. Это 2 утилитки которые позволяют делать бекапы разделов, которые впоследствии можно восстановить. Так же имеется возможность делать инкрементальный бэкап с возможностью компрессии. Не смотря на то, что dump работает с разделами, в дампы попадают только данные. Неоднократно использовал эти утилиты в составе FreeBSD, они себя прекрасно зарекомендовали, наверное поэтому я и выбрал этот вариант.
  2. rsync. Это, по сути, синхронизация файлов по сети. Быстро, удобно, хорошо. Но я сам ни разу не использовал.
  3. dd, старый добрый dd. С dd основная тонкость в том, что эта утилита работает с устройствами на уровне блоков и копирует их байт-в-байт. Отсюда вытекает пара моментов: первое — это то, что если у вас раздел 50 гиг и из них занято всего 5, то dd все равно скопирует все 50; второе — как следствие из первого, если у вас исходный и целевой разделы разных разделов, точнее если целевой меньше исходного, то возможны проблемы.
  4. CloneZilla. В общем-то нормальный вариант, это live-cd, к которому прикручен какой-то GUI, в котором можно с помощью вопросов и ответов, а-ля визард, выбрать что склонировать и куда. Но так как это live-cd, то требуется перегружать сервер, и следовательно он какое-то время будет не работоспособен.
  5. Kickstart + Anaconda, так же как и DRBL — это установка по сети в том или ином виде. Для меня не подходит потому что серверы физически не находятся в одной сети.
  6. Acronis True Image платный, да и вообще это больше к виндам, и уж точно не Unix-way.

Что хочется добавить еще, какой бы способ вы не выбрали, это не спасет вас от последующей правки fstab, скриптов инициализации сети, hosts и т.д.

Пара слов о эталоне

Вот какие разделы и диски имеются на эталонном сервере:
2 раздела: /boot на /dev/sda1 и / на логическом разделе LVM LogVolRoot

root@Etalon: ~# df -h
Файловая система      Разм  Исп  Дост  Исп% смонтирована на
/dev/mapper/VolGroupRoot-LogVolRoot
                       60G  6,7G   51G  12% /
/dev/sda1              99M   13M   81M  14% /boot
tmpfs                 2,0G     0  2,0G   0% /dev/shm

В системе один физический раздел

root@Etalon: ~# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               VolGroupRoot
  PV Size               67,65 GB / not usable 24,47 MB
  Allocatable           yes (but full)
  PE Size (KByte)       32768
  Total PE              2164
  Free PE               0
  Allocated PE          2164
  PV UUID               5lC4re-OsI6-zt7Z-LKGd-Nqa4-zGsK-Y0MaF0

И одна Volume Group которая состоит из этого одного физического раздела /dev/sda2

root@Etalon: ~# vgdisplay
  --- Volume group ---
  VG Name               VolGroupRoot
  System ID           
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               2
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               67,62 GB
  PE Size               32,00 MB
  Total PE              2164
  Alloc PE / Size       2164 / 67,62 GB
  Free  PE / Size       0 / 0 
  VG UUID               mbifBq-CW60-C5V7-U1dX-SBsY-kyIY-kYbd93

В этой группе есть 2 логических раздела: LogVolRoot — смонтированный как / и LogVolSwap — раздел для свапа

root@Etalon: ~# lvdisplay
  --- Logical volume ---
  LV Name                /dev/VolGroupRoot/LogVolRoot
  VG Name                VolGroupRoot
  LV UUID                zLCehW-OWcN-gSem-GjQW-w5Tk-9JOs-O9i43Q
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                61,81 GB
  Current LE             1978
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0
 
  --- Logical volume ---
  LV Name                /dev/VolGroupRoot/LogVolSwap
  VG Name                VolGroupRoot
  LV UUID                OW4EOe-LKw2-VnRI-X2EA-PBGU-k950-uh6zeu
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                5,81 GB
  Current LE             186
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:1

Ну и напоследок fstab:

root@Etalon: ~# cat /etc/fstab
/dev/VolGroupRoot/LogVolRoot /                       ext3    defaults        1 1
LABEL=/boot             /boot                   ext3    defaults        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
/dev/VolGroupRoot/LogVolSwap swap                    swap    defaults        0 0

От слов к делу

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

  • Делаем дампы разделов на эталонном сервере либо на внешний диск, либо на какой-то NAS.
  • Грузимся с live-cd на целевом сервере.
  • Подготавливаем диски целевого сервера: разбиваем на разделы, форматируем.
  • Подцепляем внешний диск/nas где лежат наши бэкапы.
  • Накатываем дампы.
  • Правим системные конфиги
  • Пересобираем initrd
  • Ставим grub в MBR.
  • Ребутимся и надеемся увидеть счастье.

Теперь по шагам.
1. Делаем дампы разделов. Поскольку этот целевой сервер я мог включить в общую сетку, то дампы я залил на самбовский сервер.

[12:59] cmd#:696
root@Etalon: ~# dump -0 -f boot.dmp -L "Etalon.boot" /boot
  DUMP: Date of this level 0 dump: Tue Nov 16 13:02:35 2010
  DUMP: Dumping /dev/sda1 (/boot) to boot.dmp
  DUMP: Label: Etalon.boot
  DUMP: Writing 10 Kilobyte records
  DUMP: mapping (Pass I) [regular files]
  DUMP: mapping (Pass II) [directories]
  DUMP: estimated 7641 blocks.
  DUMP: Volume 1 started with block 1 at: Tue Nov 16 13:02:36 2010
  DUMP: dumping (Pass III) [directories]
  DUMP: dumping (Pass IV) [regular files]
  DUMP: Closing boot.dmp
  DUMP: Volume 1 completed at: Tue Nov 16 13:02:36 2010
  DUMP: Volume 1 7700 blocks (7.52MB)
  DUMP: 7700 blocks (7.52MB) on 1 volume(s)
  DUMP: finished in less than a second
  DUMP: Date of this level 0 dump: Tue Nov 16 13:02:35 2010
  DUMP: Date this dump completed:  Tue Nov 16 13:02:36 2010
  DUMP: Average transfer rate: 0 kB/s
  DUMP: DUMP IS DONE
[12:59] cmd#:696
root@Etalon: ~# dump -0 -f root.dmp -L "Etalon.root" /
...

2. Грузимся с live-cd. Я использовал тот же CentOS live-cd.

3. Далее нам нужно разбить диски в сервере на разделы и настроить LVM. Сделать это можно с помощью утилит fdisk/cfdisk/lvm. Хотя тем, кому лень возиться с этими утилитами из консоли, могу посоветовать самый наверное простой способ — это воспользоваться графическим инсталлером с установочного диска CentOS. Там после пары вопросов про язык и раскладку наступает шаг разбиения диска, все красиво, быстро и удобно. Собственно я так и сделал :-[ Разбил диск на 2 раздела: 100 mb под /boot и остальное под управлением LVM с двумя разделами для свапа и /. В новом сервере диск в системе видится как /dev/cciss/c0d0 с двумя разделами p1 и p2.

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

[13:19] cmd#:700
root@Etalon: ~# mount.cifs //storage/Backups /mnt/storage -o user=kostik ip=192.168.24.111
Password:

5. Теперь надо накатить дампы на новенькие разделы. Но тут есть подстава в виде того, что в лив-сиди нет этих утилит. Надо их поставить. Берем с установочного диска CentOS 2 rpm’ки: rmt-0.4b41-4.el5.x86_64.rpm & dump-0.4b41-4.el5.x86_64.rpm. rmt нужна как зависимость для dump. Ставим их:

root@Etalon: ~# rpm -ivh rmt-0.4b41-4.el5.x86_64.rpm
root@Etalon: ~# rpm -ivh dump-0.4b41-4.el5.x86_64.rpm

Далее монтируем новые разделы, если они еще не смонтированы

[root@livecd lvm]# mount /dev/mapper/VolGroupRoot-LogVolRoot VolGroupRoot-LogVolRoot
[root@livecd lvm]# mount /dev/cciss/c0d0p1 boot/

Затем переходим в mount-point каждого раздела и накатываем dump:

[root@livecd lvm]# cd VolGroupRoot-LogVolRoot
[root@livecd lvm]# restore -rf /mnt/storage/root.dmp
[root@livecd lvm]# cd ../boot/
[root@livecd lvm]# restore -rf /mnt/storage/boot.dmp

6. Теперь нам надо поправить некоторые системные конфиги.
Поскольку диск мы разбили точно так же как и эталон, и LVM’овские тома и группы назвали так же, то fstab особо править не надо. Едиственное, что поскольку /boot у нас монтируется, используя метку а не путь к устройству, то надо убедиться, что у нашего boot’ового раздела такая же метка. Проверить и поставить метку можно с помощью e2label. Я, когда форматировал разделы, забыл указать метку и у меня ее не было, так что пришлось выставить:

[root@livecd lvm]# e2label /dev/cciss/c0d0p1

[root@livecd lvm]# e2label /dev/cciss/c0d0p1 "/boot"
[root@livecd lvm]# e2label /dev/cciss/c0d0p1
/boot

Теперь надо поправить grub.

root@Etalon: ~# cat /boot/grub/device.map
# this device map was generated by anaconda
(hd0)     /dev/sda

надо поменять на

root@Etalon: ~# cat /boot/grub/device.map
# this device map was generated by anaconda
(hd0)     /dev/cciss/c0d0

7. Теперь нам надо пересобрать RAM-диск, инициализируемый загрузчиком, то есть initrd. Приведу кусок мана:
Специальный файл /dev/initrd — это блочное устройство только для чтения. Устройство /dev/initrd — это диск, расположенный в оперативной памяти, который инициализируется (т.е. загружается) загрузчиком до запуска ядра. Затем ядро может использовать содержимое блочного устройства /dev/initrd для двухфазовой загрузки системы.
Во время первой фазы ядро запускает и монтирует начальную корневую файловую систему из содержимого /dev/initrd (например, RAM-диска, инициализируемого загрузчиком). Во время второй фазы из начального содержимого корневого устройства загружаются дополнительные драйвера или другие модули. После загрузки дополнительных модулей с другого устройства монтируется новая корневая файловая система (т.е., нормальная корневая файловая система).

Для этого нам надо, во-первых, перемонтировать наш boot в boot, который находится в корне нашего подмонтированного рутового раздела, а не просто куда-нибудь. Это важно. Затем также смонтировать системные fs в дерево нашего образа, затем чрутнуться в наш образ и переинициализировать initrd:

[root@livecd lvm]# umount boot/
[root@livecd lvm]# cd VolGroupRoot-LogVolRoot
[root@livecd VolGroupRoot-LogVolRoot]# mount /dev/cciss/c0d0p1 boot/
[root@livecd VolGroupRoot-LogVolRoot]# mount -t proc proc proc/
[root@livecd VolGroupRoot-LogVolRoot]# mount -t sysfs sys sys/
[root@livecd VolGroupRoot-LogVolRoot]# mount -o bind /dev dev/
[root@livecd VolGroupRoot-LogVolRoot]# chroot ./
[root@livecd /]# mkinitrd -v -f --force-ide-probe --force-scsi-probe --force-raid-probe --force-lvm-probe /boot/initrd-2.6.18-194.el5.img 2.6.18-194.el5
Creating initramfs
Looking for deps of module ehci-hcd
Looking for deps of module ohci-hcd
Looking for deps of module uhci-hcd
Looking for deps of module ext3: jbd
Looking for deps of module jbd
Looking for driver for device cciss/c0d0p2
Looking for deps of module megaraid_sas: scsi_mod
Looking for deps of module scsi_mod
Looking for deps of module sd_mod: scsi_mod
Looking for deps of module ata_piix: scsi_mod libata
Looking for deps of module libata: scsi_mod
Looking for deps of module qla2xxx: scsi_mod scsi_transport_fc
Looking for deps of module scsi_transport_fc: scsi_mod
Looking for deps of module ide-disk
Looking for deps of module dm-mod
Looking for deps of module dm-mirror: dm-mod dm-log
Looking for deps of module dm-log: dm-mod
Looking for deps of module dm-zero: dm-mod
Looking for deps of module dm-snapshot: dm-mod
Looking for deps of module dm-mem-cache
Looking for deps of module dm-region_hash: dm-mod dm-log
Looking for deps of module dm-message
Looking for deps of module dm-raid45: dm-message dm-mod dm-mem-cache dm-log dm-region_hash
Looking for deps of module cciss: scsi_mod
Using modules:  /lib/modules/2.6.18-194.el5/kernel/drivers/usb/host/ehci-hcd.ko /lib/modules/2.6.18-194.el5/kernel/drivers/usb/host/ohci-hcd.ko /lib/modules/2.6.18-194.el5/kernel/drivers/usb/host/uhci-hcd.ko /lib/modules/2.6.18-194.el5/kernel/fs/jbd/jbd.ko /lib/modules/2.6.18-194.el5/kernel/fs/ext3/ext3.ko /lib/modules/2.6.18-194.el5/kernel/drivers/scsi/scsi_mod.ko /lib/modules/2.6.18-194.el5/kernel/drivers/scsi/sd_mod.ko /lib/modules/2.6.18-194.el5/kernel/drivers/scsi/megaraid/megaraid_sas.ko /lib/modules/2.6.18-194.el5/kernel/drivers/ata/libata.ko /lib/modules/2.6.18-194.el5/kernel/drivers/ata/ata_piix.ko /lib/modules/2.6.18-194.el5/kernel/drivers/scsi/scsi_transport_fc.ko /lib/modules/2.6.18-194.el5/kernel/drivers/scsi/qla2xxx/qla2xxx.ko /lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-mod.ko /lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-log.ko /lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-mirror.ko /lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-zero.ko /lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-snapshot.ko /lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-mem-cache.ko /lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-region_hash.ko /lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-message.ko /lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-raid45.ko /lib/modules/2.6.18-194.el5/kernel/drivers/block/cciss.ko
/sbin/nash -> /tmp/initrd.dQ6087/bin/nash
/sbin/insmod.static -> /tmp/initrd.dQ6087/bin/insmod
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/usb/host/ehci-hcd.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/ehci-hcd.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/usb/host/ohci-hcd.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/ohci-hcd.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/usb/host/uhci-hcd.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/uhci-hcd.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/fs/jbd/jbd.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/jbd.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/fs/ext3/ext3.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/ext3.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/scsi/scsi_mod.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/scsi_mod.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/scsi/sd_mod.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/sd_mod.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/scsi/megaraid/megaraid_sas.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/megaraid_sas.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/ata/libata.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/libata.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/ata/ata_piix.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/ata_piix.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/scsi/scsi_transport_fc.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/scsi_transport_fc.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/scsi/qla2xxx/qla2xxx.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/qla2xxx.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-mod.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/dm-mod.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-log.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/dm-log.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-mirror.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/dm-mirror.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-zero.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/dm-zero.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-snapshot.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/dm-snapshot.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-mem-cache.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/dm-mem-cache.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-region_hash.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/dm-region_hash.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-message.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/dm-message.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/md/dm-raid45.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/dm-raid45.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.18-194.el5/kernel/drivers/block/cciss.ko' [elf64-x86-64] to `/tmp/initrd.dQ6087/lib/cciss.ko' [elf64-x86-64]
/sbin/lvm.static -> /tmp/initrd.dQ6087/bin/lvm
/sbin/dmraid.static -> /tmp/initrd.dQ6087/bin/dmraid
/sbin/kpartx.static -> /tmp/initrd.dQ6087/bin/kpartx
Adding module ehci-hcd
Adding module ohci-hcd
Adding module uhci-hcd
Adding module jbd
Adding module ext3
Adding module scsi_mod
Adding module sd_mod
Adding module megaraid_sas
Adding module libata
Adding module ata_piix
Adding module scsi_transport_fc
Adding module qla2xxx
Adding module dm-mod
Adding module dm-log
Adding module dm-mirror
Adding module dm-zero
Adding module dm-snapshot
Adding module dm-mem-cache
Adding module dm-region_hash
Adding module dm-message
Adding module dm-raid45
Adding module cciss
[root@livecd /]#
[root@livecd /]# exit

Если вы не подмонтируете специальные файловые системы /proc /sys /dev — то mkinitrd не сможет увидеть ваше железо и соответственно не добавит нужные драйвера в образ. Вот что может быть в этом случае:

[root@livecd /]# mkinitrd -v -f /boot/initrd-2.6.18-194.el5.img 2.6.18-194.el5
Creating initramfs
Looking for deps of module ehci-hcd
Looking for deps of module ohci-hcd
Looking for deps of module uhci-hcd
Looking for deps of module ext3: jbd
Looking for deps of module jbd
Looking for driver for device VolGroupRoot/LogVolRoot
error opening /sys/block: No such file or directory
Looking for driver for device VolGroupRoot/LogVolSwap
error opening /sys/block: No such file or directory
Looking for deps of module megaraid_sas: scsi_mod
Looking for deps of module scsi_mod
Looking for deps of module sd_mod: scsi_mod
Looking for deps of module ata_piix: scsi_mod libata 
...

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

[root@livecd /]# mkinitrd -v -f --with=cciss /boot/initrd-2.6.18-194.el5.img 2.6.18-194.el5

Даже в этом случае при попытке загрузить ОС появляется kernel panic

8. Теперь дело за малым, это проинсталлить grub в MBR, чтобы он указывал на правильный раздел /boot. Поскольку диск у нас в системе один, и бутовый раздел на нем первый, то делаем следующее:

[root@livecd /]# grub
grub> root (hd0,0)
grub> setup (hd0)
grub> quit

Если grub будет не будет прописан в MBR, то сервер просто скажет «Non-System Disk», а если grub будет указывать на неверный раздел, то не сможет загрузиться ядро.

9. Ну и самое интересное — отправляем сервер на ребут и верим в счастье 🙂

Как же этот раздел обычно называется… АА! Список литературы!

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

В общем и целом, как оказалось, ничего кроме манов не требуется.

P.S. Если есть какие-то неточности/замечания или может быть даже пожелания — Велкам!