Решился написать эту заметку, надеясь на то, что, возможно, кому-нибудь это позволит сэкономить час другой времени. Итак.
Дано:
- Сервер в датацентре с двумя SATA дисками (аппаратного RAID-контроллера нет).
- На сервере установлена ОС:
Код: Выделить всё
# uname -a FreeBSD server.domain.tld 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r250917
- С geom зеркалом, созданным со следующими параметрами:
Код: Выделить всё
# gmirror label -v -b round-robin gm0 ada0 ada1
- Поверх gmirror создан пул ZFS.
Код: Выделить всё
# gmirror status
Name Status Components
mirror/gm0 DEGRADED ada1 (ACTIVE)
ada0 (SYNCHRONIZING, 3%)
Код: Выделить всё
[root@rescue ~]# zpool status -v
pool: server-pool
state: ONLINE
status: One or more devices has experienced an error resulting in data
corruption. Applications may be affected.
action: Restore the file in question if possible. Otherwise restore the
entire pool from backup.
see: http://illumos.org/msg/ZFS-8000-8A
scan: scrub repaired 0 in 3h2m with 2 errors on Tue May 20 19:11:57 2014
config:
NAME STATE READ WRITE CKSUM
server-pool ONLINE 0 0 6
ada0p3 ONLINE 0 0 24 block size: 512B configured, 4096B native
errors: Permanent errors have been detected in the following files:
<metadata>:<0x1d>
server-pool:<0x786>
Код: Выделить всё
# zfs scrub
# zpool clear server-pool
Решение.
- "Разбираем" gmirror массив, удалив из массива gm0 диск ada0 - получаем два диска с ОС и данными. Система будет временно работать на одном диске ada1.
- Очищаем таблицу разделов (на всякий случай) и создаем точную копию таблицы разделов с диска ada1 на диске ada0:
Код: Выделить всё
# gpart destroy -F ada0 # gpart backup ada1 > ada1.gpart # gpart restore ada0 < ada1.gpart
- Создаем на диске ada0 ZFS пул с другим именем:
Код: Выделить всё
# zpool create zpool2 /dev/ada0p3
- Создаем нужные ZFS в новом пуле.
- Переходим к процессу переноса данных с одного пула на другой пул - для этого оптимально использовать снапшоты ZFS и отправку/получение снапшотов ZFS. Тестируем:
Тестовый перенос данных успешно завершен.
Код: Выделить всё
## Создаем снапшот: # zfs snapshot server-pool@backup ## Проверяем создался ли снапшот? # zfs list -t snapshot NAME USED AVAIL REFER MOUNTPOINT server-pool@backup 0 - 5,66G - ## Пробуем передать снапшот: # zfs send server-pool@backup | zfs recv zpool2 cannot receive new filesystem stream: destination 'zpool2' exists must specify -F to overwrite it warning: cannot send 'server-pool@backup': Broken pipe ## Следуя рекомендациям, отправляем снапшот ещё раз: # zfs send server-pool@backup | zfs recv -F zpool2
- Так как на сервере используется несколько "разделов" ZFS, для автоматизации написан скрипт:
В датацентре, где находится сервер, имеется возможность запустить rescue-систему (то есть FreeBSD, загружаемую по сети). Я решил воспользоваться ей для того, чтобы избежать изменения данных во время копирования.
Код: Выделить всё
#!/bin/sh pool_send="server-pool" pool_receive="zpool2" for i in `zfs list | grep $pool_send | awk '{print $1};'` do zfs snapshot $i@backup zfs send $i@bacup | zfs receive -F `echo $i | sed 's/server-pool/zpool2/g' | sed 's/@backup//g'` done
- После того, как скрипт отработал (в моем случае это заняло около 5-ти часов), проверяем статус нового пула (нижеследующие действия производились из rescue-системы):
Ошибок в новом пуле уже нет. Корректируем загрузку (на диске ada0 в новом пуле):
Код: Выделить всё
# zpool status pool: zpool2 state: ONLINE scan: none requested config: NAME STATE READ WRITE CKSUM zpoo2l ONLINE 0 0 0 ada0 ONLINE 0 0 0 errors: No known data errors
Исправляем точку монтирования swap'а:Код: Выделить всё
# cat /boot/loader.conf | grep -i zfs zfs_load="YES" vfs.root.mountfrom="zfs:zpool2"
С диском ada0 закончили. Приступаем к подготовке диска ada1 и созданию RAID-Z (по моему субъективному мнению, данная технология более надежна по сравнению с gmirror. Хотя не исключено, что я просто не умею "нормально готовить" geom mirror):Код: Выделить всё
# cat /etc/fstab | grep -i swap /dev/ada0p2 none swap sw 0 0
Подключаем к рабочему ZFS пулу еще один диск (ada1, ada0 уже в пуле присутствует):Код: Выделить всё
## Удаляем таблицу разделов на диске ada0 и создаем новую (использую ранее сохраненный бэкап таблицы разделов): # gpart destroy -F ada1 # gpart restore ada1 < ada1.gpart
Следуя рекомендациям, записываем код загрузчика на оба диска:Код: Выделить всё
# zpool attach zpool2 ada0 ada1 invalid vdev specification use '-f' to override the following errors: /dev/ada1 is part of potentially active pool 'server-pool' ## Учитывая "ругань" команды zpool, выполняем еще раз: # zpool attach -f zpool2 ada0 ada1 Make sure to wait until resilver is done before rebooting. If you boot from pool 'zpool2', you may need to update boot code on newly attached disk 'ada1'. Assuming you use GPT partitioning and 'da0' is your new boot disk you may use the following command: gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0
Проверяем состояние нового пула:Код: Выделить всё
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0 # gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1
Размонтируем все ZFS и исправляем точки монтирования ZFS (в моем случае это выглядело так):Код: Выделить всё
# zpool status -v pool: zpool2 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 Wed Dec 17 21:24:53 2014 146M scanned out of 2,16T at 1/s, (scan is slow, no estimated time) 146M resilvered, 0,01% done config: NAME STATE READ WRITE CKSUM zpool2 ONLINE 0 0 0 mirror-0 ONLINE 0 0 0 ada0 ONLINE 0 0 0 ada1 ONLINE 0 0 0 (resilvering) errors: No known data errors
Код: Выделить всё
# zfs unmount zpool2 # zfs set mountpoint=/ zpool2 # zfs set mountpoint=/tmp zpool2/tmp # zfs set mountpoint=/usr/home zpool2/usr/home # zfs set mountpoint=/usr/ports zpool2/usr/ports # zfs set mountpoint=/usr/src zpool2/usr/src # zfs set mountpoint=/var zpool2/var # zfs set mountpoint=/var/crash zpool2/var/crash # zfs set mountpoint=/var/log zpool2/var/log # zfs set mountpoint=/var/mail zpool2/var/mail # zfs set mountpoint=/var/tmp zpool2/var/tmp
- Перезагружаем сервер, загружаемся с диска: система загружается нормально. Автоматически стартует resilvering ZFS пула (система при этом работает нормально). После завершения процесса имеем работоспособный пул ZFS без ошибок и вполне себе работоспособную ОС:
Код: Выделить всё
# zpool status -v pool: zpool2 state: ONLINE scan: resilvered 2,16T in 11h13m with 0 errors on Thu Dec 18 08:38:06 2014 config: NAME STATE READ WRITE CKSUM zpool2 ONLINE 0 0 0 mirror-0 ONLINE 0 0 0 ada0 ONLINE 0 0 0 ada1 ONLINE 0 0 0 errors: No known data errors