502 Bad Gatewayの原因と対処法 — nginx・Cloudflare・ALB別の現場チェックリスト

502 Bad Gateway とは — 概要

「502 Bad Gateway」は、クライアント(ブラウザなど)から見たときに返されるHTTPステータスコードの一つで、ゲートウェイやプロキシ(リバースプロキシ、ロードバランサ、CDNなど)が上流サーバ(オリジン、バックエンド)から“無効な(あるいは期待できない)レスポンス”を受け取った際に返されます。RFC 7231 の定義では「502 は、ゲートウェイまたはプロキシが上流サーバからの有効なレスポンスを受け取れなかった場合に用いる」と説明されています。

502 と他の5xx系の違い

  • 500 Internal Server Error:オリジン自身の内部エラー。プロキシが介在しない場合でも発生。
  • 502 Bad Gateway:プロキシ/ゲートウェイが上流から無効なレスポンスを受け取った時。
  • 503 Service Unavailable:サービス自体が利用不可(メンテナンスや過負荷など)。
  • 504 Gateway Timeout:プロキシが上流からの応答を規定時間内に受け取れなかった時(タイムアウト)。

主な原因(典型例)

  • 上流(バックエンド)サーバがクラッシュ・落ちている、あるいはアプリケーションが異常終了している。
  • 上流が指定ポートで応答していない(サービス停止、ポート誤設定、コンテナのポートマッピングミスなど)。
  • プロキシと上流間のネットワーク障害(ファイアウォール、セグメント、ルーティングの問題)。
  • プロキシと上流のプロトコル不整合(HTTP/2 と HTTP/1.1 の期待違い、TLS/非TLSのミスマッチ)。
  • 上流が不正な、あるいは期待外の(HTTPヘッダが壊れている、空レスポンス、バイナリデータを返す等)レスポンスを返した。
  • ヘッダサイズやボディサイズの制限超過によりプロキシ側が処理できない。
  • リバースプロキシの設定ミス(upstream の名前解決失敗、ヘルスチェックで死亡判定されている等)。
  • ロードバランサやCDN(例:Cloudflare、AWS ALB)がオリジンと正しく通信できない/TLSハンドシェイクに失敗している。
  • PHP-FPM / FastCGI のプロセス枯渇(pm.max_children 足りない等)/タイムアウト。

サーバ別・環境別に起きやすい事例と対処例

Nginx(リバースプロキシ)

典型的なerror.logメッセージ:

2025/01/01 12:00:00 [error] 100#0: *1234 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 1.2.3.4, server: example.com, request: "GET / HTTP/1.1", upstream: "http://10.0.0.2:8080/", host: "example.com"

原因:上流が接続をリセットした、あるいはコネクションを閉じた。

対処:

  • 上流(10.0.0.2:8080)のログ確認、プロセス稼働確認(systemctl / ps / docker ps / kubectl logs)。
  • nginx の proxy_read_timeout / proxy_connect_timeout を適切に設定。短すぎると切れる。
  • ヘッダサイズ問題なら proxy_buffer_size / proxy_buffers / large_client_header_buffers を調整。
  • upstream name の解決やヘルスチェック設定を確認(no live upstreams の場合は upstream設定を見直す)。

Apache(mod_proxy)

Apache の場合も同様にバックエンドが不正な応答を返すと 502 を返します。error_log を確認し、ProxyPass の設定、KeepAlive、Timeout、mod_proxy_fcgi(FastCGI)の設定を点検してください。

PHP-FPM / FastCGI

  • PHP-FPM がプロセス枯渇すると接続が切れ、nginx が 502 を返すことが多い。pm.max_children やメモリ使用を確認。
  • fastcgi_read_timeout / fastcgi_send_timeout を延長することで一時的に回避できることもあるが、本質は処理遅延やリソース不足の解消が必要。

CDN(Cloudflare 等)・ロードバランサ(ALB/ELB)

Cloudflare のドキュメントにもある通り、502 はオリジンサーバが不正なレスポンスを返すか、Cloudflare とオリジン間で接続できない場合に出ます。ALB の場合はターゲットが HTTP プロトコルの期待と合わない/不正レスポンスを返した際に 502 になることがあります。

対処:

  • 一時的に CDN をバイパスして直接オリジンへリクエスト(DNS を編集、Cloudflare なら「開発モード」や「DNS だけ」に変更)して原因切り分け。
  • ロードバランサのターゲットヘルスチェック、リスナー設定、SSL終端設定を確認。

コンテナ / Kubernetes

  • コンテナのポートマッピング間違い、Pod が CrashLoopBackOff、readinessProbe が失敗していると Ingress/Service が正しいエンドポイントにルーティングできず 502 を返す。
  • kubectl get endpoints / kubectl describe ingress / kubectl logs を使って切り分け。

診断手順(現場で使えるチェックリスト)

  1. まず再現性を確認:ブラウザ、curl で再現。curl でヘッダ確認:
    curl -I -v https://example.com/
  2. プロキシ(nginx/Apache/ALB/CDN)のログを確認。タイムスタンプで該当リクエストを特定。
  3. 上流サーバへ直接リクエスト:IP とポートで curl / telnet / nc を実行して応答確認(HTTP レスポンスヘッダが正しく返るか)。例:
    curl -v http://10.0.0.2:8080/
  4. ネットワーク経路確認:ping, traceroute, telnet ポート確認、ファイアウォールルール、セキュリティグループ。
  5. 上流のプロセス状態、リソース使用(CPU/メモリ)、ログ(アプリケーションログ、systemd/journalctl、docker/k8s のログ)。
  6. プロトコル・TLS 確認:プロキシが HTTP を期待しているのに上流が HTTPS で応答している等のミスマッチがないか。
  7. タイムアウト・バッファ設定の見直し(proxy_read_timeout, fastcgi_read_timeout 等)。
  8. ヘルスチェック・ヘルスエンドポイントの確認(ロードバランサ/オーケストレーションの健康判定)。
  9. 構成変更があればロールバックして影響を確認。最近のデプロイや設定変更が原因になりやすい。

nginx の具体的な設定例(ヒント)

例えばバックエンドが重い処理で応答に時間がかかる場合:

proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffer_size 16k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;

fastcgi を使っている場合:

fastcgi_read_timeout 60s;
fastcgi_buffer_size 16k;
fastcgi_buffers 8 16k;

ただしタイムアウトを無闇に延ばすとリソースが枯渇するので、根本原因(遅い処理やスケーリング不足)を解決することが重要です。

運用での予防と監視

  • ヘルスチェックを適切に設定し、不健康なバックエンドを速やかに切り離す。
  • ロードバランサ・プロキシ側で 502 発生率を監視(ログ解析、アラート設定)。
  • アプリケーションのタイムアウトやリトライ設計を見直し、過負荷で連鎖故障が起きないようにする。
  • リソース監視(CPU・メモリ・スレッド・コネクション数)と自動スケーリングの導入。
  • デプロイ時は段階的ロールアウト、ヘルスチェックの厳格化で不具合を早期検出。

よく見るnginxのエラーメッセージと意味

  • upstream prematurely closed connection while reading response header from upstream:上流がヘッダ読み取り中に接続を閉じた(クラッシュ、タイムアウト、プロセス終了など)。
  • recv() failed (104: Connection reset by peer):上流が接続をリセット。アプリ側の例外やプロセス死、keepalive不整合など。
  • no live upstreams while connecting to upstream:upstream グループに生きているサーバがない(設定不備/ヘルスチェックで全部落ちている)。
  • upstream sent invalid header while reading response header from upstream:上流がHTTPヘッダとして解析できないデータを返した(バイナリ、TLSハンドシェイク、ログ出力が混入等)。

まとめ:対処の優先度と考え方

502 は「プロキシ視点での上流の不正応答」を示すため、まずはプロキシ側のログで該当リクエストを特定し、次に上流へ直接アクセスして本当に正しいHTTPレスポンスが返るかを確認します。順序としては「再現 → プロキシログ確認 → 上流直接確認 → ネットワーク確認 → 設定・リソース確認 → 恒久対応(スケール、設定改善)」が有効です。

実際に使えるコマンド(例)

# curl でヘッダ確認(プロキシ経由):
curl -I -v https://example.com/

# 直接上流へ(IP:PORT を指定):
curl -v http://10.0.0.2:8080/

# ポート到達性確認:
telnet 10.0.0.2 8080
# あるいは
nc -vz 10.0.0.2 8080

# nginx のエラーログを追う:
tail -f /var/log/nginx/error.log

# systemd サービスの状態確認:
systemctl status php-fpm
journalctl -u php-fpm -n 200

# Kubernetes での切り分け:
kubectl get pods,svc,ep -n your-namespace
kubectl logs  -n your-namespace
kubectl describe ingress  -n your-namespace

参考となるポイント(注意点)

  • ブラウザキャッシュやCDNのキャッシュにより一時的に古いエラーが見えることがある。原因切り分け時はキャッシュのバイパスを行う。
  • 502 が頻発する場合は単発対応ではなく、パフォーマンス改善、スケーリング、SOA 設計見直しなどの中長期対策が必要。
  • ログのタイムスタンプを合わせる(プロキシとバックエンドで時刻ズレがあると相関が難しい)。

参考文献