エラーの読み解きブラウザには 502 Bad Gateway や 504 Gateway Timeout が表示されているかもしれません。これらは一般的なエラーですが、本当の原因は Nginx のエラーログ(通常は /var/log/nginx/error.log)に記録されています。そこには、次のような特定のエントリが見つかるはずです。
2023/10/27 14:30:15 [error] 12345#0: *67890 no live upstreams while connecting to upstream, client: 192.168.1.1, server: example.com, request: "GET /api/v1/data HTTP/1.1", upstream: "http://backend_cluster", host: "example.com"
実際に何が起きているのか?このエラーは、Nginx が過保護になっている状態だと考えてください。Nginx はパッシブヘルスチェックシステムを使用してバックエンドサーバーを監視しています。特定の期間(fail_timeout)内にバックエンドが指定回数(max_fails)失敗すると、Nginx はそのサーバーを信頼できないと判断し、一時的にローテーションから外します。Nginx が upstream ブロック内のすべてのサーバーを同時に「ダウン」とマークすると、処理を諦めて「no live upstreams」エラーをスローします。
ステップバイステップのトラブルシューティング### 1. バックエンドが起動しているか確認するまずは基本から確認しましょう。アプリケーション(ポート 3000 の Node.js やソケット経由の PHP-FPM など)が実際に動作していることを確認します。アプリがクラッシュしている場合、Nginx の接続先がなくなります。ss または netstat を使用してポートを確認してください。
# アプリがポート 8080 でリッスンしているか確認
sudo ss -tulpn | grep :8080
サービスが実行されている場合は、Nginx サーバーから直接アクセスを試みてください。これにより、問題が Nginx の設定にあるのか、それともより深いネットワークの問題なのかを判断できます。
curl -I http://127.0.0.1:8080
2. Upstream の制約を緩和するNginx のデフォルト設定は驚くほど厳格です。デフォルトでは max_fails=1 かつ fail_timeout=10s に設定されています。つまり、一度の 504 タイムアウトやわずかな遅延が発生しただけで、Nginx はそのサーバーを 10 秒間遮断します。バックエンドサーバーが 1 台しかない場合、小さな不具合が 1 回起きただけでサイト全体が即座にオフラインになってしまいます。
upstream ブロックをより寛容な設定に更新しましょう。多くの本番環境では、諦める前に数回のリトライを許可するのが安全です。
upstream backend_cluster {
# オプション A: サーバーをダウンとしてマークしない(シングルサーバー構成に最適)
server 127.0.0.1:8080 max_fails=0;
# オプション B: 30秒間に3回の失敗を許容する
# server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
keepalive 32;
}
max_fails=0 に設定するのは、一般的な「クイックフィックス」です。これにより、以前のエラーに関係なく Nginx はバックエンドへの試行を継続します。これは、すべての訪問者に 502 ページを表示するよりも多くの場合において適切な対応です。
3. SELinux とファイアウォールを確認するRHEL、CentOS、Fedora などのディストリビューションでは、SELinux が接続をブロックしている可能性があります。アプリが完全に動作していても、Nginx がネットワークソケットを開く権限を持っていない場合があります。拒否ログを確認してください。
sudo ausearch -m avc -ts recent
Nginx に関連する拒否設定が見つかった場合は、次のコマンドを実行して Nginx がネットワークに接続できるように許可します。
sudo setsebool -P httpd_can_network_connect 1
4. DNS の有効期限に対処するupstream ブロックで backend.internal のようなホスト名を使用していませんか?Nginx は起動時に一度だけこの名前を IP アドレスに解決します。Docker、AWS ALB、または IP が頻繁に変わる動的なクラウド環境を使用している場合、Nginx はすでに存在しない古い IP アドレスに接続しようとしている可能性があります。
これが疑われる場合は、Nginx を再起動して DNS を強制的にリフレッシュしてください。恒久的な解決策としては、proxy_pass で変数を使用するか、設定に resolver を定義します。
修正の適用とテスト設定を調整したら、タイポでサイトをダウンさせないよう、必ず構文を検証してください。
sudo nginx -t
テストに合格したら、現在の接続を切断せずに設定を適用するためにリロードを行います。
sudo systemctl reload nginx
エラーが再発しないか、リアルタイムでログを監視します。
tail -f /var/log/nginx/error.log | grep "no live upstreams"
パフォーマンス向上のためのプロのヒント
- **Keepalive を有効にする:** upstream ブロックに `keepalive 32;` を追加すると、接続が維持されます。これにより、高トラフィック時の CPU 負荷とレイテンシを 10〜15% 削減できます。
- **タイムアウトを調整する:** Nginx はデフォルトでは「せっかち」です。バックエンドが時折 60 秒以上かかる重いリクエストを処理する場合は、プロキシのタイムアウト値を増やしてください。
location / {
proxy_connect_timeout 10s; # 接続を確立するまでの時間
proxy_send_timeout 60s;
proxy_read_timeout 60s; # バックエンドからの応答を待つ時間
proxy_pass http://backend_cluster;
}
バックエンドの応答に数秒の余裕を持たせることで、Nginx が時期尚早にサーバーを「ダウン」と判断するのを防ぐことができます。

