ProxmoxでZFSのARCがメモリを食う:VMが落ちる前にARCの上限を設定する手順

Photo: Sergei Starostin / Pexels
Proxmox VE を ZFS でインストールして VM を増やしていくと、ある日 VM が前触れなく停止している——というトラブルに出会うことがあります。ログを追うと、ホストのメモリが足りなくなって OOM Killer が VM のプロセス(kvm)を止めていた、というパターンです。
先に結論です。ZFS はメモリを読み込みキャッシュ(ARC)として積極的に使うため、メモリの少ないミニPCでは VM と取り合いになります。zfs_arc_max で ARC の上限を決めておけば防げます。 設定はファイル1行と再起動だけです。
ARC とは何か、なぜ VM が落ちるのか
ARC(Adaptive Replacement Cache)は、ZFS がディスクから読んだデータをメモリに置いておくキャッシュです。読み込みが速くなるので本来はありがたい仕組みで、メモリが逼迫すれば ARC は縮む設計とされています。
ただ、VM が一気にメモリを確保したとき、ARC の縮小が間に合わないことがあります。そのとき Linux カーネルは空きを作るために、メモリを一番使っているプロセスを止めます。Proxmox では、それがたいてい VM の kvm プロセスです。
もうひとつ紛らわしい点があります。ARC は free -h で「buff/cache」ではなく「used」に数えられます。 ページキャッシュと違い、Linux から見ると「使用中のメモリ」に見えるので、「VM の合計より明らかに使用量が多い」と感じたら ARC を疑ってください。
なお、ARC の既定の上限は Proxmox のバージョンで違います。
- Proxmox VE 8.1 以降の新規インストール:インストーラーが搭載メモリの 10%(最大 16GiB)を上限に設定するとされています
- それより前に入れて、アップグレードしてきた環境:OpenZFS の既定どおり、搭載メモリの 50% まで使います
古いバージョンから使い続けているホストほど、ARC が大きいまま残っている可能性があります。
ステップ1:VM が落ちた原因が OOM か確認する
まず本当にメモリ不足で止まったのかを確認します。
journalctl -k | grep -i -E "out of memory|killed process"
Out of memory: Killed process 12345 (kvm) のような行があれば OOM です。何も出なければ、別の原因(ゲスト内のエラー、ストレージ不足など)を先に疑ってください。
ステップ2:ARC が今どれだけ使っているかを見る
arc_summary | head -n 30
ARC size (current) が現在の使用量、Max size (high water) が上限です。arc_summary が見つからない場合は、次のコマンドでも確認できます(単位はバイト)。
grep -E "^(size|c_max|c_min) " /proc/spl/kstat/zfs/arcstats
cat /sys/module/zfs/parameters/zfs_arc_max
zfs_arc_max が 0 なら、上限が明示されておらず既定値(搭載メモリの 50%)で動いています。
ステップ3:上限をいくつにするか決める
Proxmox の公式ドキュメントでは、目安として 「ベース 2GiB + ストレージ 1TiB あたり 1GiB」 が挙げられています。たとえば ZFS プールが 2TB なら、4GiB 程度が出発点です。
私が考える決め方は、逆算です。
- 搭載メモリから、全 VM・コンテナに割り当てたメモリの合計を引く
- さらに ホスト(Proxmox 本体)用に 2〜4GB を引く
- 残りの範囲で、上の目安以上の値を ARC の上限にする
16GB のミニPCで VM に合計 10GB 割り当てているなら、ARC は 2〜4GB が現実的です。残りが目安を下回るなら、ARC を削るより VM の割り当てを見直すか、メモリを増設するほうが健全です。
ステップ4:すぐに反映する(再起動まで有効)
まず再起動せずに反映して、様子を見ます。4GiB にする例です。
echo "$((4 * 1024*1024*1024))" > /sys/module/zfs/parameters/zfs_arc_max
注意点がひとつあります。設定値が zfs_arc_min(既定は搭載メモリの 1/32)以下だと、zfs_arc_max は無視されるとされています。 小さな値にしたいときは、先に zfs_arc_min をそれより小さい値にしてください。
ARC はすぐに縮むとは限らず、メモリ要求に応じて徐々に下がっていきます。
ステップ5:再起動後も残るように設定する
/etc/modprobe.d/zfs.conf に1行書きます(ファイルが無ければ新規作成)。
echo "options zfs zfs_arc_max=4294967296" > /etc/modprobe.d/zfs.conf
ルートファイルシステムが ZFS の場合(インストール時に ZFS を選んだ場合)は、起動時の initramfs にこの設定を取り込む必要があります。
update-initramfs -u -k all
値を変えるたびにこのコマンドが必要です。忘れると、再起動したら元の 50% に戻っていた、ということになります。再起動後に、ステップ2のコマンドで zfs_arc_max が設定値になっているか確認してください。
それでも足りないときはメモリを増設する
ARC を小さくしすぎると、ZFS の読み込み性能が落ちます。VM を増やしたい、ZFS のプールも大きくしたい、という状況なら、根本的な解決はメモリの増設です。ミニPCはメモリがオンボード直付けの機種もあるので、購入時の仕様を確認してから選んでください。
- Crucial DDR5-5600 SO-DIMM 32GB(16GB×2):N100/N150 系や最近の Ryzen ミニPC 向け
- Crucial DDR4-3200 SO-DIMM 32GB(16GB×2):中古の法人向けミニPCなど DDR4 世代向け
N100 系は対応メモリ量がメーカー公称より多く載る例も知られていますが、動作保証外になるので、公称値の範囲で選ぶのが無難です。
まとめ
- ZFS の ARC はメモリを大きく使い、VM のメモリ確保と競合すると OOM Killer が kvm を止めることがある
- ARC は
free -hでは used に数えられる。arc_summaryで実際の使用量を確認する - Proxmox VE 8.1 より前から使っているホストは、ARC の上限が搭載メモリの 50% のままの可能性がある
- 上限は「2GiB + 1TiB あたり 1GiB」を目安に、VM の割り当て合計から逆算して決める
- 恒久設定は
/etc/modprobe.d/zfs.conf。ルートが ZFS ならupdate-initramfs -u -k allを忘れない
運営者が作った Excel テンプレートを BOOTH で配布しています。IT 資産管理台帳(無料 Lite 版あり) / IT 資格の学習管理シート


