Extensible Service Proxy V2 に移行する

Extensible Service Proxy V2(ESPv2)は、Cloud Endpoints で API 管理機能を提供できるようにする Envoy ベースのプロキシです。ESPv2 は、NGINX ベースの Extensible Service Proxy(ESP)に代わるものです。

このドキュメントでは、既存の Endpoints API のデプロイを、ESP から ESPv2 に移行する方法について説明します。

始める前に

移行を開始する前に、以下で説明する、サポートされていないユースケースと、API の重要な変更を検討してください。

ESPv2 のサポート対象外のユースケース

  • App Engine フレキシブル環境はサポートされていません

    App Engine フレキシブル環境には、Endpoints のサポートが組み込まれており、アプリケーションの app.yaml ファイルで endpoints_api_service を設定することで有効になります。この組み込みの Endpoints 実装では、ESP のみがサポートされています。ESPv2 には移行できません。

    App Engine フレキシブル環境で ESPv2 を使用する場合は、app.yamlendpoints_api_service を無効にします。 ESPv2 は、アプリケーションの管理に使用する App Engine フレキシブル環境で別個の Cloud Run サービスとしてデプロイできます。デプロイは、ESPv2 を使用して App Engine スタンダード環境をサポートするのと同じ方法で機能します。

  • カスタム NGINX 構成はサポートされていません。

    ESPv2 は、Envoy ベースのプロキシです。カスタム NGINX プロキシ構成はサポートできません。ESP 構成で -n フラグまたは --nginx_config フラグを使用している場合、ESPv2 に簡単に移行できないカスタム NGINX 構成に実装が依存している場合があります。

重要な変更

  • X-Endpoint-API-UserInfo ヘッダーのデータ形式が変更されました。アプリケーションでこのヘッダーを使用する場合は、新しい形式を使用するように変更する必要があります。詳しくは、バックエンド サービスにおける JWT の取り扱いをご覧ください。
  • リクエストに API キーが必要な場合、ESP はユーザー プロジェクト ID を含む X-Endpoint-API-Project-ID ヘッダーをバックエンド アプリケーションに送信します。ESPv2 では、X-Endpoint-API-Consumer-TypeX-Endpoint-API-Consumer-Number という 2 種類のヘッダーを使用して、必要な詳細を送信します。これらのヘッダーで送信される Consumer-TypeConsumer-Number の詳細については、Service Infrastructure リファレンス ドキュメントをご覧ください。

  • HTTP エラー レスポンスの本体の形式が変更されました。ESPv2 が HTTP リクエストを拒否すると、新しい形式のエラー レスポンス本文が生成されます。実装にクライアント コードを使用して HTTP エラーの JSON レスポンス本文を処理する場合は、クライアント コードを更新する必要があります。詳細については、HTTP エラーの JSON レスポンス本文をご覧ください。

  • 新しい起動フラグを利用できます。一部の ESP フラグは非推奨であるか、ESPv2 で置き換えられています。ESP と ESPv2 の間の起動フラグの変更をご覧ください。

ESPv2 を使用するための Endpoints API の移行

サーバーレス プラットフォーム(Cloud Run、Cloud Functions、App Engine)で ESPv2 を使用するために必要な移行手順は、非サーバーレス プラットフォーム(Google Kubernetes Engine、Compute Engine、Kubernetes)で必要な手順とは異なります。

プラットフォームの種類ごとに必要な移行手順を以下に示します。

サーバーレス以外のプラットフォーム: GKE、Compute Engine、Kubernetes

ESPv2 は ESP の一時的な代替となる機能です。ほとんどの構成では、Docker イメージタグへの更新のみが必要です。

ただし、次のように ESP を構成した場合は、起動フラグの調整が必要になることがあります。

  • --http_port フラグ、http2_port フラグ、--ssl_port フラグによる複数のポート
  • SSLDNSClient IP などの、まれに使用されるフラグ。

新しい起動フラグは ESPv2 で使用できます。一部の ESP フラグは非推奨であるか、置き換えられています。詳しくは、ESP と ESPv2 の間の起動フラグの変更をご覧ください。

GKE と Kubernetes

GKE と Kubernetes の Endpoints 構成を移行するには、Deployment の yaml ファイルで ESP イメージタグを :1 から :2 に変更します。例:

- name: esp
  image: gcr.io/endpoints-release/endpoints-runtime:2
  args: [
    "--http_port=8081",
    "--backend=127.0.0.1:8080",
    "--service=SERVICE_NAME",
    "--rollout_strategy=managed",
  ]

Compute Engine

ESP と ESPv2 はどちらも、docker run コマンドを使用して Docker コンテナにデプロイされます。Compute Engine の Endpoints を ESPv2 に移行するには、コマンドで Docker イメージタグを :1 から :2 に更新します。例:

sudo docker run \
    --detach \
    DOCKER_ARGUMENTS \
    gcr.io/endpoints-release/endpoints-runtime:2 \
    --service=SERVICE_NAME \
    --rollout_strategy=managed \
    --backend=YOUR_API_CONTAINER_NAME:8080

サーバーレス プラットフォーム(Cloud Run、Cloud Functions、App Engine)

サーバーレス プラットフォームの場合、ESPv2 は Cloud Run サービスとしてデプロイされ、Cloud Run、Cloud Functions、App Engine 上で動作するアプリケーションを管理します。Endpoints を ESPv2 に移行するには、既存の Endpoints サービス構成を新しい ESPv2 Docker イメージにビルドし、そのイメージを ESPv2 の Cloud Run サービスにデプロイします。

ESP と ESPv2 のデプロイ手順は同じですが、次の点が異なります。

  • ESPv2 を Cloud Run にデプロイするときに、イメージタグを ESPv2 で :1 から :2 に変更する必要があります。例:

    gcloud run deploy CLOUD_RUN_SERVICE_NAME \
    --image="gcr.io/endpoints-release/endpoints-runtime-serverless:2" \
    --allow-unauthenticated \
    --platform managed \
    --project=ESP_PROJECT_ID
    
  • gcloud_build_image スクリプトが別の場所からダウンロードされます。ベースイメージとして gcr.io/endpoints-release/endpoints-runtime-serverless:2 が使用されます。

  • スタートアップ フラグを指定するために、環境変数が使用されます。ESP の変数名は ESP_ARGS です。ESPv2 の名前は ESPv2_ARGS です。ESPv2_ARGS および使用可能な起動フラグの詳細については、Extensible Service Proxy V2 起動オプションをご覧ください。

ESP と ESPv2 の間の起動フラグの変更

Extensible Service Proxy の場合と同様に、ESPv2 サービスをデプロイするときに構成フラグを指定できます。NGINX ベースの ESP から Envoy ベースの ESPv2 への変更に伴い、一部のフラグが非推奨または別のものに置き換えられ、新しいフラグが追加されました。このセクションでは、次の 3 つの表を使用してこの変更について説明します。

  • 表 1 では、非推奨になったフラグを置き換える新しいフラグについて説明しています。
  • 表 2 では、新しいフラグを説明しています。
  • 表 3 では、非推奨になったフラグについて説明しています。

置き換えられたフラグ

新しいフラグ 置き換えられたフラグ 説明
--listener_port --http_port--http2_port--ssl_port 単一の Envoy リスナーポートは、ESPv2 で、http、http2、ssl をサポートします。別のポートを指定する必要はありません。
--ssl_server_cert_path --ssl_port --ssl_server_cert_path が使用される場合、ESPv2 は server.key ファイルと server.crt ファイルの証明書を使用します。ESPv2 では、/etc/nginx/ssl 以外のサーバー証明書パスを指定できます。このフラグは、/etc/nginx/ssl/nginx.key/etc/nginx/ssl/nginx.crt のファイルパスからの証明書を使用する ESP の --ssl_port に代わるものです。
--ssl_backend_client_cert_path --tls_mutual_auth--enable_grpc_backend_ssl--grpc_backend_ssl_private_key_file--grpc_backend_ssl_cert_chain_file --ssl_backend_client_cert_path が使用される場合、ESPv2 は client.key ファイルと client.crt ファイルの証明書を使用します。ESPv2 では、/etc/nginx/ssl 以外のクライアント証明書パスを指定できます。このフラグは、/etc/nginx/ssl/backend.key/etc/nginx/ssl/backend.crt のファイルパスからの証明書を使用する ESP の --tls_mutual_auth に代わるものです。
--ssl_backend_client_root_certs_file --grpc_backend_ssl_root_certs_file ESPv2 では、--ssl_backend_client_root_certs_file はすべてのバックエンドで機能します。このフラグは、ESP の --grpc_backend_ssl_root_certs_file を置き換えるもので、gRPC バックエンドに対してのみ機能します。
--ssl_minimum_protocol--ssl_maximum_protocol --ssl_protocols ESP で --ssl_protocols を使用する場合、必要なすべての SSL プロトコルを一覧表示する必要があります。ESPv2 では、最小プロトコルと最大プロトコルを指定できます。
--envoy_use_remote_address--envoy_xff_num_trusted_hops --xff_trusted_proxy_list--client_ip_header--client_ip_position Envoy は、クライアント IP の抽出を構成するために use_remote_addressxff_num_trusted_hops を必要とします。
--dns_resolver_addresses --dns 置換フラグの動作は同じですが、デフォルト値は異なります。ESP では DNS リゾルバとして 8.8.8.8 を使用します。ESPv2 では、/etc/resolv.conf で構成される DNS リゾルバが使用されます。
--service_account_key --non_gcp, --service_account_key ESP では、--service_account_key フラグで GCP 以外のプラットフォームへのデプロイが暗黙的に許可されます。これにより、ESP がインスタンス メタデータ サーバーを呼び出さないようにします。 ESPv2 では、この暗黙の行動は別のフラグに分割されます。移行時に --non_gcp の追加が必要になることがあります。そうしないと、ESPv2 が GCP 以外のプラットフォームで起動できなくなります。

新しいフラグ

新しいフラグ 説明
--http_request_timeout_s すべての http/https リモート呼び出しのタイムアウトを秒単位で設定します。ただし、バックエンド呼び出しと Google Service Control 呼び出しは除きます。
--service_control_check_timeout_ms Google Service Control Check 呼び出しのタイムアウトをミリ秒単位で設定します。
--service_control_report_timeout_ms Google Service Control Report 呼び出しのタイムアウトを設定します。
--service_control_quota_timeout_ms Google Service Control Quota 呼び出しのタイムアウトを設定します。
--service_control_check_retries Google Service Control Check 呼び出しの再試行番号を指定します。
--service_control_report_retries Google Service Control Report 呼び出しの再試行番号を指定します。
--service_control_quota_retries Google Service Control Quota 呼び出しの再試行番号を指定します。
--backend_dns_lookup_family すべてのバックエンドの DNS ルックアップ ファミリーを定義するために使用される Envoy 固有の構成。
--disable_tracing すべてのトレースを無効にするために使用される全体的なフラグ。
--tracing_project_id トレースデータを所有するプロジェクトの ID を設定するために使用されます。
--tracing_incoming_context 受信トレース コンテキストを指定するために使用します。
--tracing_outgoing_context 送信トレース コンテキストを指定するために使用します。

非推奨のフラグ

非推奨のフラグ 説明
--enable_websocket WebSocket は Envoy でデフォルトで有効になっています。
--experimental_proxy_backend_host_header サポートされていません。
--allow_invalid_headers サポートされていません。これは NGINX 構成 ignore_invalid_headers です。HTTP リクエストに無効なヘッダー名がある場合、ESPv2 により拒否されます。有効なヘッダー名は、英字、数字、ハイフン、アンダースコアから構成されます。ESPv2 では、フラグ --underscores_in_headers で、ヘッダーでアンダースコアを許可するかどうかを決定します。
--client_max_body_size NGINX 構成はサポートされていません。
--client_body_buffer_size NGINX 構成はサポートされていません。
--large_client_header_buffers NGINX 構成はサポートされていません。
--keepalive_timeout NGINX 構成はサポートされていません。
--client_body_timeout NGINX 構成はサポートされていません。
--rewrite サポートされていません。
--experimental_enable_multiple_api_configs サポートされていません。
--enable_backend_routing 不要です。サーバーレス プラットフォームでは、バックエンド ルーティングが自動的に有効になります。
--rollout_fetch_throttle_window_in_s 不要です。
--nginx_config サポートされていません。

ESPv2 の起動フラグの詳細については、Extensible Service Proxy V2 の起動オプションをご覧ください。フラグに関するその他の一般的な例とヘルプテキストについては、GitHub リポジトリをご覧ください。

デフォルトの JWT の場所

デフォルトでは、JWT は Authorization ヘッダー(接頭辞「Bearer」)、X-Goog-Iap-Jwt-Assertion ヘッダー、または access_token クエリ パラメータのいずれかで渡されます。これらの場所は、ESP と ESPv2 の両方でサポートされます。ESP の使用時は、Authorization ヘッダー(接頭辞なし)で JWT を渡すこともできます。ただし、この場所は ESPv2 ではサポートされていません。

ESPv2 に移行後も Authorization ヘッダー(接頭辞なし)を使用して JWT を渡す場合は、次のようにします。

  • openAPI ファイルで x-google-jwt-locations を設定します(HTTP バックエンド ユーザー向け)。
x-google-jwt-locations:
- header: "Authorization"
jwt_locations:
- header: Authorization

バックエンド サービスにおける JWT の取り扱い

JWT を使用して認証を行う場合、ESPv2 と ESP で認証ヘッダーの X-Endpoint-API-UserInfo ヘッダーがバックエンド API に送信されます。元の Authorization ヘッダーの代わりにこのヘッダーを使用することをおすすめします。元の Authorization ヘッダーは、サーバーレス プラットフォームでは変更される可能性があるためです。

X-Endpoint-API-UserInfo ヘッダーには、Base64Url エンコードされた JSON オブジェクトが含まれます。ただし、形式は ESP から ESPv2 に変更されています。

ESPv2 では、X-Endpoint-API-UserInfo ヘッダーに何も変更していない元の JWT ペイロードが含まれます。

ESP では、X-Endpoint-API-UserInfo ヘッダーに JWT ペイロードと ESP によって追加されたいくつかの特定のフィールドが含まれています。ESP は、idissueremailaudiences の各フィールドを JSON オブジェクトに追加します。また、元の JWT ペイロードを含める claims フィールドも追加されています。

# ESPv1 X-Endpoint-API-UserInfo header value
{
  "id": "extracted from 'sub' field",
  "issuer": "extracted from 'iss' field",
  "email": "extracted from 'email' field",
  # The following "audiences" is extracted from 'aud' field.
  # The 'aud' field may have multiple audiences delimited by coma. e.g. "aud: aud1,aud2".
  # but the following "audiences" is always a JSON array.
  "audiences": ["aud1", "aud2"],
  "claims": {
     Original JWT payload
   }
}

次の例は、その違いを示しており、すべて base64url でデコードされています。

# This is an example of the original JWT payload:
{
  "iss": "https://accounts.google.com",
  "email": "abcdefg123456@gmail.com",
  "sub": "1234567890123456789",
  "aud": "xyz1.example.com,xyz2.example.com",
  "foo": "foo.foo.foo.foo",
  "bar": "bar.bar.bar.bar",
  "azp": "98765432109876543210",
  "exp": "1642809446",
  "iat": "1642805846"
}

# This is an example of the `X-Endpoint-API-UserInfo` header from ESPv2
# extracted from above JWT payload.
{
  "iss": "https://accounts.google.com",
  "email": "abcdefg123456@gmail.com",
  "sub": "1234567890123456789",
  "aud": "xyz1.example.com,xyz2.example.com",
  "foo": "foo.foo.foo.foo",
  "bar": "bar.bar.bar.bar",
  "azp": "98765432109876543210",
  "exp": "1642809446",
  "iat": "1642805846"
}

# This is an example of the `X-Endpoint-API-UserInfo` header from ESP
# extracted from above JWT payload.
{
  "id":"1234567890123456789",
  "issuer": "https://accounts.google.com",
  "email": "abcdefg123456@gmail.com",
  "audiences": [
    "xyz1.example.com"
    "xyz2.example.com"
  ],
  "claims": {
    "iss": "https://accounts.google.com",
    "email": "abcdefg123456@gmail.com",
    "sub": "1234567890123456789",
    "aud": "xyz1.example.com,xyz2.example.com",
    "foo": "foo.foo.foo.foo",
    "bar": "bar.bar.bar.bar",
    "azp": "98765432109876543210",
    "exp": "1642809446",
    "iat": "1642805846"
  }
}

認証を含む JWT の使用についての詳細は、カスタム メソッドを使用したユーザーの認証サービス間の認証をご覧ください。

エラー JSON レスポンスの本文の形式

ESP または ESPv2 で HTTP リクエストが拒否された場合、レスポンスの本文にはステータス コードとエラー メッセージ(JSON 形式)が含まれます。次の例に示すように、レスポンスの本文の形式は ESPv2 で変更されています。

ESP のエラー レスポンス本文

{
 "code": 5,
 "message": "Method does not exist.",
 "details": [
  {
   "@type": "type.googleapis.com/google.rpc.DebugInfo",
   "stackEntries": [],
   "detail": "service_control"
  }
 ]
}

ESPv2 のエラー レスポンス本文

{
 "code": 400,
 "message": "Method does not exist.",
}

主な違いは次の 2 点です。

  • ESPv2 では、code フィールドには ESP で見られた RPC ステータス コードではなく、http ステータス コードが含まれます。
  • ESPv2 のエラー レスポンス本文に details フィールドは含まれません。

次のステップ

以下の内容について学習します。