FreeBSDのRoot on ZFSシステムの別ディスクへの移行

2017年6月18日FreeBSD,Mac,NAS

FreeBSD10のRootで使っているプール(rpool)を別のディスクにコピーし、そのディスクから起動出来るようにしました。かなりハマったので、メモとして残しておきます。

FreeBSD11のLiveCDで立ち上げ、そのShell環境の中で作業します。

  1. USB起動イメージの作成
  2. LiveCDの起動
  3. コピー元ディスクのスナップショット作成
  4. コピー先ディスクの作成
  5. データコピー
  6. 起動設定

1. USB起動イメージの作成

まずは、FreeBSDのインストールメディアを作ります。USBメモリを使うのが便利です。次のウェブページからリンクをたどり、”…-amd64-memstick.img”をダウンロードします。例えば、”FreeBSD-11.0-RELEASE-amd64-memstick.img”です。

この後、ダウンロードしたイメージファイルをUSBメモリに書き込みます。ofで、USBメモリスティックを指定するのですが、これを間違うと既存のデータを破壊してしまいます。macOSの場合だと、diskutil listを、USBメモリを挿す前と挿した後で違いを見ればわかります。以下の例は、/dev/disk6だった場合です。

$ diskutil umountDisk /dev/disk6
$ sudo dd if=FreeBSD-11.0-RELEASE-amd64-memstick.img of=/dev/disk6 bs=512k
$ diskutil eject /dev/disk6

インストールメディアを作る時、最初私は、USBメモリに書き込むイメージファイルとして、DVD用イメージを使っていて、USBメモリから起動できずに困りました。

2. LiveCDの起動

Install開始

一番右のLibe CDを選びます。FreeBSD11が起動し、ログイン画面になります。アカウント名rootのパスワード無しでログインできます。

3. コピー元ディスクのスナップショット作成

コピー元のpoolは、プール名を変えてimportしておきます。

# zpool import -f -R /media rpool rpool-org

次に、コピー元のFreeBSD10のスナップショットを作ります。

# zfs snapshot -r rpool-org@20170616

4. コピー先ディスクの作成

gpartとzpool/zfsを使用します。コピー先のディスクは、/dev/ada0につながっているものとします。

まずは、GPTパーティションの作成です。

# gpart destroy ada0
# gpart create -s gpt ada0
# gpart add -a 4k -t freebsd-boot -s 512k ada0
# gpart add -a 4k -t freebsd-zfs -s 128G -l zroot ada0
# gpart add -a 4k -t freebsd-zfs -s 8G -l zil ada0
# gpart add -a 4k -t freebsd-zfs -l l2arc ada0
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0

使用中のディスクだとgpart destroyでエラーになります。その場合はdestroyの後に-Fオプションをつけて、強制的にdestroyできます。

もし、そのディスクの中に、ZFSで使っていたプールがある場合、いきなりgpart destroyするとハマります。元のプールをzpool destroyで破棄しておいてください。そうしないと、二度とimportも破棄も出来ない、ゾンビのプールができます。このゾンビプールは、ddで0を書き込まないと消えないようです。

gpart createでGPTディスクにします。

その後、gpart addで、起動領域、データ領域、キャッシュ領域の確保をします。-a 4kをつける事で、4kアラインのAFTディスクに対応できます。freebsd-bootは512kで、設定可能な最大サイズにします。zil(ログ)領域を確保しておきます。この大きさは、メインメモリの半分にします。使用しているホストは16GBのメモリを載せているので、8GBを指定しています。残りの領域をl2arc用(キャッシュ)に確保しておきます。

次に、ZPOOLの設定です。

# zpool create -R /mnt rpool gpt/zroot
# zfs create rpool/root
cannot mount '/mnt/rpool/root': failed to create mountpoint
filesystem successfully created, but not mounted
# zfs set mountpoint=/ rpool/root
# zpool export rpool
# zpool import -R /mnt rpool

まず、zpoolでZFSのプールを作成します。-R /mntで、/mntにマウントされる様にするのが肝です。

zfs createでrootと言う名前のデータセットを作り、この下に各データセットを作ります。2段構成にするのは、snapshotをsend/recvでリストアする時に簡単に出来るようにする為です。

ただ、この時点で、/mnt/rpool/rootを作れないと言うエラーになります。この為、set mountpoint=/を設定します。設定後、正しくマウントさせる為に、一旦exportして、再度importします。この時も-R /mntが必要です。

5. データコピー

ZFSを使うと本当に便利だなぁと思うのが、zfs send/recvによるデータコピーです。

# zfs send -pR rpool-org@20170616 | zfs recv -uvdF rpool

zfs sendのpオプションはプロパティもそのままコピーする設定で、Rオプションは階層も対象にする設定です。

zfs recvのuオプションは、コピー終了後にマウントしない設定です。recvの時はいつもuオプションを付けるようにした方が安全です。dオプションは階層のディレクトリを作る設定、FオプションはsendのRオプションに対応する階層を扱う設定です。vオプションはverbose設定です。出力メッセージが豊富になります。

私の場合、/usr/local以下は、別のプール(upool)に入れていました。これもコピーしてきます。

# zpool import -R /media upool
# zfs snapshot -r upool/usr/local@20170616 
# zfs send -pR upool/usr/local@20170513 | zfs recv -nuvdF rpool/root
# zfs send -pR upool/usr/local@20170513 | zfs recv -uvdF rpool/root

zfs recvで、最初nオプションを使って、ドライラン(dry run)しています。これは、recvで受け取ったデータをディスクへは書き込まず、挙動だけ確認するオプションです。recvで受け取るディレクトリが正しいかを確認するために使います。

この確認が終わったら、nオプション無しで実行します。

6. 起動設定

ここまででバックアップは終わりですが、このままでは起動しません。ブートローダのコピーが終わっていないためです。

# gpart bootcode -b /media/boot/pmbr -p /media/boot/gptzfsboot -i 1 ada0

/media/bootからコピーしてくるのが肝です。/mediaは、コピー元ディスクです。この中のpmbrとgptzfsbootを使わないと、ZFSのバージョンが合わずに、起動できません。最初、/bootに入っているFreeBSD11のものを使っていました。この状態だと起動せず、原因特定に時間がかかり、かなりハマりました。

loader.confの中身を確認します。次のようになっていればOKです。

zfs_load="YES"
vfs.root.mountfrom="zfs:rpool/root"

再起動は、rebootコマンドかctrl+alt+delを使います。

これで起動出来れば、成功です。

[amazonjs asin="B00CPG04JE" locale="JP"]

Posted by お市のかた