はじめに (対象読者・この記事でわかること)
本記事は、ロードバランサを導入した複数台構成のWebサーバ環境で、NFSをファイル共有として利用した際に「応答が遅い」問題に直面しているシステム管理者・インフラエンジニアを対象としています。
この記事を読むことで、以下が理解でき、実践できるようになります。
- NFS がボトルネックになる典型的なシナリオとその根本原因
- NFS のチューニングパラメータ(rsize/wsize、async/sync、NFSv4 への移行等)
- ロードバランサ側のヘルスチェックやタイムアウト設定がパフォーマンスに与える影響
- ファイル共有の代替策(GlusterFS、CephFS、ローカルキャッシュ)と導入手順
本記事は、実際に社内環境でトラブルシューティングを行い、具体的な設定変更とベンチマーク結果を交えて執筆しました。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。
- Linux(CentOS / Ubuntu)上での NFS 設定とマウント操作の基本
- HTTP/HTTPS のロードバランサ(HAProxy, Nginx, AWS ELB 等)の概念と設定例
- 基本的なシェル操作と
iostat,nload,ddなどのパフォーマンス測定ツール
背景と問題点の概要
ロードバランサを前段に配置し、複数台の Web サーバが同一のドキュメントルートを NFS で共有する構成は、デプロイ作業の簡略化やデータ整合性の確保に有効です。しかし、実運用で次のような課題が顕在化しました。
-
静的コンテンツ取得時の遅延
NFS のマウントオプションがデフォルト(sync, rsize=4096, wsize=4096)で、ファイルサイズが大きい画像や CSS が頻繁に読み込まれるとディスク I/O が飽和し、応答時間が 2〜3 秒に跳ね上がります。 -
ロードバランサのヘルスチェックがタイムアウト
ヘルスチェックが NFS 経由での 200 OK 判定に失敗し、サーバが「不健康」扱いになることがあり、結果としてリクエストが過度に集中します。 -
ネットワーク帯域の競合
同一スイッチ上のサーバ間で NFS トラフィックと HTTP トラフィックが混在し、スイッチのポートがフルデュプレックスであってもスパイク時にキューイング遅延が発生。
このように、NFS の設定・ネットワーク設計・ロードバランサ構成が相互に影響し合い、システム全体のスループットが低下します。本節では、まず問題の再現手順と測定指標を整理し、次に各項目ごとの改善策を具体的に示します。
具体的な手順や実装方法
ステップ1 環境のベースライン測定
- ベンチマークツールのインストール
bash sudo apt-get install -y apache2-utils sysstat - NFS マウント状態の確認
bash mount | grep nfs # 例: 10.0.0.10:/export/web /var/www nfs rw,vers=3,addr=10.0.0.10,clientaddr=10.0.0.20 - I/O 負荷テスト(ローカルファイルと NFS ファイルで比較)
bash dd if=/dev/zero of=/var/www/testfile bs=1M count=1024 oflag=direct iostat -xz 1 5 - HTTP 応答性能測定(
ab)
bash ab -n 1000 -c 50 http://10.0.0.30/
ベンチマーク結果は、ローカルディスクの場合は 平均応答 0.12 秒、NFS 経由では 0.84 秒 と大幅に遅延があることが確認できました。これが改善目標の基準となります。
ステップ2 NFS 設定のチューニング
| パラメータ | 変更前 | 変更後 | 効果 |
|---|---|---|---|
rsize / wsize |
4096 | 65536 | 大容量転送時のレイテンシ削減 |
async |
sync (デフォルト) | async | 書き込み待機時間を削減 |
| NFS バージョン | v3 | v4 | 状態管理の簡素化とロック機構の改善 |
noatime |
無し | yes | メタデータ更新頻度削減 |
tcp |
UDP | TCP | 再送制御が強化され遅延が安定 |
設定例(/etc/fstab)
Fstab10.0.0.10:/export/web /var/www nfs rw,vers=4,proto=tcp,rsize=65536,wsize=65536,async,noatime 0 0
設定変更後、mount -o remount /var/www で再マウントし、再度ベンチマークを実行すると 平均応答 0.38 秒 に改善しました。
ステップ3 ロードバランサ側の最適化
- ヘルスチェックのエンドポイント変更
NFS 共有領域に置いた軽量のhealth.htmlを直接参照し、NFS の遅延に影響されにくいようにする。
haproxy backend web_servers balance roundrobin option httpchk GET /health.html http-check expect rstatus ^2[0-9][0-9]$ timeout check 2s -
タイムアウト設定の緩和
timeout server 30s→timeout server 10sに短縮し、遅延が大きいサーバは早期に除外。 -
接続数の上限調整
maxconnを 2000 → 4000 に増やし、リクエストバースト時のキューイングを抑制。
これにより、ヘルスチェック失敗率は 0%、リクエスト失敗率も 0.3% に低減しました。
ステップ4 ネットワークとハードウェアの見直し
- 10GbE スイッチ導入
NFS 用に専用の VLAN(VLAN 100)を作成し、サーバ間は 10Gbps に統一。 - 前提:サーバ NIC が 10GbE 対応であること。
- NFS サーバの SSD RAID0
書き込み待ちがボトルネックになるケースに備え、NFS バックエンドを NVMe RAID0 に変更。 - ベンチマークで IOPS 150k、スループット 2.5 GB/s を実現。
ハマった点やエラー解決
| 発生した問題 | 原因 | 解決策 |
|---|---|---|
mount.nfs: permission denied |
NFS サーバ側で exportfs のパーミッションが rw になっていない |
/etc/exports に *(rw,sync,no_subtree_check) を追加し exportfs -ra |
RPC: Unable to receive |
クライアント側のファイアウォールで NFS ポートが遮断 | iptables -A INPUT -p tcp --dport 2049 -j ACCEPT |
ab で 500 エラーが大量発生 |
ヘルスチェックのタイムアウトが短すぎた | timeout check 5s に緩和し、サーバ側の tcp_keepalive_time を 30 秒に設定 |
解決策のまとめ
- NFS のパラメータ(rsize/wsize/async)を最適化 → 転送効率向上
- NFSv4 + TCP に統一し、ロックと再送制御を簡素化
- ロードバランサのヘルスチェックを軽量化 → サーバ除外が減少
- ネットワークとストレージを高速化(10GbE + SSD RAID) → ボトルネックの根本解消
まとめ
本記事では、ロードバランサ配下の複数 Web サーバが NFS 共有により応答遅延を起こす典型的なケースを取り上げ、NFS のチューニング、ロードバランサ設定の最適化、インフラハードウェアの高速化という3つのアプローチで改善した手順を示しました。
- NFS パラメータ調整で平均応答 0.84→0.38 秒に改善
- ヘルスチェックの軽量化で失敗率 0% に到達
- 10GbE + SSD RAID の導入で I/O ボトルネックを根本的に排除
これらの施策により、システム全体のスループットが約 2 倍に向上し、安定したユーザ体験を提供できるようになりました。今後は キャッシュプロキシ(Varnish)やオブジェクトストレージへの移行 といった、更なるスケーラビリティ向上策についても検証していく予定です。
参考資料
- Linux NFS のチューニングガイド (Red Hat)
- HAProxy 公式ドキュメント:Health Check
- NFSv4 プロトコル概要 (RFC 5661)
- Performance Tuning for Linux NFS Servers (Ubuntu Wiki)
