OpenZFS自作ストレージのすすめ

2022/07/17

なぜストレージを自分で作るのか

研究を行っていると、大きめの(1つのHDDに収まりきらないぐらいの)ファイルを長期間保存する必要が度々出てきます。通常であれば、外付けUSBHDDを買って分けて格納したり、業者さんに見積もりを依頼してRAIDの組まれたサーバーを購入することになるのが普通かと思いますが、自分の研究室ではOpenZFSによる大容量(700TB+)ストレージを作成し、NFSでアクセスできるようにして自前で長期運用しています。

こういう構成にたどり着いたのには次のような理由があります:

OpenZFS + RAIDZ2 (or RAIDZ3) + snapshotを使うことで、上の問題の大部分をカバーできるため、これを使っています。一方で、OpenZFSは速度の面で優れているわけではありません。このため、計算結果をすぐに格納するストレージとして使うことは推奨できません。弊研では計算クラスタの/homeなどの高速アクセスが必要な場所はXFSなどを利用し、NFS経由でOpenZFSが見えるようにしています。

最近だと、東大のストレージや、名大のコールドストレージなどの便利なサービスが増えていますが、いずれも継続性がよく分からない1という問題があります(名大のものは終了時にデバイスを返却する・ドライブ貸し出しという点でよく考えられていると思いますが、n年後にドライブ自体が故障したらどうするんでしょう……)。そういうわけで、最後には自分で面倒を見る前提でストレージを自前運用しています。本当はこういうのこそ大型計算機センターに任せたいのですが、昨今の予算制約ではまぁ仕方が無いか、という感じです。

ハードウェアの選択

OpenZFS用のサーバー構成を組んでくれる業者さんはレアだと思うので、ストレージを組もうとすると自前で構成を考える必要があります。自分が使っているHW構成は以下のようなものです。

ホストサーバーとJBODストレージを1つのシャーシに突っ込むこともできます。その場合、HBAのケーブルはinternalから挿せるものを選びましょう。UPSは強く推奨します – 皆さんも全データを落雷一発で焼きたくないですよね。

HBAの選択

HBAは次の条件を満たすように選びます。

本当は速度とかも考慮した方が良いのですが、前述の通りパフォーマンスを要求しないことを前提としているので、無視します。ZFSはHDDが1枚ずつ見えることが前提になって設計されており、RAIDを組んだ上にZFSを構成するケースは考慮されていません。管理も面倒になるのでやめた方が良いです。

ほとんどの<=2Uサーバーはlow profileと呼ばれる短いブラケット(PCIeカードから外に出るインターフェース部の長さ)を使うので、HBAがちゃんとlow profile対応か確認してください(普通は対応だと思いますが)。 特にホストサーバーを1Uにすると、カードの配置やインターフェースが特殊であることが多いので、よく確認してください。

JBODの選択

特に悩む点は無いですが、

自分は SuperMicroSuperChassis の66HDDモデルを購入しました。SuperMicro, Dellあたりは取扱業者も多いので、困ることは少ないと思います(クラスタ計算機を扱っている会社の大部分は見積もりに対応してくれると思います)。

HDDの選択

基本的には価格面でSATA3 ディスクを選ぶのが最適ですが、HDDにはSMRとCMRという二つの記録方式があります。SMRはZFSと致命的に相性が悪いので絶対に避けてください。判別方法はHDD各社の公式カタログを見ることで、SMR / CMRどちらであるか記載されています。WD redシリーズやSeagate IronWolfシリーズ、東芝の監視カメラ向けシリーズ(MN)あたりが良い価格帯かと思います(2022年現在、このあたりの大容量はすべてCMRだったはずです)。交換含めて5%ぐらい多めに買っておくと良いです。

ソフトウェアの設定

ここでは細かなコマンドを逐一書くことはしません(マニュアルを自分で読んで行動できる人の為に書いています)。

RAIDZの構成

OSにはLinuxを使います。最近だとRocky Linux, Ubuntuあたりが定番でしょうか。OSをインストールし、HBAやGbEのファームウェアを最新に更新しましょう。

OpenZFSをページに従いインストールします。Linux kernelの更新に対応できるよう、DKMS経由でOpenZFSのカーネルモジュールを自動でコンパイルできるようにしてください。3最近だとkABIベースの手法もありますが、私は使ってみたことが無いのでわかりません。

ZFSの構成はzpool createで行います。冗長性を確保するため、raidz2 以上を使用し、枚数が多い(>15)場合は1枚以上のspareを入れておくことを推奨します。(最近のOpenZFSだとraidzの代わりにdRAIDがありますが、その場合もparity2枚以上、spare1枚以上を推奨する、ということです)。リスク計算はこの辺が便利です4。また、ZFSの構成に用いるパスは/dev/disk/by-pathまたはby-vdevを推奨します

# zpool create/addは必ず--dry-runでできあがりを確認してから実行しましょう
zpool create --dry-run tank raidz2 /dev/disk/by-path/foobar-0-baz-baaz-1 /dev/disk/by-path/foobar-0-baz-baaz-2 /dev/disk/by-path/foobar-0-baz-baaz-3 ... spare ...
zpool create tank raidz2 /dev/disk/by-path/foobar-0-baz-baaz-1 /dev/disk/by-path/foobar-0-baz-baaz-2 /dev/disk/by-path/foobar-0-baz-baaz-3 ... spare ...

巨大な1枚のraidzにするのが良いか、中規模のraidzを2-3個作って1つのpoolにするのが良いかは私も分かりません。誰か詳しい人がいれば教えてください。管理の上ではraidz2/3を1個+spareが楽だと思います。

zpool createが終わったらzfs createでドライブを作成した後、マウントされるパスを調整(zfs set mountpoint=/foo/bar tank)し、/etc/exportsまたは/etc/export.d以下のファイルを記述してnfsからディスクを見えるようにしましょう。最後に各ユーザーの名前でディレクトリを掘ってpermissionを設定します。

定期scrubと定期snapshotと定期チェック

HDDの故障は、アクセスをしないと気づきにくいため、定期的にチェックをすることが好ましいです。ZFSの場合、zpool scrubで書き込まれ済みのデータに対してチェックサムの照合を行います。zpool scrubをcronで毎月実行することを強く推奨します。

# crontab -e でcronを設定しよう
@monthly /sbin/zpool scrub tank

また、データ消失の原因の多くはオペミスに起因します。このため、自分はZFSのsnapshot機能を使って定期的にread-onlyのスナップショットを作り、時間の経ったものを消すようにしています。これにより、オペミスによるファイル消去に気休め程度の対策が可能です。こんな感じです:

# 普段はzshで書いていますがbashでも動くはず……?
# このscriptは@weeklyで動かす
/sbin/zfs snapshot shared@$(/bin/date '+%Y-%m-%d')

str2weeks() {
  S=$1
  sec=$(/bin/date -d $S '+%s')
  echo $(( sec / (60 * 60 * 24 * 7) ))
}

thisweek=$(str2weeks $(/bin/date '+%Y-%m-%d'))

# clean up snapshots
for snap in $(/sbin/zfs list -t snapshot -H | cut -f1); do
  d=${snap##*@}
  wk=$(str2weeks $d)
  # keep only 4 weeks
  if (( wk < thisweek - 4 )); then
    /sbin/zfs destroy -d $snap
  fi
done

最後に、定期scrubをしても警報が送られないと困るので、cronで毎日、チェックスクリプトを走らせてメールでも飛ばすことにしましょう。

# このscriptは@dailyで動かす
declare -a mailto=(foobar@example.com bazbaaz@example.com)
NC=$(/sbin/zpool status | /bin/grep -c -E 'DEGRADED')
/sbin/zpool status | /bin/grep -E '(ERR|FAULTED|UNAVAIL)' -q
Q=$?
if (( $NC > 0 )) || (( $Q == 0 )) ; then 
  for mail in ${mailto[@]}; do
    {
      /bin/cat << EOF
To: $mail
Subject: zpool detected error(s)

Disk shinderu pyon
EOF
        /sbin/zpool status -v
      } | /usr/sbin/sendmail $mail
  done
fi

sendmailが使えない環境の場合、slack bot等を作って通知を飛ばすのが楽だと思います。

上記の設定を行った後、/dev/urandomあたりを用いて適当な巨大ファイルを作成し、scrubを掛けてみることを推奨します。 30枚を超えるHDDがあるとほぼ確実に1枚以上、初期不良HDDが見つかります。 メール送信用のスクリプトが動いているかどうかの確認にもなります。

これまでにやらかしたミスとbad-knowhow

このページを参考にストレージを構成する方に向けて、自分がやらかしたミスや注意事項をいくつか記載しておきます。

補遺

本ページのスクリプトおよび情報は参考用として置いているものです。スクリプトはas-is(あるがまま)で提供しており、万一スクリプトがユーザーの予想外の動作をした場合でも、ページ著者である桜庭は一切の責任を負わず、保障もしません。スクリプトの実行はご自身の責任で内容と動作の確認を行ってください。


  1. 継続性というと昨今ではどこでも研究室の継続性自体が怪しいのだが……。 ↩︎

  2. 2022年8月7日現在、日本語版wikipediaの説明は完全に間違っているので注意 ↩︎

  3. DKMSを用いる都合上、OpenZFSをWSL上で走らせるのは非常に面倒で、非推奨です。 ↩︎

  4. 仮定はそれなりに雑なモデルなので過信しないこと。たとえばreal worldのHDDは同時期に買うとまとまって壊れる。 ↩︎