はじめに (対象読者・この記事でわかること)

本記事は、ロードバランサを導入した複数台構成の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 で共有する構成は、デプロイ作業の簡略化やデータ整合性の確保に有効です。しかし、実運用で次のような課題が顕在化しました。

  1. 静的コンテンツ取得時の遅延
    NFS のマウントオプションがデフォルト(sync, rsize=4096, wsize=4096)で、ファイルサイズが大きい画像や CSS が頻繁に読み込まれるとディスク I/O が飽和し、応答時間が 2〜3 秒に跳ね上がります。

  2. ロードバランサのヘルスチェックがタイムアウト
    ヘルスチェックが NFS 経由での 200 OK 判定に失敗し、サーバが「不健康」扱いになることがあり、結果としてリクエストが過度に集中します。

  3. ネットワーク帯域の競合
    同一スイッチ上のサーバ間で NFS トラフィックと HTTP トラフィックが混在し、スイッチのポートがフルデュプレックスであってもスパイク時にキューイング遅延が発生。

このように、NFS の設定・ネットワーク設計・ロードバランサ構成が相互に影響し合い、システム全体のスループットが低下します。本節では、まず問題の再現手順と測定指標を整理し、次に各項目ごとの改善策を具体的に示します。

具体的な手順や実装方法

ステップ1 環境のベースライン測定

  1. ベンチマークツールのインストール
    bash sudo apt-get install -y apache2-utils sysstat
  2. 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
  3. I/O 負荷テスト(ローカルファイルと NFS ファイルで比較)
    bash dd if=/dev/zero of=/var/www/testfile bs=1M count=1024 oflag=direct iostat -xz 1 5
  4. 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)

Fstab
10.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 ロードバランサ側の最適化

  1. ヘルスチェックのエンドポイント変更
    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
  2. タイムアウト設定の緩和
    timeout server 30stimeout server 10s に短縮し、遅延が大きいサーバは早期に除外。

  3. 接続数の上限調整
    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)やオブジェクトストレージへの移行 といった、更なるスケーラビリティ向上策についても検証していく予定です。

参考資料