====== ZFSのSpecial Allocation ClassのSpecial VDEVの容量を見積もる ====== (2022-03-30 追記) 実際にテストしてみた→[[blog:2022:2022-02-24]] SSDをSpecial VDEVとしてZFSプールに追加すれば[[blog:2020:2020-12-08|性能向上が見込めそう]]なのは分かった。続いてSpecial VDEVに必要な容量を見積もってみる。 Special VDEVに格納されるデータは大きく2つに分けられる。 * メタデータ * 小ブロックのデータ(スモールI/Oの結果として生成される小さなレコード) zdbコマンドでプールのこれらの現在量を確認し、Special VDEVの容量を見積もることができそうだ。 実際に、稼働中の家鯖のプールで実際に確認してみよう。対象プールの下表のとおり。 ^ 用途 | システム用プール (zroot) | ^ 種類 | ミラー | ^ 使用量/容量 | 37.2/99.8GiB | ^ 特記事項 | * FreeBSD 12.2-RELEASEが入っている * 9-BETAの頃から連綿と続く年季の入ったプール * ホームディレクトリは別プールの * 細かなファイルが多め(/usr/srcや.svnフォルダ、portsのソース&ビルドファイルなど) | なお、zdb実行時はメモリの空きに注意すること。プールの使用量がテラバイト級だと数ギガ単位で消費する。メモリ不足でzdbが落ちるようなら、Special VDEVより先にメモリを追加しましょう。何はなくともZFSはメモリが重要なので。 ===== メタデータ ===== メタデータの使用量は簡単に確認できる。 Allocation Classにおける「メタデータ」とは、ファイルデータとzvolデータを除いたデータである。正確に言うと、レベル0のZFS plain file(いわゆる普通のファイルのデータ)とレベル0のzvol object(zvolのデータブロック)を除いたものがメタデータとなり、それら全てがSpecial VDEVに載るとのこと。 ''zdb -bbb プール名''を実行するとプールの詳細情報がズラズラ出るが、このうちTypeがTotalのASIZEからL0 ZFS plain fileとL0 zvol objectのASIZEを引いた値がメタデータサイズとなる。 $ zdb -bbb zroot Traversing all blocks to verify nothing leaked ... loading concrete vdev 0, metaslab 398 of 399 ... 36.3G completed (1522MB/s) estimated time remaining: 0hr 00min 00sec No leaks (block sum matches space maps exactly) bp count: 1693872 (省略) Dittoed blocks on same vdev: 147925 Blocks LSIZE PSIZE ASIZE avg comp %Total Type - - - - - - - unallocated 2 32K 8K 24K 12K 4.00 0.00 object directory (省略) - - - - - - - ZFS V0 ACL 85 3.62M 222K 688K 8.09K 16.76 0.00 L2 ZFS plain file 25.2K 2.85G 103M 214M 8.50K 28.36 0.56 L1 ZFS plain file 1.43M 47.3G 33.9G 35.9G 25.0K 1.40 96.63 L0 ZFS plain file ★これ 1.46M 50.1G 34.0G 36.1G 24.7K 1.48 97.19 ZFS plain file 4 64K 16K 32K 8K 4.00 0.00 L2 ZFS directory 1.02K 118M 4.26M 8.61M 8.47K 27.60 0.02 L1 ZFS directory 86.2K 237M 120M 456M 5.29K 1.97 1.20 L0 ZFS directory 87.2K 355M 125M 464M 5.32K 2.84 1.22 ZFS directory - - - - - - - zvol object      ★これ (省略) 1.62M 51.6G 34.4G 37.2G 23.0K 1.50 100.00 Total         ★これ この例だと、37.2G - 35.9G - 0 = 1.3G がメタデータサイズとなる(zvolは使っていないのでL0 zvol objectは出てこない)。 ===== 小ブロックのデータ ===== 必要となる小ブロック用の領域は、データセット毎に指定する''special_small_blocks''プロパティの値で変わってくる。 このプロパティはSpecial Allocation Classとして扱うブロックサイズ、すなわちSpecial VDEVへの読み書きとなる閾値で、512~128kの2の累乗値で指定する。この値**以下**の読み書きがSpecial VDEV行きとなるので、''recordsize''と同じ値にするのは危険。基本的には64k以下を指定することになるだろう。 ''zdb -bbbb プール名''を実行すると、データの種類ごとにレコードサイズの使用状況が表示される。 ここでも注目すべきはL0 ZFS plain fileとL0 zvol objectの分布である。非常に長いログのため、L0 ZFS plain fileの一部のみ掲載。 1.43M 47.3G 33.9G 35.9G 25.0K 1.40 96.63 L0 ZFS plain file psize (in 512-byte sectors): number of blocks 0: 36843 ******* 1: 213506 **************************************** 2: 139110 *************************** 3: 137030 ************************** 4: 98715 ******************* 5: 70100 ************** 6: 56304 *********** 7: 43444 ********* 8: 158789 ****************************** 9: 13123 *** (省略) 255: 36 * 256: 179774 ********************************** 0:, 1:, ..., 256: はブロックサイズを、その後ろはブロック数を表す。1ブロック512バイトなので、上記の8:の行は4096バイトブロックが158789個で約620MiBと読める。 各レコードサイズ以下のデータ量は下表の通りだった。 ^ レコードサイズ ^ データ量 ^ | 4KiB以下 | 1.69GiB | | 8KiB以下 | 2.53GiB | | 16KiB以下 | 3.40GiB | | 32KiB以下 | 4.60GiB | | 64KiB以下 | 7.9GiB | ここではSpecial VDEVをフル活用するとして、全部盛りの7.9GiBを採用する。 (2021-12-14追記) FreeBSD 13.0 (OpenZFS 2.0)の''zdb -bbb''でBlock Size Histogramという、まんまの情報が出ることに気づいた。ご丁寧に対象ブロック以下の合計バイト数まで出してくれるので、一撃で見積もることができる。 Block Size Histogram block psize lsize asize size Count Size Cum. Count Size Cum. Count Size Cum. 512: 310K 155M 155M 218K 109M 109M 0 0 0 1K: 353K 394M 549M 190K 225M 334M 0 0 0 2K: 149K 402M 951M 150K 392M 726M 0 0 0 4K: 346K 1.42G 2.35G 139K 747M 1.44G 0 0 0 8K: 303K 2.96G 5.31G 113K 1.24G 2.67G 773K 9.06G 9.06G 16K: 391K 8.17G 13.5G 183K 3.49G 6.16G 613K 14.4G 23.4G 32K: 528K 23.7G 37.2G 138K 6.11G 12.3G 553K 25.4G 48.8G 64K: 945K 83.4G 121G 137K 11.6G 23.8G 592K 57.7G 107G 128K: 19.5M 2.44T 2.56T 21.3M 2.66T 2.68T 20.2M 4.22T 4.32T 256K: 198K 70.1G 2.63T 11.2K 4.00G 2.69T 125K 47.3G 4.37T 512K: 39.6M 19.8T 22.4T 40.0M 20.0T 22.7T 39.7M 33.5T 37.9T 1M: 602K 602G 23.0T 602K 602G 23.3T 602K 1009G 38.8T 2M: 0 0 23.0T 0 0 23.3T 0 0 38.8T 4M: 0 0 23.0T 0 0 23.3T 0 0 38.8T 8M: 0 0 23.0T 0 0 23.3T 0 0 38.8T 16M: 0 0 23.0T 0 0 23.3T 0 0 38.8T 上記は26TBのプール(使用量は23TB)で、64KB以下のブロックが121GBだからプールに占める割合は0.46%となる。Special VDEVの容量は、一般的な用途ではプールの1~2%を確保しておけば十分なのかも。 ===== Special VDEVサイズの見積もり ===== 以上より、メタデータ量1.3GiBと小ブロックデータ量7.9GiBの合算、9.2GiBが現時点のSpecial Allocation Classのサイズとなる。 プールの使用量とメタデータ量/小ブロック量の関係は読み切れない部分があるけど、今後も同じ割合でSpecial Allocation Classが増えるとすれば、Special VDEVに必要なサイズは25GiB程度となる。 プールサイズの25%というと結構な割合となるが、細々とした大量のファイルの影響が考えられる。実際、このプールでは4KiB以下のファイルが全ファイル数の8割を占めており、中でも特に1KiB以下が5割を占めている。 ===== 様々なプールを分析してみる ===== Special VDEVの必要量は、プールの使われ方にも大きく依存すると考えられる。 そこで、手元の6つのプールについてSpecial VDEVの容量に影響しそうな項目を調査した。 ^ プール名 ^ 種類 ^ 使用量/容量 ^ ファイル数 ^ 平均ファイルサイズ ^ メタデータ ^ 64kB以下のレコード総量 ^ 使われ方 ^ | システムプール | ミラー | 37.2/99.8GiB | 1286414 | 0.029MiB | 1.3GiB \\ (3.5%) | 7.9GiB \\ (21.2%) | FreeBSDのシステム格納用。 \\ 見積作業で使ったプール。小粒で大量のファイル成分強い。| | データプール1 | ミラー | 2.54/7.12TiB | 1003104 | 2.654MiB | 20GiB \\ (0.8%) | 31.7GiB \\ (1.2%) | ホームディレクトリ用のプール。 \\ 日常生活での書類データ、数MB~数十MBの音楽ファイル、数十MBオーダーの写真などが主。 | | データプール2 | RAIDZ1 | 20.2/20.4TiB | 229356 | 92.351MiB | 700MiB \\ (0.003%) | 6.74GiB \\ (0.03%) | データプール1より重要度が下のデータ群。 \\ 数GB級の動画ファイル、数百KBクラスの画像、アプリのアーカイブ(ISO, zipなど様々)など。 | | データプール3 | 単体 | 6.49/7.1TiB | 1099395 | 6.190MiB | 10GiB \\ (0.2%) | 64.5GiB \\ (1.0%) | データプール2より重要度が下のデータ群。 \\ バックアップデータ、Time Machineのスパースバンドル、~2GB程度の動画、数百KBクラスの画像など。| | 業務用プール1 | RAIDZ1 | 5.09/8.93TiB | 2674793 | 1.995MiB | 30GiB \\ (0.6%) | 120.2GiB \\ (2.3%) | 業務で使われているプール、その1。 \\ 主に間接部門の書類、資料性の高いデータ、流動性の低いデータなど。 | | 業務用プール2 | ミラー | 0.954/1.99TiB | 183582 | 5.451MiB | 2GiB \\ (0.2%) | 1.04GiB \\ (0.1%) | 業務で使われているプール、その2。 \\ 数十KB~数百KBの多数の画像、数MBのアセットなど。| ファイル数が多いほど、またファイルサイズが小さいほど、メタデータと小ブロックの量は増える傾向にあるものの、一概にプール容量の何パーセントと言える感じではなさそうだ。 システムプールが少々特殊な気がするので除外すると、多くの場合、Special VDEVのサイズはプールサイズの5%あれば十分と言えなくもない?が、断定するにはサンプルが不足してるかな…。少々時間はかかるけど、今のところ都度zdbで計算する方がよさげ。潤沢な資金があるならともかく、20TiBの5%は1TiBになるので、丸ごとSpecial VDEVにおごるのは勿体ない気も…。 ファイルサイズの分布。 {{ :blog:2020:zpool_filesize_distribution.png |}} 用途ごとにプールを分けてることもあって、ファイルサイズはプールごとにそれなりにバラつきが見られる(目論見通り)。 続いてレコードサイズの分布。 {{ :blog:2020:zpool_recordsize_distribution.png |}} ZFSのトランザクショングループ(txg)のおかげか殆どが128KiBレコードとなっており、グラフにする意味もなかった。txgって予想以上に効くんだね…。これでは何も読み取れないので、各プールの使用率上位3位のレコードサイズを表にまとめた。 ^ プール名 ^ 1位 ^ 2位 ^ 3位 ^ | システムプール | 512 (14.2%) | 128k (11.95%) | 4k (10.54%) | | データプール1 | 128k (88.1%) | 4k (0.98%) | 512 (0.89%) | | データプール2 | 128k (99.6%) | 512 (0.11%) | 4k (0.02%) | | データプール3 | 128k (90.7%) | 4k (0.98%) | 8k (0.54%) | | 業務用プール1 | 128k (63.6%) | 1 (8.34%) | 112k (2.10%) | | 業務用プール2 | 128k (97.7%) | 512 (1.75%) | 11k (0.02%) | ZFSの書き込みは、ほぼほぼ128k/4k/512バイトに集約されると言っても過言ではなさそう。