Nginx 502 Bad Gatewayエラーの診断と解決方法

Nginx 502 Bad Gatewayエラーに遭遇しましたか?この包括的なガイドでは、問題の診断と解決方法をステップバイステップで解説します。Nginxのエラーログの解釈、アップストリームサーバーの状態の確認、プロキシ設定の誤り、PHP-FPMの問題、リソース枯渇、ファイアウォールによるブロックなどの一般的な原因のトラブルシューティング方法を学びます。実践的な例と段階的な解決策により、根本原因を迅速に特定し、Webサービスを復旧させて、スムーズな運用とダウンタイムの最小化を確保できます。

46 ビュー

Nginx 502 Bad Gatewayエラーの診断と解決方法

Nginxは、強力で人気のあるWebサーバーおよびリバースプロキシであり、静的コンテンツの提供、トラフィックの負荷分散、PHP-FPM、Node.js、Python Gunicorn、Apache Tomcatなどのさまざまなアップストリームアプリケーションサーバーへのリクエスト転送によく使用されます。Nginxがこれらのアップストリームサーバーのいずれかとの通信で問題に遭遇すると、通常は「502 Bad Gateway」エラーで応答します。

この記事では、Nginx 502 Bad Gatewayエラーを理解し、診断し、解決するための包括的で段階的なガイドを提供します。一般的な原因を探り、コマンドラインツールを使用した実践的なトラブルシューティング技術を身につけ、Webサービスを迅速に復旧させるための実用的なソリューションを提供します。システム管理者、開発者、または独自のサーバーを管理しているかにかかわらず、このガイドは、最も一般的なNginxエラーの1つを効果的に解決するのに役立ちます。

Nginx 502 Bad Gatewayエラーの理解

502 Bad Gatewayエラーは、リバースプロキシとして機能するNginxが、アップストリームサーバーから無効な応答を受け取ったことを示します。これは、Nginxがアップストリームサーバーに正常に接続したが、応答がなかった、不完全な応答だった、または理解できない応答だったことを意味します。重要なのは、問題はNginx自体ではなく、Nginxが通信しようとしているサービスにあるということです。

一般的なアップストリームサーバーには次のようなものがあります。

  • PHP-FPM: PHPアプリケーション(例:WordPress、Laravel)用。
  • Gunicorn/uWSGI: Pythonアプリケーション(例:Django、Flask)用。
  • Node.js: JavaScriptアプリケーション用。
  • Apache Tomcat: Javaアプリケーション用。
  • その他のWebサーバー: 特定のコンテンツを提供するApache HTTP Serverなど。

502エラーは、アプリケーションのバックエンドが正しく機能していないか、Nginxからアクセスできないことを示す重要な指標です。

ステップバイステップの診断

502エラーを解決する鍵は、体系的な診断です。最も可能性の高い原因から始め、徐々に調査を進めてください。

1. まずNginxエラーログを確認する

Nginxのエラーログは情報の主要な情報源です。多くの場合、Nginxがアップストリームサーバーと通信できなかった理由に関する具体的な詳細が含まれています。

  • 場所: 通常、/var/log/nginx/error.logにあります。
  • コマンド: エラーを再現しようとするときに、ログをリアルタイムで監視するには tail -f を使用します。
tail -f /var/log/nginx/error.log

確認すべきこと:
* connect() failed (111: Connection refused): アップストリームサーバーが指定されたアドレス/ポートでリッスンしていないか、ファイアウォールが接続をブロックしていることを示します。
* upstream timed out: アップストリームサーバーの応答に時間がかかりすぎました。
* upstream prematurely closed connection: アップストリームサーバーが完全な応答を送信する前に接続を閉じました。
* no live upstreams while connecting to upstream: Nginxは設定された利用可能なアップストリームサーバーを見つけられませんでした。

2. アップストリームサーバーのステータスを確認する

Nginxエラーログから手がかりを得たら、アップストリームアプリケーションサーバーのステータスを確認します。

  • PHP-FPMの場合:

    bash systemctl status phpX.X-fpm # X.X を PHPバージョンに置き換えてください。例: php7.4-fpm sudo service phpX.X-fpm status

  • Node.js/Python/その他のカスタムアプリの場合:
    プロセスが実行されているか確認します。

    bash ps aux | grep node ps aux | grep gunicorn
    PM2(Node.js)やSupervisor(汎用)などのプロセス管理ツールを使用している場合は、そのステータスを確認します。

    bash pm2 status sudo supervisorctl status

サービスが実行されていない場合は、起動してみてください。エラーについては、それ自体のログを確認してください。

systemctl start phpX.X-fpm
# または
sudo service phpX.X-fpm start

3. アップストリームへのネットワーク接続を確認する

Nginxが設定されたポートまたはソケットパスでアップストリームサーバーに到達できることを確認します。

  • TCP/IP接続の場合(例: 127.0.0.1:8000:
    Nginxサーバーからポート接続をテストするには、telnetまたはnc(netcat)を使用します。

    bash telnet 127.0.0.1 8000 nc -vz 127.0.0.1 8000
    接続に成功すると Connected to 127.0.0.1. または succeeded! が表示されます。ハングしたり Connection refused が表示されたりした場合は、アップストリームサービスがリッスンしていないか、ファイアウォールがブロックしています。

  • Unixソケットの場合(例: unix:/run/php/phpX.X-fpm.sock:
    ソケットファイルが存在し、正しい権限を持っていることを確認します。

    bash ls -l /run/php/phpX.X-fpm.sock
    Nginxはこのソケットファイルに対して読み取り/書き込み権限を持っている必要があります。Nginxユーザー(例: www-data)は、ソケットを所有するグループ(例: www-dataまたはphp-fpm)のメンバーである必要があります。

一般的な原因と解決策

診断手順に基づき、502エラーの最も一般的な原因とそれらを解決する方法を以下に示します。

1. アップストリームサーバーが実行されていないかクラッシュした

原因: Nginxがプロキシしようとしているアプリケーション(例: PHP-FPM、Gunicorn、Node.jsアプリ)が実行されていないか、クラッシュしています。

解決策: アップストリームサービスを起動または再起動します。

# PHP-FPMの例
systemctl start phpX.X-fpm
# すでに実行中でクラッシュが疑われる場合は、再起動します:
systemctl restart phpX.X-fpm

# カスタムアプリケーションの場合は、それらの特定の開始/再起動コマンドを使用します

ヒント: アップストリームサービスがシステム起動時に自動的に開始するように設定されていることを確認します。systemdサービスの場合は、systemctl enable phpX.X-fpmを使用します。

2. アップストリームサーバーの過負荷 / リソース枯渇

原因: アップストリームサーバーが過負荷になり、メモリ、CPUが不足したり、プロセス制限に達したりして、応答しなくなったり、新しい接続を拒否したりします。

症状: Nginxエラーログには、特に負荷がかかっているときに、断続的に connection refused または upstream timed out が表示されることがあります。システム監視ツール(tophtopfree -h)は高いリソース使用率を示します。

解決策:

  • PHP-FPMの場合: 設定ファイル(例: /etc/php/X.X/fpm/pool.d/www.conf)でPHP-FPMプール設定を調整します。

    • pm.max_children: 同時にアクティブにできる子プロセスの最大数。
    • pm.start_servers: 起動時に作成される子プロセスの数。
    • pm.min_spare_serverspm.max_spare_servers: アイドル状態のプロセスをいくつ保持するかを制御します。

    ini ; 動的プロセス管理の例 pm = dynamic pm.max_children = 50 pm.start_servers = 10 pm.min_spare_servers = 5 pm.max_spare_servers = 20
    * スクリプトがメモリを使い果たしている場合は、php.inimemory_limitを増やします。
    * その他のアプリケーションの場合: 可能であれば、ワーカープロセスの数、スレッド数を増やしたり、より多くのメモリを割り当てたりします。アプリケーション固有のメトリクスを監視します。
    * Nginxタイムアウト: Nginx設定で proxy_connect_timeoutproxy_send_timeoutproxy_read_timeout ディレクティブを増やしますが、これはバックエンドが実際に苦労している場合、エラーを遅延させるだけであることを理解してください。

    nginx http { ... proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; ... }

3. Nginxでのアップストリーム設定の誤り

原因: Nginxがアップストリームサーバーの誤ったIPアドレス、ポート、またはUnixソケットパスに接続するように設定されています。

症状: リクエスト直後にNginxエラーログに connect() failed (111: Connection refused) が表示されます。

解決策: Nginxサーバーブロック設定(/etc/nginx/sites-available/your_site.conf)を注意深く確認します。

  • HTTP/HTTPSアップストリームの場合:

    nginx location /app { proxy_pass http://127.0.0.1:8000; # IPとポートが正しいことを確認してください proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }

  • Unixソケット経由のPHP-FPMの場合:

    nginx location ~ \.php$ { fastcgi_pass unix:/run/php/phpX.X-fpm.sock; # このパスがPHP-FPM設定と正確に一致するか確認してください fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }

  • TCP/IP経由のPHP-FPMの場合:

    nginx location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; # IPとポートを確認してください fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }

変更を加えた後は、常にNginxの設定をテストし、Nginxをリロード/再起動します。

nginx -t
systemctl reload nginx # -t が必要性を示している場合は再起動します

4. PHP-FPM request_terminate_timeout の超過

原因: PHPスクリプトの実行時間がPHP-FPMの request_terminate_timeout 設定よりも長いためです。Nginxは応答を待ちますが、PHP-FPMはスクリプトを終了させ、Nginxは不完全な応答を受け取ることになります。

症状: Nginxエラーログに upstream timed out または script timed out が表示されることがあります。PHP-FPMログには child XX exited on signal 9 (SIGKILL) が表示されることがあります。

解決策:
* request_terminate_timeout を増やす: PHP-FPMプール設定(www.conf)で、このディレクティブを見つけて調整します。0に設定するとタイムアウトが無効になりますが、長時間実行されるスクリプトはリソースをハングさせる可能性があるため、一般的には推奨されません。

```ini
request_terminate_timeout = 300 # 5分(300秒)に増やす
```
  • Nginxの fastcgi_read_timeout を増やす: このNginxタイムアウトは、request_terminate_timeout以上である必要があります。

    nginx location ~ \.php$ { ... fastcgi_read_timeout 300s; # PHP-FPMの request_terminate_timeout 以上である必要があります ... }

警告: タイムアウトを増やすことで502エラーを解決できる場合がありますが、根本的なパフォーマンスの問題を隠してしまう可能性があります。最善の長期的な解決策は、遅いPHPスクリプトを最適化することです。

5. ファイアウォール問題

原因: ファイアウォール(Nginxサーバーまたはアップストリームサーバー自体(別々の場合)のいずれか)が、アップストリームポートまたはソケットへの接続をブロックしています。

解決策:
* ファイアウォールステータスを確認する:

```bash
sudo ufw status # UFW(Ubuntu/Debian)の場合
sudo firewall-cmd --list-all # firewalld(CentOS/RHEL)の場合
sudo iptables -L # iptablesの場合
```
  • 必要なポートを開く: Nginxがアップストリームに接続するために使用するポート(例: TCP/IP経由のPHP-FPMの場合は9000)が開いていることを確認します。

    bash sudo ufw allow from 127.0.0.1 to any port 9000 # ローカルホストが9000に接続できるようにする sudo firewall-cmd --permanent --add-port=9000/tcp # firewalldの場合 sudo firewall-cmd --reload
    * テスト目的で、制御された環境でのみファイアウォールを一時的に無効にし、その後再度有効にして正しく設定します。

6. SELinuxまたはAppArmorの干渉

原因: SELinux(RHEL/CentOS)やAppArmor(Ubuntu/Debian)などのセキュリティ強化機能により、ファイル権限やファイアウォールが正しく設定されていても、Nginxがアップストリームソケットにアクセスしたり、ネットワーク接続を行ったりすることが妨げられる可能性があります。

症状: ログに permission denied などのメッセージが表示されることがあります。特に /var/log/audit/audit.log(SELinuxの場合)に表示されます。

解決策:
* audit.logを確認する:

```bash
sudo grep nginx /var/log/audit/audit.log
```
  • SELinuxを一時的にパーミッシブモードに設定する: sudo setenforce 0。エラーが解消された場合、SELinuxが原因です。その後、適切なSELinuxポリシー(例: audit2allow)を生成して適用する必要があります。強制モードに戻すことを忘れないでください(sudo setenforce 1)。
  • AppArmorステータスを確認する: sudo aa-status。AppArmorがアクティブな場合、Nginxプロファイルを調整する必要があるかもしれません。

7. 大きなリクエスト/レスポンスボディ(プロキシバッファリング)

原因: Nginxのデフォルトのプロキシバッファリング設定が、非常に大きなリクエストまたはレスポンスボディに対して小さすぎると、接続が早期に閉じられる可能性があります。

症状: Nginxエラーログに upstream prematurely closed connection while reading response header from upstream または upstream prematurely closed connection while reading response body from upstream が表示されることがあります。

解決策: httpserver、またはlocationブロックでNginxプロキシバッファリングディレクティブを調整します。

http {
    ...
    proxy_buffer_size   128k; # レスポンスの最初の部分のバッファサイズ
    proxy_buffers   4 256k; # 残りのレスポンスのバッファの数とサイズ
    proxy_busy_buffers_size   256k; # ビジーバッファの最大サイズ
    proxy_temp_file_write_size 256k; # バッファリングがオーバーフローした場合の一時ファイルへの書き込みサイズ
    ...
}

注意: これらの設定はより多くのメモリを消費します。サーバーのリソースとアプリケーションのレスポンスの典型的なサイズに基づいて、慎重に調整してください。

一般的なトラブルシューティングのヒント

  • 関連するすべてのログを確認する: Nginxエラーログに加えて、Nginxアクセスログ、アップストリームアプリケーションログ(PHP-FPM、Gunicorn、Node.jsアプリのログ)、およびシステムログ(/var/log/syslogdmesg)も確認します。
  • Nginxを再起動する: 設定変更後は、必ずNginxを再起動して変更を有効にします: systemctl restart nginx
  • Nginx設定をテストする: 再起動する前に、Nginx設定の構文を検証します: nginx -t
  • 問題を分離する: Nginxをバイパスして、アップストリームアプリケーションに直接アクセスしてみてください。たとえば、Node.jsアプリが localhost:3000 で実行されている場合、サーバーのコマンドラインから curl http://localhost:3000 を使用します。これも失敗する場合、問題は明らかにNginxではなくアプリケーションにあります。
  • ディスク容量を確認する: ディスクがいっぱいになると、アプリケーションが一時ファイルやログを書き込めなくなり、クラッシュや障害につながる可能性があります。ディスク使用量を確認するには df -h を使用します。

結論

Nginx 502 Bad Gatewayエラーは一般的ですが、ほぼ常にNginx自体ではなく、Nginxが接続しようとしているバックエンドアプリケーションの問題を示しています。Nginxエラーログを体系的に確認し、アップストリームサーバーのステータスを確認し、ネットワーク接続を確認し、次に一般的な設定またはリソースの問題に対処することで、これらの問題を効果的に診断および解決できます。

トラブルシューティングは、最も基本的なチェックから始め、徐々に深く掘り下げて、体系的にアプローチすることを忘れないでください。変更を加えた後は常にNginxの設定をテストし、アプリケーションとサーバーの正常性を監視して、将来の発生を防ぎます。これらの戦略があれば、サービスをスムーズに稼働させ続けるための十分な装備が整っているはずです。