Nginxログ分析をマスターして効率的なトラブルシューティングを実現する
Nginxは、静的コンテンツの提供から複雑なリバースプロキシ操作まで、あらゆるものを処理する数百万のWebサービスにとって重要なエントリーポイントとして機能します。パフォーマンスが低下したり、サービスが失敗したりした場合、Nginxが生成するログは最も重要な診断ツールとなります。ログは、すべてのリクエストとすべての内部運用上の問題の正確な履歴を提供します。
Nginxログ分析をマスターすることは、単にファイルを閲覧するだけでなく、ログフォーマットを理解し、重要な変数を特定し、効率的なツールを使用してイベントを相関させ、根本原因を特定することです。この包括的なガイドでは、502エラー、パフォーマンスのボトルネック、および疑わしいトラフィックパターンなどの問題を迅速に診断するために、Nginxログの解釈方法を説明します。
1. Nginxログの基本:アクセスログとエラーログ
Nginxは2つの異なる種類のログを維持しており、それぞれが重要で独立した機能を果たしています。
1.1 アクセスログ (access.log)
アクセスログは、Nginxが処理するすべてのリクエストの詳細を記録します。ユーザー行動の理解、トラフィックフローの監視、および応答時間の評価に不可欠です。
デフォルトの場所: 通常 /var/log/nginx/access.log
目的: クライアントインタラクション(成功したリクエスト、クライアントエラー(4xx))の追跡。
1.2 エラーログ (error.log)
エラーログは、Nginxの処理ライフサイクル中に発生する内部の問題、運用上の障害、および通信問題を追跡します。このログは、バックエンド接続の問題やサーバー設定エラーのトラブルシューティングにおける決定的な情報源です。
デフォルトの場所: 通常 /var/log/nginx/error.log
目的: サーバーサイドのエラー、警告、およびシステムイベント(5xxエラー、設定ファイル解析の失敗)の追跡。
エラーログの深刻度レベル
Nginxは8つの深刻度レベルを使用します。トラブルシューティングの際は、通常 error レベル以上から確認を開始します。深刻度レベルは error_log ディレクティブを使用して設定します。
# 最小深刻度レベルを 'warn' に設定
error_log /var/log/nginx/error.log warn;
| レベル | 説明 | 優先度 |
|---|---|---|
| crit | 重大な状態(例:システム障害) | 最も高い |
| error | リクエストの提供を妨げたエラーが発生 | 高い |
| warn | 予期しないことが発生したが、操作は継続 | 中程度 |
| notice | 通常だが重要な状態(例:サーバー再起動) | 低い |
| info | 情報メッセージ | 最も低い |
2. パフォーマンス分析のためにアクセスログをカスタマイズする
combined と呼ばれるデフォルトのNginxアクセスログフォーマットは便利ですが、重要なパフォーマンスタイミング変数が不足しています。スローネスを効果的にトラブルシューティングするには、Nginxがリクエストの処理に費やした時間とアップストリームサーバーが要した時間をキャプチャするカスタムフォーマットを定義する必要があります。
2.1 パフォーマンスログフォーマットの定義
log_format ディレクティブ(通常 nginx.conf で定義)を使用して、例えば timing_log というカスタムフォーマットを作成します。
log_format timing_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
server {
listen 80;
server_name example.com;
# カスタムフォーマットをここに適用
access_log /var/log/nginx/timing_access.log timing_log;
# ... 設定の残りの部分
}
| 変数 | 説明 | トラブルシューティング値 |
|---|---|---|
| $request_time | 最初のバイト受信から最後のバイト送信までにかかった合計時間。 | 値が大きい場合は、ネットワーク遅延、Nginx遅延、またはバックエンド遅延を示します。 |
| $upstream_response_time | アップストリームサーバー(例:アプリケーションサーバー)からの応答を待機して費やされた時間。 | ここで値が大きい場合は、バックエンドアプリケーションがボトルネックであることを示します。 |
| $status | クライアントに返されたHTTPステータスコード。 | エラー(4xx、5xx)のフィルタリングに不可欠です。 |
ベストプラクティス: JSONログフォーマットの使用を検討してください。手動で少し読みにくいですが、JSONログは中央集権的なログ管理システム(ELKスタックやSplunkなど)が解析および分析するのが容易であり、トラブルシューティング速度を大幅に向上させます。
3. アクセスログエントリの解釈
カスタマイズされたフォーマットを使用した典型的なエントリは、次のようになります(末尾にタイミング値が追加されています)。
192.168.1.10 - - [10/May/2024:14:30:05 +0000] "GET /api/data HTTP/1.1" 200 450 "-" "Mozilla/5.0" 0.534 0.528
診断:
- ステータスコード (200): 成功。
- リクエスト時間 (0.534秒): 合計で0.5秒かかりました。
- アップストリーム時間 (0.528秒): ほとんどすべての時間がバックエンドアプリケーションの待機に費やされました(Nginxオーバーヘッドで
0.534 - 0.528 = 0.006秒)。
結論: バックエンドアプリケーションが500msの遅延の原因です。Nginxの設定自体は効率的です。
ステータスコードを使用したトラブルシューティング
| ステータスコード範囲 | 意味 | 通常の対応/ログソース |
|---|---|---|
| 4xx(クライアントエラー) | クライアントが無効または不正なリクエストを送信しました。 | アクセスログで高頻度を確認してください。404 Not Found(ファイルが見つからない)または403 Forbidden(権限の問題)を確認します。 |
| 5xx(サーバーエラー) | Nginxまたはアップストリームサーバーが有効なリクエストを処理できませんでした。 | 対応するエントリをエラーログで即座に確認してください。 |
| 502 Bad Gateway | Nginxがアップストリームアプリケーションからの応答を取得できませんでした。 | エラーログに詳細が表示されます(Connection Refused、Timeout)。 |
| 504 Gateway Timeout | アップストリームサーバーが、設定されたプロキシ制限時間内に応答するのに時間がかかりすぎました。 | エラーログにタイムアウト警告が表示されます。proxy_read_timeout を調整してください。 |
4. エラーログで重大な問題を診断する
リクエストが5xxエラーになった場合、アクセスログはエラーが発生したことを伝えるだけです。エラーログは、なぜ発生したかを伝えます。
ケーススタディ:502 Bad Gateway
502エラーは、Nginxをリバースプロキシとして使用する際によく発生する問題の1つです。これはほとんどの場合、バックエンドアプリケーションがダウンしている、過負荷になっている、または到達不能であることを示しています。
エラーログでこれらの特定のメッセージを探してください。
4.1 Connection Refused(バックエンドダウン)
これは、Nginxがバックエンドポートに接続しようとしたが、何もリッスンしていなかったことを示しており、アプリケーションサーバー(PHP-FPM、Gunicornなど)が停止しているか、正しく設定されていないことを意味します。
2024/05/10 14:35:10 [error] 12345#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.10, server: example.com, request: "GET /test"
- 対応: バックエンドアプリケーションサーバーを再起動するか、その設定(ポート/ソケット設定)を確認してください。
4.2 Upstream Prematurely Closed Connection(バックエンドクラッシュ)
これは、Nginxが接続を確立したが、バックエンドサーバーが完全なHTTP応答を送信する前に接続を終了した場合に発生します。これは、アプリケーションコードの致命的なエラーまたはクラッシュを示唆していることがよくあります。
2024/05/10 14:38:22 [error] 12345#0: *2 upstream prematurely closed connection while reading response header from upstream, client: 192.168.1.10, server: example.com, request: "POST /submit"
- 対応: 特定の致命的なエラーについて、アプリケーションサーバーネイティブのエラーログ(PHP-FPMログ、Node.jsログなど)を確認してください。
警告: Nginxが起動時に設定ファイルを読み取れない場合、エラーは通常、設定された
error.logの場所ではなく、標準エラー出力またはブートストラップログファイルに直接ダンプされます。Nginxが起動に失敗した場合は、常にjournalctl -xeまたはシステムログを確認してください。
5. ログ分析のための実用的なシェルコマンド
本番環境では堅牢なログ監視システムが推奨されますが、Linuxコマンドラインは迅速でリアルタイムなトラブルシューティングのための強力なツールを提供します。
5.1 リアルタイム監視
リクエストが着信するにつれてログを監視します(修正をデプロイした後や新機能をテストする際に特に役立ちます)。
tail -f /var/log/nginx/access.log
# または、エラーのみの場合
tail -f /var/log/nginx/error.log
5.2 エラーのフィルタリングとカウント
過去1時間または1日の最も頻繁な5xxエラーをすばやく見つけてカウントします。
# すべての5xxリクエストを検索
grep '" 50[0-9] ' /var/log/nginx/access.log | less
# 5xxエラーの分布をカウント(例:502と504の数)
grep '" 50[0-9] ' /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c | sort -nr
説明: awk '{print $9}' はHTTPステータスコードを分離します(ステータスが9番目のフィールドであるデフォルトまたは結合ログフォーマットを想定)。
5.3 低速なリクエストの特定(カスタムログフォーマットが必要)
timing_log フォーマット($request_time が最後から2番目のフィールド、または例では16番目のフィールド)を実装している場合:
# 10個の最も遅いリクエストを検索(例:1秒以上かかったリクエスト)
awk '($16 > 1.0) {print $16, $7}' /var/log/nginx/timing_access.log | sort -nr | head -10
説明: このコマンドは、1.0秒以上かかったリクエストについて、リクエスト時間とURI($7)を表示し、降順にソートします。
5.4 最もリクエストしているIPアドレスの特定
DoS攻撃の試み、トラフィックサージ、または疑わしいアクティビティの特定に役立ちます。
# リクエストを行っている上位20個のIPを検索
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20
結論
Nginxログは、高可用性とパフォーマンスを維持するための主要な診断リソースです。デフォルトのログフォーマットを超えて、$request_timeや$upstream_response_timeのようなパフォーマンスメトリックを統合することで、単純なレコードを強力なトラブルシューティングデータに変換できます。サーバーの問題を迅速かつ効果的に解決するために、アクセスログ(何が起こったか)での発見とエラーログ(なぜ起こったか)の詳細を常に相関させてください。