PostHeaderIcon

Переход с UFS на ZFS в FreeBSD 9.3

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

1) текущая конфигурация:
# gmirror status
Name Status Components
mirror/gm0 COMPLETE ada0 (ACTIVE)
ada1 (ACTIVE)

# cat /etc/fstab
/dev/mirror/gm0a / ufs rw 1 1
/dev/mirror/gm0g /usr ufs rw 2 2
/dev/mirror/gm0e /tmp ufs rw 2 2
/dev/mirror/gm0f /home ufs rw 2 2
/dev/mirror/gm0d /var ufs rw 2 2
/dev/mirror/gm0b none swap sw 0 0

2) удаление одного диска из зеркала
# gmirror remove gm0 ada1

и зачистка таблицы разделов на нем
# dd if=/dev/zero of=/dev/ada1 bs=512 count=10

3) создание новой GTP-таблицы разделов
# gpart create -s gpt ada1

4) создание загрузочного раздела размеров 128КБ(хватит и 64КБ но, как говорится - запас карман не тянет) с размером сектора 4КБ(для оптимальной производительности дисковой подсистемы)
# gpart add -s 256 -a 4k -t freebsd-boot -l boot1 ada1

в большинстве мануалов указывают ключ -b для указания смещения,
но это уже не актуально, проверка:
# gpart show ada1
=> 34 976773101 ada1 GPT (465G)
34 6 - free - (3.0k)
40 256 1 freebsd-boot (128k)
296 976772839 - free - (465G)

видно что смещение раздела freebsd-boot 40 блоков, как и должно быть при использовании 4КБ секторов

5) создание swap-раздела 8ГБ - на сервере 4ГБ памяти, но возможно ее размер когда-нибудь будет увеличен до 8ГБ или даже до 16ГБ
т.к. swap-разделы зеркалироваться не будут, то создаются два swap(по одному на каждом диске) размером 8ГБ, что в итоге даст искомые 16ГБ необходимые для размещения дампа ядра при kernel panic в swap-раздел
# gpart add -s 8g -a 4k -t freebsd-swap -l swap1 ada1

6) все остальное пространство отдается под раздел с данными
# gpart add -a 4k -t freebsd-zfs -l disk1 ada1

7) установка загрузчика
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1

8) создание виртуальных дивайсов для правильной работы ZFS с 4КБ блоками
# gnop create -S 4096 /dev/gpt/disk1

начиная с FreeBSD 10.1 это уже не нужно и можно обойтись
# sysctl vfs.zfs.min_auto_ashift=12
не забыв прописать это в /etc/sysctl.conf

9) загружаем модуль ZFS
# kldload zfs

и создаем ZFS пул без ключа mirror, т.к. второго диска пока нет
# zpool create -o altroot=/mnt -O canmount=off -m none zroot /dev/gpt/disk1.nop

проверка:
# zpool status
pool: zroot
state: ONLINE

scan: none requested
config:

NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
gpt/disk1.nop ONLINE 0 0 0

errors: No known data errors

10) т.к. ФС создана избавляемся от виртуального диска:
отсоединяем пул
# zpool export zroot

удаляем устройство gnop
# gnop destroy /dev/gpt/disk1.nop

присоединяем пул
# zpool import zroot

проверяем смещение(если 12, то 2^12=4К. Если 9, то 2^9=512Б)
# zdb -C zroot | grep ashift
ashift: 12

в итоге:
# zpool status
pool: zroot
state: ONLINE
scan: none requested
config:

NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
gpt/disk1 ONLINE 0 0 0

errors: No known data errors

11) устанавливаем алгоритм проверки контрольных сумм fletcher4, в место дефолтного fletcher2
# zfs set checksum=fletcher4 zroot

и отключаем обновление времени доступа при каждом обращении к файлам, т.к. это серьезно снижает производительность
# zfs set atime=off zroot

12) создание ФС с учетом оптимального размера блока для разных БД:
# zfs create -o mountpoint=/mnt zroot/root
# zfs create -o mountpoint=/mnt/tmp -o setuid=off zroot/tmp
# zfs create -o mountpoint=/mnt/home -o setuid=off zroot/home
# zfs create -o mountpoint=/mnt/usr zroot/usr
# zfs create -o mountpoint=/mnt/usr/local zroot/usr/local
# zfs create -o recordsize=8k -o mountpoint=/mnt/usr/local/pgsql zroot/usr/local/pgsql
# zfs create -o mountpoint=/mnt/var zroot/var
# zfs create -o mountpoint=/mnt/var/db zroot/var/db
# zfs create -o recordsize=16k -o mountpoint=/mnt/var/db/mysql zroot/var/db/mysql

# chmod 1777 /mnt/tmp

13) Указываем корневую ФС
# zpool set bootfs=zroot/root zroot

и прописываем загрузку и монтирование ZFS
# echo 'zfs_enable="YES"' >> /etc/rc.conf
# echo 'zfs_load="YES"' >> /boot/loader.conf

14) подключение файла подкачки
# cat /mnt/etc/fstab
# Device Mountpoint FStype Options Dump Pass#
/dev/gpt/swap0 none swap sw 0 0
/dev/gpt/swap1 none swap sw 0 0

второго диска под swap еще нет, но это не критично

15) копирование данных на новый диск:
# cd / ; pax -p eme -X -rw . /mnt
# cd /var; pax -p eme -X -rw . /mnt/var
# cd /home; pax -p eme -X -rw . /mnt/home
# cd /usr; pax -p eme -X -rw . /mnt/usr

копировать /tmp смысла не имеет, т.к. там нет ничего нужного

16) перед загрузкой с нового ZFS диска выставляем правильные точки монтирования - это приведет к монтированию новых ZFS-ных разделов в текущую файловую систему, но проблем не будет т.к. все процессы остановлены(или мы загрузились в single mode), а в предыдущем пункте синхронизировали данные между двумя дисками

# zfs set mountpoint=/tmp zroot/tmp
# zfs set mountpoint=/home zroot/home

# zfs set mountpoint=/usr/local/pgsql zroot/usr/local/pgsql
# zfs set mountpoint=/usr/local zroot/usr/local
# zfs set mountpoint=/usr zroot/usr

# zfs set mountpoint=/var/db/mysql zroot/var/db/mysql
# zfs set mountpoint=/var/db zroot/var/db
# zfs set mountpoint=/var zroot/var

# zfs set mountpoint=/ zroot/root

# reboot

в настройках BIOS`а указываем загрузку с диска ada1 - обычно это второй по счету диск

17) после успешной перезагрузки с ZFS диска удаляем остатки UFS на первом диске(ada0)
# gmirror stop gm0
# gmirror destroy gm0

очистка таблицы разделов
# dd if=/dev/zero of=/dev/ada0 bs=512 count=10

отключение загрузки ненужного модуля GEOM-зеркала
# grep geom /boot/loader.conf
#geom_mirror_load=YES

создание новой таблицы разделов
# gpart create -s gpt ada0

создание разделов
# gpart add -s 256 -a 4k -t freebsd-boot -l boot0 ada0
# gpart add -s 8g -a 4k -t freebsd-swap -l swap0 ada0
# gpart add -a 4k -t freebsd-zfs -l disk0 ada0

прописывание загрузчика
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0

подключение нового диска к существующему пулу и создание зеркала
# zpool attach zroot /dev/gpt/disk1 /dev/gpt/disk0

проверка:
# zpool status
pool: zroot
state: ONLINE
status: One or more devices is currently being resilvered. The pool will
continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
scan: resilver in progress since Sun Mar 29 17:05:55 2015
9.03G scanned out of 23.0G at 72.8M/s, 0h3m to go
9.02G resilvered, 39.17% done
config:

NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/disk1 ONLINE 0 0 0
gpt/disk0 ONLINE 0 0 0 (resilvering)

errors: No known data errors