稼動中FreeBSDのクローンでマシンの引っ越し@zfs

稼動中のシステムがある。ハードウェアの引っ越しをしたい。 止める時間をできるだけ短く。FreeBSDの話。

+--- 現行PC ----+          +--- 新PC ----+
|               |          |             |
|               |          |             |
|    [HDD0]     |   移行   |   [HDD0]    |
|    [HDD1]     |   →→   |   [HDD1]    |
|    ミラー     |          |    ミラー   |
|               |          |             |
+-----+---------+          +-------------+
      +--[ USB外付けHDD ]

現行PCのハードウェアを刷新して同じ構成の新ハードウェアに行きたい。 ただし、ダウンタイムは最少にしたい。というときは、 以下の手順をとるとリブート+USBケーブル差し替え時間だけの停止で済む。。

  1. 構成ミラーと同じ容量のHDDをUSB外付けで繋ぎミラー内容を引き継ぐ
  2. ミラーのコピーが完了したら現行PCを止めると同時に外付けHDDを新 PCに繋いで起動
  3. 新PCの内蔵HDDにミラー内容をコピーする

gmirror化してあるシステムだとUSB-SATAなんかに外付けデバイスをくっつけて、 da0 に生き写しを取る。

gmirror insert existingvol /dev/da0p3

とかやって、ミラーのrebuildingが終わった頃合でシングルユーザモードに 落とし、

gmirror remove existingvol /dev/da0p3

とかして外したHDDを別のマシンに持って行くとそのまま使える。あ、 もちろん gpart bootcode とかでブートコードを書いておく必要はある。

zfsだとどうかな。やってみよう。

GPT zfs bootの場合

大事なことを先に。この手のことをする場合は、データ移行用HDDを外す場合に

zpool detach/offline してはアカン。

移行した先で pool として認識されないものができ上がるから。さて本論。

まず現行システムに既存poolよりでかいHDDを外付け接続する。 HDDに残っているかもしれない既存ラベルを壊してパーティション分けする。 以下の例は現行システムのHDDが80GBで、FreeBSD10インストーラの AutoZFSにパーティション分けしてもらったものを真似っこでda0に作るものである。

dd if=/dev/zero of=/dev/da0 count=64
gpart create -s GPT da0
gpart add -a4k -t freebsd-boot -s 512k da0
gpart add -a4k -t freebsd-swap -s 2g da0
gpart add -a4k -t freebsd-zfs -s 80g da0
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0
gpart show da0
=>        34   976773101   da0  GPT  (466G)
          34           6        - free -  (3.0K)
          40        1024     1  freebsd-boot  (512K)
        1064     4194304     2  freebsd-swap  (2.0G)
     4195368   167772160     3  freebsd-zfs   (80G)
   :

これ(da0p3)を既存zpoolにattachする。

zpool status
  :
        NAME        STATE     READ WRITE CKSUM
        zpool       ONLINE       0     0     0
          gpt/zfs0  ONLINE       0     0     0
  :
zpool attach zpool gpt/zfs0 da0p3
(沈黙の後つながる)

zpool status を繰り返して resilver が終わったら落とす。 いきなり新PCに繋ぎかえる前に、現行PCにて外付けHDDからも起動できることを 確認してもよい。ちゃんと外付けHDDから起動できると確信が持てたら 止める。このとき、zpoolは offline したり detach しちゃうとHDDを持ってった 先で認識できないからいきなり shutdown でよい。

shutdown -p now

この外付けHDDを別のまっさらのマシンに持って行って外付けHDDから起動する。 まっさらマシンの内蔵HDDへのコピーは同じ手順で。うまく引っ越しが終わったら 外付けHDDを外しておしまい。これも外付けHDDを外すときに zpool detach する ともうそのHDD単体ではpool認識されなくなるので物理的に外してから 新マシン側で外付けHDDがつながっていない状態で zpool detach したほうが安心感がある。

NICとかは新旧マシンで揃えとくとほんとにリブート1回の一瞬で終わる。 もしNICの種類が変わっちゃう場合は事前に /etc/rc.conf で

# 旧マシン
ifconfig_em0_name=lan0
ifconfig_bge0_name=wan0

  ↓

# 新マシン
ifconfig_re0_name=lan0
ifconfig_em0_name=wan0

こんな風に仮想的なNIC名でネットワークを組むようにしておくとよい。

GPT zfsboot から MBR zfsboot へ

しかしこのやり方には罠がある。まっさらマシンの方が 「GPTブートできなーい」ってときに起動できなくてハマる。 移行先マシンでGPTブートできるか心配な場合はまず、 外付けHDDを移行先マシンに繋ぎ、FreeBSD10の標準インストーラの「Auto ZFS」で 外付けHDDにインストールし、その外付けHDDから起動できるか確かめてみる。 もし、移行先の本体がGPTブートできないようなら MBR で zfs root 起動する設定でコピーを作る必要がある。 ということで、外付けHDDをda0とした場合のコマンド羅列。

dd if=/dev/zero of=/dev/da0 count=64
gpart create -s mbr da0
gpart add -a4k -t freebsd da0
gpart create -s BSD da0s1
gpart add -t freebsd-zfs -s ZFSのサイズ da0s1
gpart add -t freebsd-swap da0s1
gpart bootcode -b /boot/boot0 da0
gpart set -a active -i 1 da0
dd if=/boot/zfsboot of=/dev/da0s1 count=1
dd if=/boot/zfsboot of=/dev/da0s1 iseek=1 oseek=1024
zpool attach zpool gpt/zfs0 da0s1a

ポイントはブートコード(zfsboot)の書き込みで、これはddで行なう。 ちなみにこのやり方は zfsboot(8) に書いてあるので作業時にぐぐれなくても安心。