はじめに
Amazon FSx for OpenZFSを本番導入する前、CloudWatchの監視設定(アラームのしきい値など)を決めるために、実際にファイルを書き込みながら各種メトリクスの動きを見る検証をしていました。10GiBのファイルを書き込んでみたところ、MemoryUtilizationが書き込み前は20%台前半だったのに、書き込み後は67%台まで急上昇していることに気づきました。
ディスク使用量は10GiB分しか増えていないのに、メモリ使用率は3倍以上に跳ね上がっています。最初は次のような懸念が頭をよぎりました。
- メモリリークが起きているのではないか
- サイジング(スループットキャパシティ)が不足しているのではないか
- 何らかの異常な処理が裏で走っているのではないか
調べてみると、これはZFSのARC(Adaptive Replacement Cache)というキャッシュ機構による、想定どおりの挙動でした。ARCはZFSが性能を出すために意図的にメモリを使い切る設計になっているため、単純な閾値監視で「メモリ使用率が高い = 異常」と判断すると誤検知を招きます。これはFSx for OpenZFSのデプロイタイプに限った話ではなく、ARCを使うOpenZFSであればどの構成でも起こり得る挙動です。
この記事では、監視設定を検討する過程で遭遇したこの挙動をきっかけに、ZFSのARCの仕組みと、FSx for OpenZFSの監視設計で気をつけたい点を整理します。
想定読者
- EC2やVPCなどAWSの基本的なサービスを理解しているインフラエンジニア
- FSx for OpenZFSやNFSサーバーの運用、監視設計に関わる方
- ZFSやOpenZFSの内部構造について詳しい前提知識は不要です(本文で解説します)
この記事でわかること
- ZFSのARC(Adaptive Replacement Cache)とは何か、なぜメモリを積極的に使う設計になっているか
- FSx for OpenZFSの
MemoryUtilizationが高くても異常ではないケースの見分け方 - メモリ使用率だけに頼った監視・アラート設計の落とし穴と、代わりに見るべき指標
検証で気づいたCloudWatchメトリクスの挙動
検証内容
EC2からFSx for OpenZFSをNFSマウントし、ddコマンドで10GiBのランダムデータを書き込むだけのシンプルな検証です。
検証に使ったボリュームはLZ4圧縮を有効にしていました。ZFSには圧縮したブロックをそのままキャッシュする「Compressed ARC」という仕組みがあり、圧縮率が高いデータを書き込むと、ARCが実際に消費するメモリ量は論理データ量より小さくなります。書き込んだデータ量とメモリ使用量の関係をそのまま見たかったので、ゼロ埋めや繰り返しパターンではなく、圧縮がほとんど効かない/dev/urandom由来のランダムデータを使いました。
まず、マウント直後の状態をdfで確認します。この時点ではFSxボリュームの使用量は0です。
[root@ip-10-8-3-242 ~]# df
...
fs-040a55a74558bfc58.fsx.ap-northeast-1.amazonaws.com:/fsx 67108864 0 67108864 0% /mnt/fsx
続けて、/dev/urandomを使って10GiBのランダムデータを書き込みます。
dd if=/dev/urandom of=/mnt/fsx/random_10gb.bin bs=1M count=10240 status=progress
実測結果
書き込み後にdfを確認すると、使用量が約10GiB(16%)に増えています。
10737418240 bytes (11 GB, 10 GiB) copied, 127.934 s, 83.9 MB/s
[root@ip-10-8-3-242 ~]# df
...
fs-040a55a74558bfc58.fsx.ap-northeast-1.amazonaws.com:/fsx 67107840 10492928 56614912 16% /mnt/fsx
同じタイミングでCloudWatchのMemoryUtilizationを見ると、書き込み前は20%台前半だったメモリ使用率が、書き込み中から書き込み直後にかけて67.3%まで急上昇していました。
書き込んだのはたった10GiBのファイル1つですが、メモリ使用率はディスク使用量の増加分よりはるかに大きく跳ね上がっています。負荷試験や大規模な移行作業でまとまったデータを書き込んだとき、この挙動を知らずに見ると「メモリリークではないか」「サイジングが足りないのではないか」と誤解しそうです。
書き込み量を20GiBに増やしても大きくは変わらなかった
「書き込み量を増やせばメモリ使用率はさらに上がり続けるのか」も気になったので、続けてもう1本10GiBのファイルを書き込み、ファイルシステム全体の使用量を累計20GiBまで増やしてみました。
[root@ip-10-8-3-242 ~]# dd if=/dev/urandom of=/mnt/fsx/random_20gb.bin bs=1M count=10240 status=progress
10722738176 bytes (11 GB, 10 GiB) copied, 128 s, 83.8 MB/s
10240+0 records in
10240+0 records out
10737418240 bytes (11 GB, 10 GiB) copied, 128.554 s, 83.5 MB/s
[root@ip-10-8-3-242 ~]# df
...
fs-040a55a74558bfc58.fsx.ap-northeast-1.amazonaws.com:/fsx 67107840 20985856 46121984 32% /mnt/fsx
ディスク使用量は16%(約10GiB)から32%(約20GiB)へと倍増しましたが、同じタイミングのMemoryUtilizationは66.2%とほぼ横ばいでした(10GiB書き込み時は67.3%)。
書き込むデータ量を2倍にしても、メモリ使用率はむしろ微減しています。ARCによるメモリ使用は書き込んだデータ量に比例して際限なく増え続けるわけではなく、ある水準で頭打ちになるようです。この点は、次のARCの仕組みとあわせて見ていきます。
ZFSのARC(Adaptive Replacement Cache)とは何か
ZFSはOS標準のページキャッシュとは別に、ARC(Adaptive Replacement Cache)という独自のインメモリキャッシュ機構を持っています。読み取ったデータをメモリ上に保持し、ディスクI/Oを減らして読み取り性能を高速化する仕組みです。
ARCは読み取りデータだけでなく、書き込んだデータも直後に読み返される可能性を見込んでキャッシュに乗せます。先ほどの検証で10GiBの書き込みだけでメモリ使用率が急上昇したのは、この書き込みデータがARCに乗ったためだと考えられます。
圧縮が有効なボリュームでは、ARCは圧縮した状態のままブロックを保持する「Compressed ARC」という仕組みも持っています。同じ論理データ量でも、圧縮率が高いデータほどARCが消費する物理メモリは少なく、圧縮が効きにくいデータほど書き込んだ量に近いメモリを消費します。検証で圧縮の効きにくいランダムデータを使ったのは、この圧縮の影響を排除して、書き込みデータ量とメモリ使用量の関係をそのまま見たかったからです。
なぜ「Adaptive」なのか
ARCは単純なLRU(Least Recently Used、最近使われたものを優先)ではなく、次の2種類のリストを組み合わせて管理します。
- 最近アクセスされたデータのリスト(Recency重視、LRU的な性質)
- アクセス頻度が高いデータのリスト(Frequency重視、LFU的な性質)
ワークロードの傾向に応じて、この2つのリストにメモリをどう配分するかを動的に調整するのが「Adaptive(適応的)」と呼ばれる理由です。単純なLRUキャッシュだと、たまたま1回だけ大量に読まれたデータにキャッシュを奪われて、本来頻繁にアクセスされるデータが追い出されてしまうことがありますが、ARCはこの弱点を緩和する設計になっています。
ARCは「空いているメモリを使い切る」設計
ARCのもう一つの特性は、デフォルトで利用可能なメモリを積極的に使い切ろうとする点です。ZFSには「使われていないメモリは無駄」という思想があり、ARCはキャッシュとして使える上限(arc_maxに相当する設定)まで空きメモリを埋めていきます。
- OSやアプリケーションから見て「メモリ使用率が高い」ように見えても、キャッシュとして有効活用されているだけで、メモリ不足とは違います
- 他のプロセスが実際にメモリを必要とした場合、ARCは保持しているキャッシュを解放して譲ります
- ARCによるメモリ使用は「使われている」というより「(今のところ)無駄なく活用されている」と捉えたほうが実態に近いです
ARCは書き込んだデータ量に比例して無制限にメモリを消費し続けるわけではありません。使用量が上限に近づくと、あまり使われていないキャッシュデータを追い出しながら新しいデータを取り込むため、メモリ使用率はある水準で頭打ちになります。先ほどの検証で書き込み量を10GiBから20GiBに倍増させてもメモリ使用率がほぼ横ばいだったのは、この上限に達していたからだと思われます。
この特性はLinuxのページキャッシュ(freeコマンドでbuff/cacheに計上される部分)にもある程度似ています。ただし、ARCはZFSがカーネル空間内で独自のロジックによって管理している点、キャッシュ対象がブロックデバイスレベルではなくZFSのデータセット・ボリューム単位である点が異なります。
FSx for OpenZFSにおけるARCとL2ARCの位置づけ
FSx for OpenZFSは、OSSのOpenZFSが持つARC・L2ARCの仕組みをそのままマネージドサービスとして提供しています。CloudWatchではCacheTypeというディメンションで、ARC(インメモリキャッシュ)とL2ARC(NVMeキャッシュ)を分けてキャッシュヒット率(FileServerCacheHitRatio)を確認できます。
ARCはデプロイタイプ(Single-AZ 1、Single-AZ 2、Multi-AZ)を問わず、どのFSx for OpenZFSでも動作する基本のキャッシュ機構です。一方、L2ARCはSingle-AZ 2だけが持つ追加のNVMeキャッシュ層で、それ以外のデプロイタイプにはありません。
- ARCによるメモリ使用そのものはOpenZFSの基本的な仕組みで、L2ARCの有無にかかわらず発生します
- L2ARCはARCから溢れたデータを受け止める二次キャッシュなので、L2ARCがないからといってARCのメモリ使用が特別に増えるわけではありません
MemoryUtilizationの急上昇は、デプロイタイプを問わず起こり得る、ARC由来の一般的な挙動と捉えてよさそうです。
FSx for OpenZFSではARCを直接チューニングできない
一般的なZFS環境では、zfs_arc_maxやzfs_arc_minといったカーネルモジュールパラメータで、ARCが使うメモリの上限・下限を直接制御できます。データベースサーバーなど、ARCにメモリを奪われたくないワークロードを同居させる場合は、zfs_arc_maxを低めに設定してアプリケーション側にメモリを残す運用方法もあるようです。
しかしFSx for OpenZFSは完全マネージド型サービスで、ファイルサーバー側のOSやカーネルパラメータにユーザーが直接アクセスすることはできません。一般的なZFS環境で使われるARCのチューニング手法は、FSx for OpenZFSでは使えないということです。
この制約の中で実務上コントロールできる要素は次のとおりです。
| 対応策 | 内容 |
|---|---|
| スループットキャパシティの選定 | スループットキャパシティに応じてファイルサーバーの搭載メモリ量が変わるため、間接的にARCが使える物理メモリの絶対量を調整できる |
| デプロイタイプの選定 | Single-AZ 2であればL2ARC(NVMeキャッシュ)を併用できるため、ARC(メモリ)だけに依存せずキャッシュ層を拡張できる |
| 監視設計での吸収 | チューニングで制御できない以上、後述する複合アラームなど監視側の工夫でメモリ使用率の高さそのものをリスクとして扱わない設計にする |
FSx for OpenZFSでは、「ARCの挙動そのものを直接コントロールする」のではなく、「ARCが十分に機能する土台(メモリ量・キャッシュ層)を選び、監視側でその挙動を正しく解釈する」という間接的なアプローチを取ることになります。
CloudWatchのMemoryUtilizationは何を測っているか
MemoryUtilizationは、AWS公式ドキュメントでは「file serverのメモリリソースの使用率(%)」と定義されているメトリクスです。ARCによるキャッシュ使用分もこのメモリ使用率に含まれます。
MemoryUtilizationが高いこと自体は、次のどちらの状態でも起こり得ます。
- キャッシュが有効に機能し、読み取り性能に貢献している(正常)
- 本当にメモリが逼迫し、性能や安定性に影響が出始めている(注意が必要)
この2つを見分けるために、あわせて確認したいのがFileServerCacheHitRatioです。CacheType=ARCでこの値を確認します。キャッシュヒット率が高い水準を保っているなら、MemoryUtilizationの高さはキャッシュが効いている結果と判断できます。逆に、メモリ使用率が高いままキャッシュヒット率が下がっているなら、キャッシュの効率が悪化しているサインとして注意深く見る必要があります。
メモリ監視だけで判断することの危険性
ここが実務上、最も注意したいところです。ARCの特性を知らずにMemoryUtilizationへ固定閾値のアラート(例: 80%超えで通知)を設定すると、まとまったデータの書き込みや読み込みが発生するたびにアラートが鳴る状態になりかねません。典型的な「アラート疲れ」を招き、本当に見るべき異常を見逃すリスクにつながります。
FSx for OpenZFSの監視設計では、MemoryUtilizationを単独の障害検知トリガーとして扱わず、次のようなメトリクスと組み合わせて判断することをおすすめします。
| メトリクス | 見るべきポイント |
|---|---|
| MemoryUtilization | 単体で高いことを問題視せず、他メトリクスとの相関で判断する |
| FileServerCacheHitRatio(CacheType=ARC) | 低下傾向が続く場合はキャッシュ効率の悪化を疑う |
| CPUUtilization | メモリ使用率とあわせて高い場合は、負荷そのものが高い可能性を検討する |
| FileServerDiskIopsUtilization / FileServerDiskThroughputUtilization | ディスク側の逼迫がないかをあわせて確認する |
| NetworkThroughputUtilization | クライアントとの通信がボトルネックになっていないか確認する |
MemoryUtilizationとFileServerCacheHitRatioを組み合わせた複合アラーム
単一のメトリクスに閾値を設定する代わりに、CloudWatchの複合アラーム(Composite Alarm)を使ってMemoryUtilizationとFileServerCacheHitRatioを組み合わせると、ARCが正常に機能している状態と、本当に注意すべき状態を切り分けやすくなります。
ARCが正常に機能している間は、メモリ使用率が高くてもキャッシュヒット率は高い水準を保っているはずです。逆に、キャッシュヒット率が下がっているのにメモリ使用率だけが高いままという状態は、キャッシュの効率が悪化しているか、本当にメモリが逼迫している兆候として注視したいところです。
次の2つの子アラームを用意し、両方が同時にALARM状態になった場合のみ通知する複合アラームを組みます。
| 子アラーム | 条件(例) |
|---|---|
| MemoryUtilization高アラーム | MemoryUtilizationの平均値が15分間85%を超える |
| CacheHitRatio低アラーム | FileServerCacheHitRatio(CacheType=ARC)の平均値が15分間70%を下回る |
複合アラームの条件式は次のようなイメージです。
ALARM(MemoryUtilization-High) AND ALARM(CacheHitRatio-Low)
この構成であれば、大量データの書き込みなどでARCがフル稼働してMemoryUtilizationが一時的に跳ね上がっても、FileServerCacheHitRatioが高い水準を保っている限りは通知されません。キャッシュヒット率の低下を伴うメモリ高使用率だけを検知対象にできるので、アラート疲れを防ぎながら、本当に注意すべき状態を見逃しにくくなります。
しきい値(85%、70%など)は環境やワークロード特性によって変わります。実際には検証環境で正常時のMemoryUtilizationとFileServerCacheHitRatioの推移を計測し、その実測値をもとにしきい値を決めることをおすすめします。
MemoryUtilizationが高いこと自体はARCの設計上ごく自然な状態です。とはいえ、常に無視してよいわけでもないというのが個人的な感覚です。ARCは必要に応じてメモリを解放しますが、その解放が追いつかないほどの負荷や、キャッシュ以外の要因でメモリが逼迫するケースまで否定するものではありません。「高いメモリ使用率=即異常、ではない」という前提を持ちつつ、他の指標とあわせて総合的に判断する姿勢が必要だと思います。
実務での教訓
今回はまだ業務利用前の検証段階だったので、時間をかけてARCの仕組みを調べ、監視設計を見直す余裕がありました。もしこれが本番稼働後に大量データの書き込みをきっかけとしたアラートで初めて発覚していたら、「メモリ不足かもしれない」という誤った仮説のもとで緊急対応を進めてしまっていたかもしれません。
- マネージドサービスであっても、内部で使われているOSSコンポーネント(今回でいうOpenZFS)の設計思想を理解しておくと、メトリクスの解釈を誤らずに済みます
- 監視のアラート閾値は、そのメトリクスが何を測っていて、どういう挙動が正常かを理解したうえで設計したいところです
- 同様の「キャッシュ由来のメモリ高使用率」は、FSx for OpenZFSに限らず、他のキャッシュ機構を持つマネージド型ファイルストレージやデータベースサービスでも起こり得るので、汎用的な教訓として持っておきたいです
まとめ
- FSx for OpenZFSの
MemoryUtilizationが高いのは、多くの場合ZFSのARC(Adaptive Replacement Cache)によるキャッシュ利用が原因で、それ自体は異常ではありません - ARCは読み取りだけでなく書き込んだデータもキャッシュに乗せる一方、上限に達すると古いキャッシュを追い出して頭打ちになるため、データ量に比例して際限なく増え続けるわけではありません(検証では10GiBの書き込みで20%台から67%台に上昇し、20GiBに増やしても66%台とほぼ横ばいでした)
- この挙動はデプロイタイプ(Single-AZ / Multi-AZ)を問わず、ARCを使うOpenZFSであれば共通して起こり得ます
- FSx for OpenZFSは完全マネージド型サービスのため
zfs_arc_maxなどARCの直接チューニングはできません。スループットキャパシティやデプロイタイプの選定、監視設計の工夫といった間接的なアプローチでコントロールする必要があります -
MemoryUtilizationを単独の閾値アラートで監視するのではなく、FileServerCacheHitRatioやCPU・ディスク・ネットワーク系のメトリクスとあわせて判断することが重要です。両者を条件にした複合アラームを組むと、アラート疲れを防ぎながら本当に注意すべき状態を検知しやすくなります
FSx for OpenZFSを導入・検証する際は、MemoryUtilizationの値だけで一喜一憂せず、まずはFileServerCacheHitRatioをあわせて確認してみてください。






