88171.net

ZFS on GELI

COVID-19のせいで、会社のMacBook Airを平日は毎日持ち歩いている。 万一の紛失や盗難に備えて、つい先日(今更)FileVaultを有効化してこのMBAのローカルストレージを暗号化した。 勢いで、私物のMacBook Proも暗号化した。

こうなると、次はXigmaNASで稼働している自宅のNASが気になる。 これにはTime Machineのバックアップが載っているが、Time Machineにはバックアップデータを暗号化する機能はない。 ローカルストレージは暗号化されているのにそのバックアップデータは平文という、この片手落ち感。

NASを暗号化、しよう。


XigmaNASのベースOSであるFreeBSDでは、現時点ではZFSのnative encryptionを利用できない。 なので、GELI (GEOM ELI) を使うというのが順当な選択肢になる。

FreeBSDに関してはnewbieなので正確性に欠けるかもしれないけれども、調べた限りではこういうことらしい。

つまりGELIとZFSはレイヤーが異なり、オペレーションも完全に独立している。 最初は何だか複雑で面倒な構成だと思っていたけれど、理解してしまうとこれはこれで明快に思える。

最終目標は、既存のzpoolの冗長性を確保したまま、すべてのデバイスをGELIデバイスに交換すること。


既存のzpoolに、以下のようなmirror vdevが一つある。 ここに新たにGELIデバイスをattachして、一時的に3-way mirrorの構成とする。 空きベイは少なくとも一つあるものとする(ないと辛い)。

# zpool status
[...]
config:

NAME            STATE     READ WRITE CKSUM
tank            ONLINE       0     0     0
 mirror-0      ONLINE       0     0     0
   ada0p1      ONLINE       0     0     0
   ada1p1      ONLINE       0     0     0
[...]

新しいディスクにパーティションを整備する。 HDDの総セクタ数は、たとえ同じベンダー・同じモデルでも僅かに異なることがある(経験談)。 せっかく用意したHDDがその僅かな差のせいで使えない、というリスクは許容し難いので、余裕を残して使うことにしている。 ただし256MiBという数字に深い根拠はない。

# gpart create -s gpt ada2
# gpart add -t freebsd-zfs -a 4k -s <calculate_yourself> -i 1 ada2
# gpart show ada2
=>        34  5860533101  ada2  GPT  (2.7T)
          34           6        - free -  (3.0K)
          40  5860008800     1  freebsd-zfs  (2.7T)
  5860008840      524295        - free -  (256M)

作成したパーティションをGELIで初期化してattachする。

# geli init -b -e AES-XTS -l 256 -s 4096 /dev/ada2p1
# geli attach /dev/ada2p1
# geli status
      Name  Status  Components
ada2p1.eli  ACTIVE  ada2p1

GELIデバイスをvdevにattachし、resilverが完了するのを待つ。 無事3-way mirrorの状態になれば、既存のディスクを安全に(データの冗長性を確保したまま)detachすることができる。

# zpool attach tank ada1p1 ada2p1.eli
# zpool status
[...]
config:

NAME            STATE     READ WRITE CKSUM
tank            ONLINE       0     0     0
 mirror-0      ONLINE       0     0     0
   ada0p1      ONLINE       0     0     0
   ada1p1      ONLINE       0     0     0
   ada2p1.eli  ONLINE       0     0     0
[...]

あとは、残りの未暗号化ディスクについて以下の手順を繰り返す。

  1. vdevからdetachする
  2. (必要があれば)パーティションテーブルを調整する
  3. GELIで初期化しattachする
  4. GELIデバイスをvdevにattachする

GELIに関していくつか。

BOOTフラグに頼らず、OS起動後にリモートから手作業でattachする運用も考えはしたが、逆に手間がかかりそうなので諦めた。 KVMレスでは運用できなくなってしまうが、ストレージが整った状態でOSに引き渡す方が(特にXigmaNASのようなembeddedな環境では)無用なトラブルも避けられるだろう。

サイズを見比べるとGELIには4KiBのオーバーヘッドがあるように見える。 頭の片隅には置いておいた方が良いかもしれない。

# geli list
[...]
Providers:
1. Name: ada2p1.eli
   Mediasize: 3000324501504 (2.7T)
   Sectorsize: 4096
   Mode: r0w0e0
Consumers:
1. Name: ada2p1
   Mediasize: 3000324505600 (2.7T)
   Sectorsize: 512
   Stripesize: 4096
   Stripeoffset: 0
   Mode: r1w1e1

GELIにはチェックサムによる整合性検証の機能もあるが、ZFSと組み合わせる場合はZFSに任せてしまうのが一般的らしい。 実際のところ、敢えてGELIにやらせても単にリソースの無駄遣いだろう。


参考文献