Мы — долго запрягаем, быстро ездим, и сильно тормозим.
www.lissyara.su —> статьи —> FreeBSD —> настройка —> backup/restore & ZFS

Процедуры резервного копирования и восстановления системы с ZFS

Автор: egor.


Для компьютера под управлением OS FreeBSD 9.1 RELEASE


Предисловие.


В предыдущей статье, dump/restore, я рассказывал каким образом реализовано полное резервное копирование "классической" FreeBSD, установленной на "родную" файловую систему. Теперь я расскажу, как я решал схожую задачу после установки системы на ZFS.

Сама тема установки системы на ZFS довольно подробно освещена. Я пользовался следующими материалами:

  • Руководство по администрированию файловых систем ZFS Solaris (pdf). Толстая книга, распечатал, долго читал. Что то понял, что то не очень, т.к. с Solaris не сталкивался.
  • Установка FreeBSD 9 c ZFS - Основа.
  • Установка FreeBSD 9.0 RELEASE на ZFS - Скрипт.
  • Installing FreeBSD Root on ZFS using GPT.
  • 20.2. Файловая система ZFS.
  • Установка FreeBSD с использованием ZFS в качестве основной.
  • Создание "правильной" геометрии диска.

    В результате чтения, экспериментов, проб и ошибок "родился" скрипт bsdinstall.sh, который привожу без комментариев, и только потому, что на нем основано восстановление и на него идут ссылки.

    Используемое "железо".



    оборудование
    характеристика
    CPU DualCore Intel Celeron G540; 2500 MHz (25 x 100)
    MB Asus P8H61-M LX (3 PCI-E x1; 1 PCI-E x16; 2 DDR3 DIMM; Audio; Video; Gigabit LAN) (Intel Cougar Point H61; Intel Sandy Bridge)
    VIDEO Intel(R) HD Graphics 2500
    RAM 2G (DDR3-1333 DDR3 SDRAM Kingston 9905474-012.A00LF)
    HDD WDC WD5000AAKX-001CA0 (500 Гб; SATA II)
    LAN Realtek PCIe GBE Family Controller (Onboard) (Realtek RTL8111E chip)

    Подготовка загрузочного носителя.


    Для установки системы и для восстановления использовалась флешка (на самом деле картридер и карта microSD). На Windows XP делаем загрузочную флешку из  img образа FreeBSD-9.1-RELEASE-amd64-memstick.img при помощи dd for windows.
    Вставляем флешку в компьютер, определяем диск с флешкой командой:
    >dd --list
    

    У меня это был диск 2:
    ...
    \\?\Device\Harddisk2\Partition0
    link to \\?\Device\Harddisk2\DR74
    Removable media other than floppy. Block size = 512
    size is 15808331776 bytes
    ...

    Выполняем, соответственно, команду создания флешки, указав нужный диск:
    >dd if=FreeBSD-9.1-RELEASE-amd64-memstick.img \ 
      of=\\?\Device\Harddisk2\Partition0 bs=2M --progress
                            ^
    

    Естественно, все это можно сделать той же dd из под любой *nix системы.
    Естественно, можно пойти по классическому пути, затянув ISO образ и закатав его на DVD (или даже CD) матрицу и использовать этот диск при установке и/или восстановлении системы.

    Процедура резервного копирования.


    По мотивам: Full system backups for FreeBSD systems using ZFS и dump/restore.

    Обеспечиваем доступ к ftp серверу. В моем случае по адресу 192.168.1.19 на сервере под управлением MS Windows 2003 R2 создан в IIS узел ftp на порту 8022 с полным доступом для учетной записи proxy3 c паролем proxy3 и резервом дискового пространства порядка 50G.

    Создаем на резервируемой системе каталог, например "\usr\home\teg\CONFIG\BACKUP\" и в нем файлы "backup_restore_910.txt" (с этим руководством по восстановлению) и выполняемый файл скрипта "backup.sh".
    #!/bin/sh
    # резервное копирование
    
    #имя пула
    poolname='tank'
    #дата и время
    DATE=`date +%Y.%m.%d_%H%M`
    
    #Делаем рекурсивный снапшот пула с корня 
    zfs snapshot -r ${poolname}@${DATE}
    
    #рисуем результат
    zfs list -t snapshot
    
    ftpkeys="-i -a -A -P 8022"
    usr="proxy3"
    pass=${usr}
    ftpsrv="192.168.1.19"
    
    #отправляем руководство по восстановлению на сервер
    cp backup_restore_910.txt fb910.${poolname}.${DATE}.backup.txt
    ftp -i -A -P 8022 -u ftp://${usr}:${pass}@${ftpsrv}/ \
     fb910.${poolname}.${DATE}.backup.txt
    rm fb910.${poolname}.${DATE}.backup.txt
    
    #отправляем загрузчик и загрузочную область на сервер
    cp /boot/pmbr fb910.${poolname}.${DATE}.pmbr
    cp /boot/gptzfsboot fb910.${poolname}.${DATE}.gptzfsboot
    ftp -i -A -P 8022 -u ftp://${usr}:${pass}@${ftpsrv}/ \ 
     fb910.${poolname}.${DATE}.pmbr
    ftp -i -A -P 8022 -u ftp://${usr}:${pass}@${ftpsrv}/ \ 
     fb910.${poolname}.${DATE}.gptzfsboot
    rm fb910.${poolname}.${DATE}.pmbr
    rm fb910.${poolname}.${DATE}.gptzfsboot
    
    #Вариант полный, с запаковкой, медленный
    #1160334296 bytes sent in 18:26 (1.00 MiB/s)
    #Тут узкое место по времени - процесс сжатия,
    #можно попробовать сжимать с меньшей эффективностью, 
    #но не вижу пока необходимости.
    zfs send -R ${poolname}@${DATE} | gzip -9 | ftp ${ftpkeys} -u \ 
     ftp://${usr}:${pass}@${ftpsrv}/fb910.${poolname}.${DATE}.img.gz -
    echo "------- end send snapshot '${poolname}.${DATE}', sleep 4c ----" 
    
    #Вариант полный, без запаковки, быстрый
    #4814869016 bytes sent in 01:07 (68.14 MiB/s)
    #zfs send -R ${poolname}@${DATE} | ftp ${ftpkeys} -u \
    # ftp://${usr}:${pass}@${ftpsrv}/fb910.${poolname}.${DATE}.img -
    #echo "------- end send snapshot '${poolname}.${DATE}', sleep 4c ----" 
    
    sleep 4
    echo ' '
    
    #удаляем снапшот
    zfs destroy -r ${poolname}@${DATE}
    

    Запуск скрипта позволяет создать файлы резервной копии сразу на другом компьютере.
    Естественно, никто не запрещает Вам выполнять резервное копирование не на ftp, а, на другой жесткий диск, или, скажем, на флешку.

    Процедура тестового восстановления.


    По тем же мотивам: Full system backups for FreeBSD systems using ZFS и dump/restore.

    1 Делаем флешку для загрузки.

    2 Выполняем бакап системы. Получаем файлы:
    ftp://proxy3@192.168.1.19:8022/fb910.tank.2012.11.01_1735.img.gz
    ftp://proxy3@192.168.1.19:8022/fb910.tank.2012.11.01_1735.pmbr
    ftp://proxy3@192.168.1.19:8022/fb910.tank.2012.11.01_1735.gptzfsboot
    

    3 Гасим восстанавливаемый компьютер:
    % sudo poweroff
    

    4 Берем другой компьютер, поддерживающий 64 битные инструкции (amd64). У меня была машина в следующей конфигурации:
    оборудование
    характеристика
    CPU DualCore Intel Pentium E2180; 2017 MHz (10 x 202)
    MB MSI 945GCM7 (MS-7507) (2 PCI; 1 PCI-E x1; 1 PCI-E x16; 2 DDR2 DIMM; Audio; Videol; LAN) (Intel Lakeport-G i945GC)
    VIDEO Intel(R) 82945G Express Chipset Family (128 Мб) Intel GMA 950
    RAM 1G (2x512 Мб DDR2-667 DDR2 SDRAM)
    HDD ST330013A (30 Гб; 7200 RPM; Ultra-ATA/100)
    LAN Realtek RTL8168C(P)/8111C(P) PCI-E Gigabit Ethernet NIC

    Небольшое лирическое отступление или как избежать ловушек.
    Конфигурация оригинального компьютера, на котором я разворачивал систему,
    описана выше, в разделе Используемое "железо".
    При установке системы сетевой контроллер с чипом "Realtek RTL8111E" не корректно работал, хоть и идентифицировался системой. Помогла замена драйвера на "родной" от Realtek для Freebsd. На сайте Realtek, точнее HOME > Downloads > Communications Network ICs > Network Interface Controllers > 10/100/1000M Gigabit Ethernet > PCI Express > Software забрал архив для "FreeBSD 7.x and 8.0 1.81 2012/11/16 56k". Установку провел в соответствии с рекомендациями файла "rtl_bsd_drv\Readme.txt" из этого архива по "Методу 2" с последующим переходом к "Методу 1".
    После замены драйвера сеть заработала. Мне нужны были два разных сетевых интерфейса в системе. Сетевых карт разных у меня есть в запасе, но ни одной для шины PCI-E, а других интерфейсов в бюджетной материнской плате "Asus P8H61-M LX" не предусмотрено. Поэтому я прикупил сетевую карту с шиной PCI-E "TP-Link TG-3468" на чипе "Realtek RTL8168E". Она обнаружилась в системе как устройство re и была подхвачена и корректно работала, и только благодаря обновленному драйверу.
    Теперь представьте ситуацию, на оригинальном компьютере "умер" HDD. Берем другой HDD, подключаем в тот же компьютер, и, если выполнять восстановление через сеть, то, естественно, ничего не получиться. Потому что грузимся мы с флешки, а там драйвер от Freebsd, он не поймет ни первую ни вторю сетевую. Поэтому - либо вручную подменять драйвер (честно говоря я пока не заню как это корректно сделать), либо восстанавливаться не по сети а с флешки или другого носителя (HDD), Соответственно, необходимо внести изменения в скрипт "bsdrestor.sh". Еще как вариант, найти внешнюю сетевую карту PCI-E, которая поддерживается "голой" системой Freebsd c флешки.

    5 Грузимся с флешки. Заходим в "Shell", смотрим, если ли на новом винте разделы:
    # gpart show
    

    Если есть, то все разделы удаляем, например на ada0:
    # gpart destroy -F ada0
    

    Если диск ранее использовался, то, как пишут, имеет смысл затереть несколько первых мегабайт диска, например:
    # dd if=/dev/zero of=/dev/ada0 bs=1M count=2048
    

    6 Подготавливаем скрипт формирования файловой системы после бакапа на другом компьютере. Можно сделать и на восстанавливаемом. Готовый вариант скрипта в файле bsdrestor.sh. Этот файл необходимо отредактировать, в начале, в части переменных. Фактически это адаптация скрипта разметки диска под ZFS и установки системы. Этот скрипт обрезан до строки
    zfs set checksum=fletcher4 $tank"
    

    Вместо группы команд "zfs create ..." введены команды настройки сети и восстановления пула из архива. Расширены возможности настройки, в начале, в заголовке. Наиболее важные:
    Имя устройства:
    dev=ada0
    

    Строка даты и времени резервной копии, необходима для определения имен файлов для восстановления:
    backup_f="2012.11.01_1735"
    

    Имя сетевого интерфейса:
    if_lan=re0
    

    И еще другие, достаточно, на мой взгляд, прокомментированные параметры-переменные.
    По окончании редактирования необходимо скопировать подготовленный скрипт на ДРУГУЮ флешку, в корень.
    Привожу весь тест скрипта. А вот для работы файл bsdrestor.sh лучше затянуть, т.к. эта "экранная" версия, она снабжена переводами строк, для читабельности.
    #!/bin/sh
    # Переменные
    # Перед выполнением проверить и отредактировать!
    
    # Имя диска (устройства)
    dev=ada0
    
    # Имя создаваемого пула
    tank=tank
    
    # имя сетевого интерфейса
    if_lan=re0
    # адрес хоста на момент восстановления
    ip_host="192.168.1.79"
    # адрес шлюза
    ip_gw="192.168.1.1"
    # адрес ftp сервера c файлами восстановления
    ip_ftp="192.168.1.19"
    # порт ftp сервера c файлами восстановления
    port_ftp="8022"
    # логин и пароль ftp сервера c файлами восстановления
    usr="proxy3"
    pass=${usr}
    
    # Строка даты и времени резервной копии
    backup_data="2012.11.01_1735"
    
    # ================= Расcчитываемыt занчения, для, справки =====================
    # имя файла-архива с запакованным пулом
    backup_f="fb910.tank.${backup_data}.img.gz"
    # имя резервных копий файлов загрузчиков
    backup_gptzfsboot="fb910.tank.${backup_data}.gptzfsboot"
    backup_pmbr="fb910.tank.${backup_data}.pmbr"
    
    ### =============== Разбивка диска, для, справки ==============================
    # Два примера рачета длинны 3-го оновного раздела, ZFS
    # Cам расчет проводится автоматически самим скриптом
    ###
    
    # скрипт делает такую разметку:
    #        34 - 6            - free -
    #        40 - 1024      1  freebsd-boot boot0
    #      1064 - 984          - free -
    #      2048 - 8388608   2  freebsd-swap
    #   8390656 - xxxxxxxxx 3  freebsd-zfs
    # xxxxxxxxx - xx           - free -
    
    # Пример 1
    # 80G винт, блоков 156299308, начиная с 34.
    # т.е. всего 156299308+34=156299342 блоков
    # на раздел freebsd-zfs можно выделить
    # 156299342-8390656=147908686 блоков,
    # 147908686/8=18488585.75, т.е. 6 блоков в конце лишние,
    # итого длинна "основного", 3-го, раздела,
    # c учетом выравнивания по 4К (8 блоков)
    # составит 147908686-6=147908680 блоков
    #blk_long=147908680
    
    # Пример 2
    # 500G винт, блоков 976770988, начиная с 34.
    # т.е. всего 976770988+34=976771022 блоков
    # на раздел freebsd-zfs можно выделить
    # 976771022-8390656=968380366 блоков,
    # 968380366/8=121047545.75, т.е. 6 блоков в конце лишние,
    # итого длинна "основного", 3-го, раздела,
    # c учетом выравнивания по 4К (8 блоков)
    # составит 968380366-6=968380360 блоков
    #blk_long=968380360
    
    # =========== Тело скрипта ===================================================
    echo "script: Create GPT, add partitions..."
    gpart create -s gpt $dev
    
    echo "script: add freebsd-boot partition boot0"
    gpart add -b 40 -s 1024 -t freebsd-boot -l boot0 ${dev}
    
    echo "script: add freebsd-swap partition swap0"
    gpart add -b 2048 -s 4G -t freebsd-swap -l swap0 ${dev}
    
    
    ####
    # Рассчет длинны 3 го, основного раздела, ZFS
    ####
    
    # Начальный блок и длинна в блоках всего устройства (диска)
    blk_begin=`gpart show ${dev} | grep '=>' | awk '{a = $2; print a}'`
    echo "script: blk_begin=${blk_begin}"
    blk_end=`gpart show ${dev} | grep '=>' | awk '{a = $3; print a}'`
    echo "script: blk_end=${blk_end}"
    
    # Начальный блок и длинна в блоках раздела (freebsd-swap)
    blk_swop_begin=`gpart show ${dev} | grep 'freebsd-swap' | \
     awk '{a = $1; print a}'`
    echo "script: blk_swop_begin=${blk_swop_begin}"
    blk_swop_end=`gpart show ${dev} | grep 'freebsd-swap' | \
     awk '{a = $2; print a}'`
    echo "script: blk_swop_end=${blk_swop_end}"
    
    # Начальный блок раздела ZFS
    blk_zfs_begin=$((${blk_swop_begin} + ${blk_swop_end}))
    echo "script: blk_zfs_begin=${blk_zfs_begin}"
    
    # Искомая длинна в блоках раздела ZFS с учетом кратности 8 блокам (4K)
    blk_long=$(( (((${blk_begin}+${blk_end})-${blk_zfs_begin})/8)*8 ))
    echo "script: blk_long=${blk_long}"
    
    echo "script: add freebsd-zfs partition data0, long is ${blk_long} blocks"
    gpart add -s ${blk_long} -t freebsd-zfs -l data0 ${dev}
    
    echo " "
    echo "script: GPT on $dev created, partitions added."
    echo " "
    
    sleep 5
    
    # Настраиваем сеть
    ifconfig ${if_lan} inet ${ip_host} netmask 255.255.255.0
    # Пропишем шлюз по умолчанию  команда route:
    route add default ${ip_gw}
    #Обязательно задержка, а то сразу сеть не поднимается!
    sleep 10
    
    #Загружаем с FTP серевера резервные копии загрузчиков
    # /boot/pmbr и /boot/gptzfsboot
    #ftp -i -A -P 8022 -o /tmp/gptzfsboot \
    # ftp://proxy3:proxy3@192.168.1.19/fb910.tank.2012.11.01_1735.gptzfsboot
    #ftp -i -A -P 8022 -o /tmp/pmbr \
    # ftp://proxy3:proxy3@192.168.1.19/fb910.tank.2012.11.01_1735.pmbr
    echo "script: Download backup boot records from ftp start...."
    ftp -i -A -P ${port_ftp} -o /tmp/gptzfsboot \
     ftp://${usr}:${pass}@${ip_ftp}/${backup_gptzfsboot}
    ftp -i -A -P ${port_ftp} -o /tmp/pmbr \
     ftp://${usr}:${pass}@${ip_ftp}/${backup_pmbr}
    
    # Записываем загрузчик в загрузочную область.
    # Корректно делать резервную копию /boot/pmbr и /boot/gptzfsboot
    # с последующим восстанавлением из нее, а не а не с того,
    # что подвернеться на загрузочной флешке.
    # Это нужно, чтобы загрузчик совпадал с загрузчиком исходной системы
    # Поэтому вместо
    #gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ${dev}
    # пишем:
    gpart bootcode -b /tmp/pmbr -p /tmp/gptzfsboot -i 1 ${dev}
    
    gpart show ${dev}
    sleep 3
    gpart show -l ${dev}
    sleep 5
    
    # Create ZFS pool
    echo "script: Create ZFS pool..."
    
    # Работаем над обеспечением геометрии с 4K
    gnop create -S 4096 /dev/gpt/data0
    zpool create -f -o altroot=/mnt -o cachefile=/var/tmp/zpool.cache ${tank} \
     /dev/gpt/data0.nop
    zpool export ${tank}
    gnop destroy /dev/gpt/data0.nop
    mkdir /tmp/${tank}
    zpool import -o altroot=/tmp/${tank} -o cachefile=/var/tmp/zpool.cache ${tank}
    
    # указываем, что пул загрузочный
    zpool set bootfs=${tank} ${tank}
    
    sleep 3
    
    # Create ZFS-filesystem
    echo "script: Create filesystem..."
    
    # ну зачем же? для быстродействия синтетического теста? За уши?
    #zfs set atime=off ${tank}
    
    # Включаем контрольные суммы посерьезнее.
    zfs set checksum=fletcher4 $tank
    
    ########################
    # А так получаем нужный нам поток:
    # ftp -i -A -P 8022 -o - \
    #  ftp://proxy3:proxy3@192.168.1.19/fb910.tank.2012.11.01_1735.img.gz
    # С распаковкой и передачей на вход zfs:
    # ftp -i -A -P 8022 -o - \
    #  ftp://proxy3:proxy3@192.168.1.19/fb910.tank.2012.11.01_1735.img.gz | \
    #  gzip -d -с | zfs receive -vF -d tank
    # итого с учетом переменных для возможности настройки:
    echo "script: Receive system from ftp start...."
    ftp -i -A -P ${port_ftp} -o - ftp://${usr}:${pass}@${ip_ftp}/${backup_f} | \
      gzip -d -c | zfs receive -vF -d ${tank}
    echo "script: Receive system from ftp finish"
    sleep 5
    
    # вообще это лишнее, но не мешает
    mkdir /tmp/root
    # что бы добраться до результирующего "/boot/zfs/zpool.cache"
    # приходится стучать в бубен
    zfs set mountpoint=/tmp/root ${tank}
    # то же лишнее
    cd /tmp
    zpool export ${tank}
    zpool import -o altroot=/tmp/${tank} -o cachefile=/var/tmp/zpool.cache ${tank}
    echo "script: Copy zpool cache..."
    # Копируем zpool.cache на своё место.
    # Только не пропустите этот шаг, были случаи )
    # Сей чудовый путь забавен, но логически верен. Проверено.
    # И запись выше "mkdir /tmp/root" вообще лишняя
    cp /var/tmp/zpool.cache /tmp/tank/tmp/root/boot/zfs/zpool.cache
    
    # отмотируем все это безобразие
    zfs unmount -af
    # вернем пул в корень
    zfs set mountpoint=legacy ${tank}
    
    echo "script: done!"
    echo "enter please command 'reboot'"
    

    7 Смотрим список устройств:
    # ls /dev
    

    Вставляем вторую флешку, со скриптом, в восстанавливаемый компьютер. По сообщениям на консоли определяем устройство флешки, уточняем раздел устройства для монтирования:
    # ls /dev
    

    Монтируем раздел флешки, например:
    # mount_msdosfs /dev/da1s1 /mnt
    

    У меня вторая флешка была размечена в NTFS, а не в FAT, поэтому вместо "mount_msdosfs" я писал "mount_ntfs". У вас может быть не "/dev/da1s1", а, например, "/dev/da0s1", если вы грузитесь не с флешки, а с DVD/CD. Или другое имя устройства. Копируем файл скрипта в "/tmp":
    # cp /mnt/bsdrestor.sh /tmp
    

    Обязательно отмонтируем флешку, т.к. скрипт использует точку монтирования "/mnt":
    # umount /mnt
    

    Выполняем скрипт:
    # sh /tmp/bsdrestor.sh
    

    Процедура восстановления, на гигабитной сети, бакапа почти голой системы, которая в запакованном виде "весит" 1.2G (в распакованном - 4.7G), длиться около 5 минут. По окончании работы скрипт просит ввести "Reboot". Но, перед перезагрузкой, следует внимательно просмотреть вывод сообщений на предмет ошибок. Если ничего не нашли, то перегружаемся, заходим под пользователем с группой whell или под root и смотрим файловую систему:
    % sudo zfs list -t all
    

    Видим - остался тот самый снапшот "tank@2012.11.01_1735", с которого мы делали бакап. Удаляем его за ненадобностью:
    % sudo zfs destroy -r tank@2012.11.01_1735
    

    Для проверки целостности системы я еще выполнил команду
    % sudo zpool scrub tank
    

    и через какое то время в ответ на команду
    % sudo zpool status
    

    получил "хороший" ответ:
      pool: tank
     state: ONLINE
      scan: scrub repaired 0 in 0h7m with 0 errors on Fri Dec 21 14:03:06 2012
    config:
    
            NAME         STATE     READ WRITE CKSUM
            tank         ONLINE       0     0     0
              gpt/data0  ONLINE       0     0     0
    
    errors: No known data errors
    

    Будем считать задачу выполненной.

    Окончание или история болезни.


  • 21.12.2012 - Вот и вышел новогодний подарок, релиз FreeBSD 9.1. На новом железе установил заново систему, как мне надо и проверил работу резервного копирования системы и восстановления на другом компьютере. Соотвественно отредактировал статью, добавив немного нового. Старую "историю болезни", котрая родилась на кривом железе, удалил, чтобы не мешалась.



    размещено: 2012-11-01,
    последнее обновление: 2012-12-22,
    автор: egor


    nero777, 2013-03-31 в 18:52:37

    Большое спасибо. Первое впечатление  - всё имхо доступно. С сегодняшнего дня заработали порты 9.1-Release. Так что статью я вовремя обнаружил.На ноуте поставил же 9.1-Release zfs Gnome2-i386.Бэкап сделал любимым tar. Попробую теперь по Вашей статье. tnx again 73!



  •  

      Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
      Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

    © lissyara 2006-10-24 08:47 MSK

    Время генерации страницы 0.0589 секунд
    Из них PHP: 46%; SQL: 54%; Число SQL-запросов: 76 шт.
    Исходный размер: 67568; Сжатая: 14751