FreeBSD10: あとからzfs構成にする

2017/04/01 追記: GPTラベルを利用するように改変。

FreeBSD 10のインストーラから zfs root 対応なので苦もなく zfs 構成にできるが、もっと前からアップグレードを繰り返して運用している FreeBSD サーバなどを zfs に鞍替えするのは腰の重い仕事である。 だが、昔に比べると FreeBSD での zfs ブートの仕組みが整理されていて案外簡単に進む。

ストーリーとして

的な流れを仮定する。

新HDDへのGPT打ち込み

新HDDを接続する。外付けでもOK。あとで古い HDD を外してデバイス名が変わっても平気。新HDDを繋いだデバイスが da0 だとする。

  1. GPTスキーム作成

    別で使ってたHDDなら既存パーティションをふっとばす。

    dd if=/dev/zero of=/dev/da0 count=64
    

    GPTで行くぜい。

    gpart create -s gpt da0
    
  2. 3つのパーティションを追加
    gpart add -l bt0 -t freebsd-boot -s 512k da0
    gpart add -l sw0 -t freebsd-swap -s 2g da0
    gpart add -l z00 -t freebsd-zfs da0
    

    -l オプションでラベルを打っておくことで、デバイス番号がずれても パーティション構成の分かりやすさが保たれるようにする(2017/4/1)。 freebsd-zfs のパーティションは -l z00 としたので、/dev/gpt/z00 でアクセスできるようになる。

  3. bootcode書き込み
  4. gpart bootcode -b /boot/pmbr da0
    gpart bootcode -p /boot/gptzfsboot -i 1 da0
    

FreeBSDインストーラに倣ってブート領域=512KB、 swap=2GB、zfs=残り全部、の3つを切った。

zfs領域作成

現行の ufs 環境で既にマウントしているファイルシステムとぶつからないよう altroot を指定してプールを作成すると、再起動するまでは altroot を仮のルートディレクトリとしてマウントされる。

  1. ストレージプールの作成

    altrootを /mnt とする。

    zpool create -o altroot=/mnt zpool0 gpt/z00
    

    これでいったん /mnt に全ての領域がマウントされる。

  2. 必要なzfsパーティションの作成

    たとえば現行環境が /, /var, /usr のパーティション構成で、 それと1対1対応するように作成するなら以下のようになる。

    zfs create -o quota=4g -o mountpoint=/ zpool0/ROOT
    zfs create -o quota=4g -o mountpoint=/var zpool0/var
    zfs create -o quota=80g -o mountpoint=/usr zpool0/usr
    

    どのくらい細かく切るかはお好みで。

  3. 既存ファイルのコピー

    tar --one-file-system でもなんでもよいが、rsync だと -x と -R オプションを利用してこんな感じか。

    rsync -avxHR / /var /usr /mnt
    

    現行環境から新環境にコピーしたい ufs パーティションのマウントポイントをコピー元にして全てコピーする。 その他オプションの意味はman参照。

  4. ブートfsの埋め込み

    起動後の /boot/ をどこから探せばよいかを zpool 自身に埋め込んでおく必要がある。今回の場合は zpool0/ROOT としたので以下のように set しておく。

    zpool set bootfs=zpool0/ROOT zpool0
    
  5. zfs構成での起動後のための修正

    コピーしたファイルを zfs 環境に適したものに修正する。

    echo zfs_load=YES >> /mnt/boot/loader.conf
    echo zfs_enable=YES >> /mnt/etc/rc.conf
    

    fstabを修正する。

    vi /mnt/etc/fstab
    

    新fstabからufsマウントの行を全部削る。swap は……この流れ、つまり古HDDを全て外して新HDDをSATAに繋ぐ想定だと ada0p2 ということになるが、せっかくzfsにするのだから swap パーティションをzvolにするのもよかろうが、 メモリの少ない状況で ZFS Swap を使うと今一つのようである(※ RootOnZFS #ZFS Swap Volume) ので、普通にGPTパーティションにするのが無難か。

最終確認

リブートしてブートデバイスを新HDDとして起動してみる。 ちょこちょこ凡ミスが出るだろうが直せばzfs運用に移行できるはず。 確認できたらshutdown後古いHDDを外して新HDDに置き換えてまた起動。

ミラー構成へ

おっと、新HDDでミラーしたい。あとから気づいても簡単。 デバイスプールを構成するディスクに別ディスクを "attach" するだけ。 今回の例で、新HDDを外付けから内蔵SATAに繋ぎ換えたと仮定すると、 以下のようになっているはず。

zpool status zpool0
  pool: zpool0
 state: ONLINE
  scan: none requested
config:

        NAME        STATE     READ WRITE CKSUM
        zpool0      ONLINE       0     0     0
          ada0p3    ONLINE       0     0     0

errors: No known data errors

構成ディスクは ada0p3 で、このディスクに同じサイズのものを attach すればよい。同サイズのHDDが ada1 に入っていて、同じように GPT を切ったとすると、ada1p3 がミラー相手になるので以下のようにする。

zpool attach zpool0 ada0p3 ada1p3

すぐ resilver が始まり、ミラー化完了。

今回、実例を元に文章化したが、書き漏らしがあるかもしれないので注意されたい。 疑問がある場合は御一報御質問を。good luck!