HTTP(S) 負荷分散のトラブルシューティング

このガイドでは、Google Cloud 外部 HTTP(S) ロードバランサの構成に関する問題のトラブルシューティングについて説明します。

概要

このガイドで説明する問題の種類は次のとおりです。

  • バックエンドの分散モードに互換性がない場合の設定の問題
  • 一般的な接続に関する問題
  • バックエンドへの HTTP/2 接続に関する問題
  • 外部バックエンドとインターネット NEG に関する問題
  • サーバーレス NEG に関する問題

始める前に

問題を調べる前に、次のページをよくお読みください。

一般的な接続について:

ロギングとモニタリングの場合:

バックエンドの負荷分散モードに互換性がない

ロードバランサを作成するときに、次のエラーが表示される場合があります。

Validation failed for instance group INSTANCE_GROUP:

backend services 1 and 2 point to the same instance group
but the backends have incompatible balancing_mode. Values should be the same.

これは、2 つの異なるロードバランサで同じバックエンドを使用しようとしたが、互換性のある負荷分散モードがバックエンドにない場合に発生します。

詳しくは以下をご覧ください。

接続に関する一般的な問題のトラブルシューティング

原因不明の 502 エラー

ロードバランサの構成を完了してから 502 エラーが数分以上続く場合は、次のいずれかの可能性があります。

502 レスポンスのトラブルシューティングを実施するには、次の手順を行います。

  1. ヘルスチェック トラフィックがバックエンド VM に到達していることを確認します。これを行うには、ヘルスチェックのロギングを有効にし、成功したログエントリを検索します。
  2. 502 レスポンスがロードバランサによって処理されているかどうか、またはバックエンドから受信しているかどうかをチェックします。次の手順を行います。

    1. Cloud Logging を使用してロードバランサのログを表示します。502 レスポンス コードのみを検索するクエリを作成できます。
    2. statusDetails フィールドの値を確認します。

      • 条件 statusDetails成功メッセージ(例: response_sent_by_backend)を返す場合は、それがバックエンドの HTTP 502 レスポンスを処理しているバックエンドです。バックエンドでログを確認し、バックエンドで実行されているサービスに応じてさらにトラブルシューティングを行います。
      • statusDetailsエラー メッセージを返す場合、502 レスポンスに関連する一般的なエラーについては、次の解決策をご覧ください。
      statusDetail エラー メッセージ 考えられる原因と解決策
      failed_to_connect_to_backend

      ロードバランサが、バックエンドとの接続を確立できなかった。これは、バックエンドで実行されているサービスが、バックエンド サービスで定義されたポートをリッスンしていないことを示している可能性があります。

      推奨:

      • サービスポートを使用するようにヘルスチェックのポートを設定します。これにより、実際のトラフィックを処理できるようになる前に、バックエンドが異常な状態であることを判断できます。
      • 次のコマンドを使用して、バックエンド サービスの名前付きポートでサービスが実行されていることを確認します。
        
        $ netstat -tnl | grep PORT
      failed_to_pick_backend

      ロードバランサがバックエンドを選択できなかった。これは、すべてのバックエンドが異常な状態であることを示している可能性があります。ヘルスチェックに正しいファイアウォール ルールを構成していることを確認します。

      backend_connection_closed_before_data_sent_to_client バックエンドは、レスポンスがクライアントにプロキシされる前に、予期せずロードバランサへの接続を閉じました。これは、ロードバランサが別のエンティティにトラフィックを送信している場合に発生します。他のエンティティは、ロードバランサのタイムアウトよりも短い TCP タイムアウトが設定されたサードパーティ ロードバランサであることが考えられます。詳細については、タイムアウトと再試行をご覧ください。
      backend_timeout バックエンドの応答に過度に長い時間を要した。バックエンド サービスのタイムアウトが過剰に低い値に設定されているため、指定したサービスが応答していない可能性があります。バックエンド サービスのタイムアウト値を引き上げることを検討するか、サービスが応答するのに非常に長い時間を要している理由を調査してください。

負荷分散されたトラフィックに元のクライアントのソースアドレスが含まれていない

ロードバランサからインスタンスへのトラフィックは、130.211.0.0/2235.191.0.0/16 の範囲の IP アドレスを持っています。負荷分散インスタンスのログを見ても、元のクライアントの送信元アドレスは記録されていません。この範囲の送信元アドレスが記録されます。

自分の Cloud Storage バケットでオブジェクトを表示すると権限エラーが発生する

負荷分散を通じてオブジェクトを提供するには、Cloud Storage オブジェクトが一般公開されている必要があります。一般読み取り可能になるように、提供するオブジェクトの権限を更新してください。

URL から予期した Cloud Storage オブジェクトが提供されない

提供される Cloud Storage オブジェクトは、URL マップとリクエストした URL に基づいて決まります。URL マップでリクエストパスがバックエンド バケットにマッピングしている場合、URL マップで指定されている Cloud Storage バケットにリクエストのフルパスが追加され、Cloud Storage オブジェクトが決まります。

たとえば、/static/*gs://[EXAMPLE_BUCKET] にマッピングしている場合、https://<GCLB IP or Host>/static/path/to/content.jpg へのリクエストにより gs://[EXAMPLE_BUCKET]/static/path/to/content.jpg の処理が試みられます。そのオブジェクトが存在しない場合は、オブジェクトの代わりに次のエラー メッセージが返されます。


NoSuchKey
The specified key does not exist.

圧縮が機能しない

HTTP(S) 負荷分散ではレスポンスそのものは圧縮や解凍はされませんが、gzipDEFLATE などのツールを使用して圧縮されたバックエンド サービスで生成されたレスポンスを処理させることはできます。

HTTP(S) 負荷分散で配信されるレスポンスが圧縮されるべきであるものの、圧縮されていない場合は、レスポンスの圧縮がインスタンス上のウェブサーバー ソフトウェアで実行されていることを確認します。デフォルトでは、一部のウェブサーバー ソフトウェアは、ヘッダー Via を含むリクエストの圧縮を自動的に無効にします。このヘッダーはリクエストがプロキシによって転送されたことを示します。HTTP(S) 負荷分散はプロキシであるため、HTTP の仕様の要求に従って Via ヘッダーがリクエストごとに追加されます。圧縮を有効にするには、ウェブサーバーのデフォルトの構成を変更し、リクエストに Via ヘッダーがある場合でもレスポンスを圧縮するように設定します。

外部 HTTP(S) ロードバランサ経由でプロキシ送信された圧縮レスポンスを処理するように nginx バックエンドを構成するには:

外部 HTTP(S) ロードバランサ経由でプロキシ送信された圧縮レスポンスを処理するように Apache バックエンドを構成するには:

HTTP 408 エラーを解決する

HTTP トラフィックの場合、クライアントがリクエストの送信を完了できる最大時間は、バックエンド サービス タイムアウトと同じです。HTTP 408 レスポンスが jsonPayload.statusDetail client_timed_out で表示されている場合は、クライアントからのリクエストがプロキシされている間、またはバックエンドからのレスポンスがプロキシされた間に、進捗がなかったことを意味します。問題の原因がクライアントのパフォーマンスの問題である場合は、バックエンド サービス タイムアウトを増やすことでこの問題を解決できます。

バックエンドに接続する HTTP/2 に関する問題のトラブルシューティング

フィールド resource.loadBalancingScheme の値が無効: 'EXTERNAL'

この問題は、グローバル オプションを選択せずにバックエンド サービスを作成した場合に発生します。次のように gcloud コマンドを発行した場合、リージョンを指定するか、ロードバランサをグローバルとして指定するように求めるメッセージが表示されます。

gcloud beta compute backend-services create service-test \
    --health-checks=hc-test \
    --project=test1 \
    --protocol=http2

次のバックエンド サービスの場合:

- [service-test] choose a region or global:
[1] global
[2] region: [REGION_A_NAME]
[3] region: [REGION_B_NAME]
....
Please enter your numeric choice:

HTTP(S) ロードバランサの場合、バックエンド サービスはグローバルである必要があります。オプション 1 を選択するか、gcloud コマンドを --global オプションで発行してください。

gcloud beta compute backend-services create service-test \
    --health-checks=hc-test \
    --project=test \
    --protocol=http2 \
    --global

原因不明の 502 エラー

バックエンド インスタンスが正常であり、HTTP/2 プロトコルをサポートしていることを確認します。これを確認するには、HTTP/2 を使用してバックエンド インスタンスへの接続をテストします。VM が HTTP/2 仕様準拠の暗号スイートを使用していることを確認します。たとえば、特定の TLS 1.2 暗号スイートは HTTP/2 では使用できません。TLS 1.2 暗号スイートのブラックリストをご覧ください。

VM が HTTP/2 プロトコルを使用していることを確認したら、ファイアウォールの設定でヘルスチェッカーとロードバランサが通過できることを確認します。

ファイアウォールの設定に問題がない場合は、VM の正しいポートに接続するようにロードバランサを構成します。

外部バックエンドとインターネット NEG に関する問題のトラブルシューティング

問題を調べる前に、次のページをよくお読みください。

トラフィックがエンドポイントに到達しない

サービスを構成すると、次の場合に、外部 HTTP(S) ロードバランサを介して新しいエンドポイントに到達できます。

  • エンドポイントは、インターネット NEG に接続されている。
  • 関連付けられた FQDN は、DNS で正常に解決できる(FQDN エンドポイント タイプを使用している場合)。
  • エンドポイントには、インターネット経由でアクセスできる。

トラフィックがエンドポイントに到達できず、HTTP(S) で 502 エラーコードが生成される場合は、次の点を確認してください。

  • dig や nslookup などのツールを使用して、_cloud-eoips.googleusercontent.com の DNS TXT レコードのクエリを実行します。CIDR を書き止め(ip4: の後)、ファイアウォールまたはクラウドのアクセス制御リスト(ACL)でこれらの範囲が許可されていることを確認します。

外部バックエンドを構成した後、外部バックエンドへのリクエストが 5xx エラーで失敗する

  • Logging を確認します。
  • 外部バックエンドの正しい IP:Port または FQDN:Port でネットワーク エンドポイント グループが構成されていることを確認します。
  • FQDN を使用している場合は、Google Public DNS で解決できることを確認してください。FQDN がこれらの手順またはウェブ インターフェースを直接使用して Google Public DNS を介して解決できることを確認できます。
  • 外部 IP でのみ HTTP(S) ロードバランサにアクセスし、送信元ウェブサーバーがホスト名を想定している場合は、カスタムのリクエスト ヘッダーを構成することにより、有効な HTTP ホストヘッダーをバックエンドに送信していることを確認します。
  • HTTPS または HTTP2 を介するバックエンドへの通信(バックエンド サービスの protocol フィールドで設定)が INTERNET_FQDN_PORT 外部バックエンドのエンドポイントとして構成されている場合は、送信元が有効な TLS(SSL)証明書を示し、構成された FQDN が証明書の SAN(サブジェクト代替名)リスト内の SAN と一致していることを確認します。有効な証明書とは、パブリック認証局によって署名され、有効期限が切れていないものと定義されています。
  • INTERNET_FQDN_PORT 外部バックエンドのエンドポイントを使用している場合は、自己署名証明書は、HTTPS ロードバランサで受け入れられず、拒否されます。
  • INTERNET_IP_PORT タイプのエンドポイントで HTTPS や HTTP/2 を使用している場合は、SSL 証明書の検証と SAN チェックは行われません。つまり、自己署名証明書を使用できます。SSL を使用している場合は、INTERNET_FQDN_PORT エンドポイントを使用して、サーバー証明書と SAN を検証できるようにすることをおすすめします。

外部バックエンドからのレスポンスが Cloud CDN によってキャッシュに保存されない

以下の点を確認してください。

  • enableCDN を true に設定して、外部バックエンドを指す NEG を含むバックエンド サービスで Cloud CDN をすでに有効にしている。
  • 外部バックエンドによって提供されるレスポンスが、Cloud CDN のキャッシュ要件を満たしている。たとえば、送信元からの Cache-Control: public, max-age=3600 レスポンス ヘッダーを返している。

サーバーレス NEG に関する問題のトラブルシューティング

問題を調べる前に、次のページをよくお読みください。

リクエストが 404 エラーで失敗する

基盤となるサーバーレス リソース(App Engine、Cloud Functions、Cloud Run サービスなど)がまだ実行されていることを確認します。サーバーレス リソースが削除されても、サーバーレス NEG がまだ存在する場合、外部 HTTP(S) ロードバランサは引き続き存在しないサービスへのリクエストの転送を試みます。これにより、404 レスポンスが返されます。

一般に、外部 HTTP(S) ロードバランサは、基盤となるサーバーレス リソースが想定どおりに動作しているかどうかを検出できません。つまり、あるリージョンのサービスがエラーを返しても、そのリージョンの Cloud Run、Cloud Functions、または App Engine インフラストラクチャ全体が正常に動作している場合は、外部 HTTP(S) ロードバランサが他のリージョンにトラフィックを自動的に転送することはありません。ユーザー トラフィックを転送する前に、サービスの新しいバージョンを入念にテストしてください。

URL マスクの不一致への対処

ユーザー リクエスト URL に構成済み URL マスクを適用してもサービス名が生成されない場合や、存在しないサービス名が生成される場合、ロードバランサは使用中のサーバーレス コンピューティング プラットフォームに応じて、これらの不一致を異なる方法で処理する可能性があります。

Cloud Run: URL マスクが一致しない場合、ロードバランサは HTTP エラー 404(Not Found)を返します。

Cloud Functions: URL マスクが一致しない場合、ロードバランサは HTTP エラー 404(Not Found)を返します。

App Engine: URL マスクが一致しない場合、App Engine は dispatch.yaml と App Engine のデフォルトのルーティング ロジックを使用して、リクエストの送信先のサービスを決定します。