88171.net

I stand with Ukraine🇺🇦

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 にやらせても単にリソースの無駄遣いだろう。


参考文献