Gateway のデプロイ

このページでは、上り(内向き)トラフィックを単一の Google Kubernetes Engine(GKE)クラスタにロードバランスするために Kubernetes Gateway リソースをデプロイする方法について説明します。

Gateway をデプロイして複数のクラスタ間(またはフリート)で上り(内向き)トラフィックをロードバランスする方法については、マルチクラスタ Gateway のデプロイをご覧ください。

Namespace をまたがるルーティングや HTTP トラフィックの分割など、Gateway の詳細な構成については、Gateway API ユーザーガイドをご覧ください。

始める前に

作業を始める前に、次のタスクが完了していることを確認してください。

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update コマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。
  • すでに Autopilot クラスタまたは Standard クラスタが存在していることを確認する。新しいクラスタを作成するには、Autopilot クラスタの作成をご覧ください。

GKE Gateway コントローラの要件

  • Gateway API は、VPC ネイティブ クラスタでのみサポートされます。
  • リージョンまたはクロスリージョンの GatewayClass を使用している場合は、プロキシ専用サブネットを有効にする必要があります。
  • クラスタで HttpLoadBalancing アドオンが有効になっている必要があります。
  • Istio を使用している場合は、Istio を次のいずれかのバージョンにアップグレードする必要があります。
    • 1.15.2 以降
    • 1.14.5 以降
    • 1.13.9 以降
  • 共有 VPC を使用している場合は、ホスト プロジェクトで、サービス プロジェクトの GKE サービス アカウントに Compute Network User ロールを割り当てる必要があります。

制限事項

GKE Gateway を使用する場合は、次の制限事項に注意してください。

  • GKE GatewayClasses がサポートする機能は、使用するロードバランサによって異なります。各 GatewayClass でサポートされている機能の詳細については、GatewayClass の機能をご覧ください。

    ベスト プラクティス:

    パフォーマンスを最適化するには、Gateway の数を最大 100 個までにします。この上限を超えると、パフォーマンスに影響したり、レイテンシが増加する可能性があります。

  • FrontendConfig または BackendConfig を使用して Gateway を構成することはできません。ポリシーを使用する必要があります。

  • Ingress とは異なり、GKE Gateway はヘルスチェックのパラメータを推定しません。Service が GET / へのリクエストに対して 200 を返さない場合、または他の調整された Pod の readiness チェックがある場合は、サービスの HealthCheckPolicy を構成する必要があります。

  • トラフィック ルーティングのホスト名にポート番号を直接指定することはできません(web.example.com:80 など)。

  • GKE が Gateway 用に作成したロードバランサ リソースは、 Google Cloud コンソールで確認できますが、これらのリソースは接続先の Gateway や GKE クラスタを参照しません。

  • Gateway を使用して Google マネージド SSL 証明書を自動的に生成することはできませんが、Google マネージド SSL 証明書を手動で作成して参照することはできます。詳細については、Gateway を保護するをご覧ください。

  • Route タイプとしてサポートされているのは HTTPRoute だけです。TCPRoutes、UDPRoutes、TLSRoutes はサポートされていません。GKE Gateway Controller がサポートするフィールドの一覧については、GatewayClass の機能をご覧ください。

  • Gateway を含むカスタム リクエストとレスポンス ヘッダー、または Gateway を使用したパス リダイレクトと URL の書き換えは、GKE バージョン 1.27 以降でのみ使用できます。

  • Gateway を含むカスタム リクエストとレスポンス ヘッダー、および Gateway を使用したパス リダイレクトと URL の書き換えの場合、GatewayClass gke-l7-gxlb はサポートされません。

  • HTTPRoute のカスタム リクエスト ヘッダーとレスポンス ヘッダーを構成する場合、次の Google Cloud 変数はサポートされません。

    • cdn_cache_id(Cloud CDN は GKE Gateway でサポートされていません)
    • cdn_cache_status(Cloud CDN は GKE Gateway でサポートされていません)
    • origin_request_headerCORS ポリシーは GKE Gateway でサポートされていません)
  • GKE Gateway は Cloud CDN のロード バランシング機能をサポートしていません。

  • 相互 TLS カスタム ヘッダーはサポートされていません(GKE Gateway で mTLS はサポートされていません)。

  • Google Cloud の従来のアプリケーション ロードバランサの制限は GKE Gateway に適用されます。また、バックエンド サービスでカスタムの Host レスポンス ヘッダーを構成することはできません。

  • パス リダイレクトと URL の書き換えは相互に排他的です。同じルールで両方のフィルタを同時に使用することはできません。

  • Cloud Load Balancing でトラフィックを別のポートにリダイレクトすることはできません。GKE Gateway Controller がサポートするフィールドの一覧については、GatewayClass の機能をご覧ください。

  • GKE Gateway は、ワイルドカード、正規表現、動的 URL をサポートしていません。

  • リージョン外部ゲートウェイ クラスを使用して Gateway を指定すると、コントローラは外部アドレスではなく内部 IP アドレスをプロビジョニングします。リージョン外部アプリケーション ロードバランサで名前付きアドレスを使用する方法については、リージョン外部 Gateway をデプロイするをご覧ください。

  • Gateway は、ネットワーク エンドポイント グループのプロビジョニングにスタンドアロン NEG を利用します。Gateway コントローラがロードバランサの構成を適切に調整できるようにするため、Gateway の一部である Service の cloud.google.com/neg アノテーションを変更することはできません。

  • GKE Gateway は、GKE Ingress でも参照される Service の参照をサポートしていません。

  • IP アドレスをプロビジョニングするように Gateway が構成されている場合、Gateway.spec.gatewayClass の変更はサポートされません。Gateway コントローラがロードバランサを適切に調整できるようにするため、既存の Gateway を削除し、更新された gatewayClass 値を含むマニフェストを再度デプロイします。

  • networking.gke.io/app-protocols アノテーションはサポートされていません。同じ結果を得るには、代わりに appProtocol フィールドを使用してください。

  • external-dns で GKE Gateway を使用し、Gateway の健全性が異常な場合、デフォルトでは、Gateway に関連付けられているすべての DNS レコードが DNS ゾーンから削除されます。

    ベスト プラクティス:

    external-dns を実行するときに、policy=upsert-only フラグを設定します。この構成は、既存の DNS レコードが削除されるのを防ぐのに役立ちます。

  • GKE Gateway がルートを介して参照する Service からポートが削除された場合は、Service の スタンドアロン NEG アノテーションで、Service のスタンドアロン NEG コントローラを更新して、そのポートを削除する必要もあります。これを行わないと、NEG コントローラは最終的にこの Service の Pod エンドポイントの同期を停止します。詳細については、Service からポートが削除されると NEG コントローラがエンドポイントの管理を停止するをご覧ください。

  • ゾーンクラスタを使用するマルチクラスタ ゲートウェイ(MCG)を使用するデプロイでは、クラスタのアップグレード中にサービスが中断される可能性があります。この問題は、ゾーンクラスタのコントロール プレーンが一時的に使用できない場合に、以前の Network Endpoint Group(NEG)検出メカニズムがバックエンドをゼロと誤って報告することが原因で発生します。長期的な修正が進行中です。この単一障害点を回避するには、MCG でリージョン GKE クラスタを使用します。

クラスタで Gateway API を有効にする

GKE でゲートウェイ リソースを使用する前に、クラスタで Gateway API を有効にしておく必要があります。

既存の GKE クラスタを更新して Gateway API を有効にする前に、最小要件が満たされていることを確認します。

既存の GKE クラスタ(Autopilot または Standard)で Gateway API を有効にするには、次のコマンドを使用します。このオペレーションは、クラスタが CRD を調整してインストールするまでに最大 45 分間かかることがあります。

gcloud container clusters update CLUSTER_NAME \     --location=CLUSTER_LOCATION\     --gateway-api=standard 

次のように置き換えます。

--gateway-api=standard フラグを指定すると、GKE は、クラスタと v1beta1 CRD をインストールします。

クラスタを確認する

クラスタを作成またはアップグレードすると、GKE Gateway Controller は GatewayClass を自動的にインストールします。コントローラが CRD を認識して GatewayClass をインストールするまでに数分かかることがあります。

  1. GKE コントロール プレーンで Gateway API が有効になっていることを確認します。

    gcloud container clusters describe CLUSTER_NAME \   --location=CLUSTER_LOCATION \   --format json 

    出力は次のようになります。この出力が空の場合は、cluster update コマンドを再実行します。

    "networkConfig": {   ...   "gatewayApiConfig": {     "channel": "CHANNEL_STANDARD"   },   ... }, 
  2. GatewayClasses がクラスタにインストールされていることを確認します。

    kubectl get gatewayclass 

    出力は次のようになります。

    NAME                             CONTROLLER                  ACCEPTED   AGE gke-l7-global-external-managed   networking.gke.io/gateway   True       16h gke-l7-regional-external-managed networking.gke.io/gateway   True       16h gke-l7-gxlb                      networking.gke.io/gateway   True       16h gke-l7-rilb                      networking.gke.io/gateway   True       16h 

各 GatewayClass の機能については、GatewayClass の機能をご覧ください。

単一クラスタの GatewayClass のみが自動的にインストールされます。内部および外部マルチクラスタ ロード バランシング用のマルチクラスタ GatewayClass をインストールして使用するには、マルチクラスタ Gateway の有効化をご覧ください。

内部 Gateway をデプロイする

内部 Gateway は、VPC または VPC に接続されているネットワーク内からのみ到達可能なアプリケーションを公開します。

リージョン内部 Gateway をデプロイする

次の例は、特定の地理的リージョン内のサービス間で効率的かつ安全な通信を可能にするリージョン内部 Gateway をデプロイする方法を示しています。

プロキシ専用サブネットを構成する

内部アプリケーション ロードバランサを使用する Gateway を作成する前に、プロキシ専用サブネットを構成する必要があります。内部アプリケーション ロードバランサを使用する VPC の各リージョンには、プロキシ専用サブネットが必要です。このサブネットは、ロードバランサ プロキシに内部 IP アドレスを提供します。

  1. プロキシ専用サブネットを作成します。

    gcloud compute networks subnets create SUBNET_NAME \     --purpose=REGIONAL_MANAGED_PROXY \     --role=ACTIVE \     --region=COMPUTE_REGION \     --network=VPC_NETWORK_NAME \     --range=CIDR_RANGE 

    次のように置き換えます。

    • SUBNET_NAME: プロキシ専用サブネットの名前。
    • COMPUTE_REGION: プロキシ専用サブネットのリージョン。
    • VPC_NETWORK_NAME: このプロキシ専用サブネットを作成する VPC ネットワークの名前。これは、GKE クラスタが配置され、Gateway をデプロイする VPC ネットワークと同じにする必要があります。これは、ロードバランサとバックエンド サービス間のシームレスな通信に重要です。
    • CIDR_RANGE: サブネットのプライマリ IP アドレス範囲。サブネット マスクの長さは /26 以下にして、リージョン内のプロキシで 64 個以上の IP アドレスを使用できるようにします。推奨のサブネット マスクは /23 です。
  2. プロキシ専用サブネットを確認します。

    gcloud compute networks subnets describe SUBNET_NAME \     --region=COMPUTE_REGION 

    出力は次のようになります。

    ... gatewayAddress: 10.1.1.1 ipCidrRange: 10.1.1.0/24 kind: compute#subnetwork name: proxy-subnet network: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/global/networks/default privateIpGoogleAccess: false privateIpv6GoogleAccess: DISABLE_GOOGLE_ACCESS purpose: REGIONAL_MANAGED_PROXY region: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION role: ACTIVE selfLink: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION/subnetworks/proxy-subnet state: READY 

ゲートウェイを作成する

Gateway リソースは、Kubernetes のトラフィックをルーティングするデータプレーンを表します。Gateway は、派生元の GatewayClass に応じて、さまざまな負荷分散とルーティングを表すことができます。Gateway リソースの詳細については、Gateway リソースの説明または API 仕様をご覧ください。

このケースでは、GKE クラスタの管理者は、さまざまなチームがアプリケーションを内部で公開するためのゲートウェイを作成したいと考えています。管理者が Gateway をデプロイして、アプリケーション チームが Route を個別にデプロイし、Gateway に接続します。

  1. 次の Gateway マニフェストを gateway.yaml という名前のファイルに保存します。

    kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata:    name: internal-http spec:   # Specify an existing GatewayClass.   gatewayClassName: gke-l7-rilb   listeners:   # Listen for HTTP traffic on port 80.   - name: http     protocol: HTTP     port: 80 

    このマニフェストには次のフィールドがあります。

    • gatewayClassName: gke-l7-rilb: このゲートウェイの派生元となる GatewayClass を指定します。gke-l7-rilb は、内部アプリケーション ロードバランサに対応しています。
    • port: 80: HTTP トラフィックをリッスンするために Gateway がポート 80 のみを公開することを指定します。

    この Gateway は、ポート 80 の HTTP トラフィックのみを処理するように構成されています。デフォルトでは HTTPS(ポート 443)をサポートしていないため、HTTPS 経由で接続しようとすると、リクエストが失敗する可能性があります。

  2. クラスタに Gateway をデプロイします。

    kubectl apply -f gateway.yaml 
  3. Gateway が正しくデプロイされたことを確認します。すべてのリソースがデプロイされるまで数分かかる場合があります。

    kubectl describe gateways.gateway.networking.k8s.io internal-http 

    出力は次のようになります。

    Name:         internal-http Namespace:    default Spec:   Gateway Class Name:  gke-l7-rilb   Listeners:     Allowed Routes:       Kinds:         Group:  gateway.networking.k8s.io         Kind:   HTTPRoute       Namespaces:         From:  Same     Name:      http     Port:      80     Protocol:  HTTP  Status:    Addresses:      Type:   IPAddress      Value:  192.168.1.14    Conditions:      Last Transition Time:  2025-03-19T19:53:46Z      Message:               The OSS Gateway API has deprecated this condition, do not depend on it.      Observed Generation:   1      Reason:                Scheduled      Status:                True      Type:                  Scheduled      Last Transition Time:  2025-03-19T19:53:46Z      Message:      Observed Generation:   1      Reason:                Accepted      Status:                True      Type:                  Accepted      Last Transition Time:  2025-03-19T19:53:46Z      Message:      Observed Generation:   1      Reason:                Programmed      Status:                True # Indicates that the Gateway is ready.      Type:                  Programmed      Last Transition Time:  2025-03-19T19:53:46Z      Message:               The OSS Gateway API has altered the "Ready" condition semantics and reserved it for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.      Observed Generation:   1      Reason:                Ready      Status:                True      Type:                  Ready      Last Transition Time:  2025-03-19T19:53:46Z      Message:      Observed Generation:   1      Reason:                Healthy      Status:                True      Type:                  networking.gke.io/GatewayHealthy Events:   Type    Reason  Age                From                       Message   ----    ------  ----               ----                       -------   Normal  ADD     92s                networking.gke.io/gateway  test/internal-http   Normal  UPDATE  45s (x3 over 91s)  networking.gke.io/gateway  test/internal-http   Normal  SYNC    45s                networking.gke.io/gateway  SYNC on test/internal-http was a success 

    この出力では、Programmed 条件の True のステータスは、ゲートウェイの準備が完了していることを示します。

    この時点で、ロードバランサと IP アドレスをプロビジョニングしているクラスタにゲートウェイがデプロイされます。ただし、Gateway には Route がないため、バックエンドにトラフィックを送信する方法がわかりません。Route を使用しないと、すべてのトラフィックがデフォルトのバックエンドに移動し、HTTP 404 を返します。次に、アプリケーションと Route をデプロイします。これにより、Gateway にアプリケーション バックエンドの取得方法が指示されます。

デモ アプリケーションをデプロイする

アプリケーション チームは、Gateway のデプロイとは別にアプリケーションと Route をデプロイできます。アプリケーション チームで Gateway を所有し、アプリケーション専用のリソースとしてデプロイすることもできます。Gateway と Route のさまざまな所有権モデルについては、ルート バインディングをご覧ください。しかし、この例では、ストアチームがアプリケーションと付属の HTTPRoute をデプロイし、前のセクションで作成した internal-http Gateway 経由でアプリを公開します。

HTTPRoute リソースには、トラフィック照合用の構成可能なフィールドが多数あります。HTTPRoute のフィールドの説明については、API の仕様をご覧ください。

  1. ストア アプリケーション(store-v1、store-v2、store-german のデプロイ)をクラスタにデプロイします。

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml 

    これにより、3 つの Deployment と、store-v1、store-v2、store-german という名前の 3 つの Service が作成されます。

  2. アプリケーションのデプロイが成功したことを確認します。

    kubectl get pod 

    アプリケーションが稼働した後の出力は次のようになります。

    NAME                        READY   STATUS    RESTARTS   AGE store-german-66dcb75977-5gr2n   1/1     Running   0          38s store-v1-65b47557df-jkjbm       1/1     Running   0          14m store-v2-6856f59f7f-sq889       1/1     Running   0          14m 
  3. Service がデプロイされていることを確認します。

    kubectl get service 

    出力には、各ストア Deployment の Service が表示されます。

    NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE store-german   ClusterIP   10.48.3.183   <none>        8080/TCP   4s store-v1       ClusterIP   10.48.2.224   <none>        8080/TCP   5s store-v2       ClusterIP   10.48.4.48    <none>        8080/TCP   5s 

HTTPRoute をデプロイする

ルートリソースは、ゲートウェイから Kubernetes バックエンドにトラフィックをマッピングするためのプロトコル固有のルールを定義します。HTTPRoute リソースは、HTTP および HTTPS トラフィックの照合とフィルタリングを行います。これは、すべての gke-l7 GatewayClasss でサポートされています。

このセクションでは、HTTPRoute をデプロイし、トア アプリケーションに到達するために必要なルーティング ルールを使用して Gateway を制御します。

  1. 次の HTTPRoute マニフェストを store-route.yaml という名前のファイルに保存します。

    kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata:   name: store spec:   # Attach the HTTPRoute to a Gateway.   parentRefs:   - kind: Gateway     name: internal-http   # Route requests that have `store.example.com` in the Host header.   hostnames:   - "store.example.com"   rules:   # Send requests with the `env: canary` header to the `store-v2` Service.   - matches:     - headers:       - name: env         value: canary     backendRefs:     - name: store-v2       port: 8080   # Send requests with `/de` in the path to the `store-german` Service.   - matches:     - path:         value: /de     backendRefs:     - name: store-german       port: 8080   # Send unmatched requests to the store-v1 Service.   - backendRefs:     - name: store-v1       port: 8080 
  2. クラスタに HTTProute をデプロイします。

    kubectl apply -f store-route.yaml 

    store HTTPRoute は parentRefs プロパティを使用して internal-http Gateway にバインドされます。次の図のように、これらのルーティング ルールは基盤となるロードバランサで構成されます。

    ストアの HTTPRoute によって構成されたルーティング ルール

    これらのルーティング ルールは HTTP トラフィックを次のように処理します。

    • store.example.com/de へのトラフィックは、Service store-german に送信されます。
    • HTTP ヘッダー "env: canary" を含む store.example.com へのトラフィックは、Service store-v2 に送信されます。
    • store.example.com への残りのトラフィックは、Service store-v1 に送信されます。
  3. HTTPRoute がデプロイされていることを確認します。

    kubectl describe httproute store 

    出力は次のようになります。

    Name:         store Namespace:    default Labels:       <none> Annotations:  <none> API Version:  gateway.networking.k8s.io/v1 Kind:         HTTPRoute # Multiple lines are omitted here. Spec:   Hostnames:     store.example.com   Parent Refs:     Group:  gateway.networking.k8s.io     Kind:   Gateway     Name:   internal-http   Rules:     Backend Refs:       Group:       Kind:    Service       Name:    store-v1       Port:    8080       Weight:  1     Matches:       Path:         Type:   PathPrefix         Value:  /     Backend Refs:       Group:       Kind:    Service       Name:    store-v2       Port:    8080       Weight:  1     Matches:       Headers:         Name:   env         Type:   Exact         Value:  canary       Path:         Type:   PathPrefix         Value:  /     Backend Refs:       Group:       Kind:    Service       Name:    store-german       Port:    8080       Weight:  1     Matches:       Path:         Type:   PathPrefix         Value:  /de Status:   Parents:     Conditions:       Last Transition Time:  2022-11-01T04:18:52Z       Message:       Reason:                Accepted       Status:                True       Type:                  Accepted       Last Transition Time:  2022-11-01T04:18:52Z       Message:       Reason:                ReconciliationSucceeded       Status:                True       Type:                  Reconciled     Controller Name:         networking.gke.io/gateway     Parent Ref:       Group:  gateway.networking.k8s.io       Kind:   Gateway       Name:   internal-http Events:   Type    Reason  Age                From                   Message   ----    ------  ----               ----                   -------   Normal  ADD     24m                sc-gateway-controller  default/store   Normal  SYNC    16m (x4 over 23m)  sc-gateway-controller  Bind of HTTPRoute "default/store" to ParentRef {Group:       gateway.networking.k8s.io",   # Multiple lines are omitted here. 
  4. HTTPRoute が Gateway にバインドされていることを確認します。

    kubectl describe gateway 

    出力は次のようになります。

    Name:         internal-http Namespace:    default Labels:       <none> <...> Status:   Addresses:     Type:   IPAddress     Value:  10.128.15.203   Conditions:     Last Transition Time:  2022-11-01T03:47:01Z     Message:     Reason:                Scheduled     Status:                True     Type:                  Scheduled     Last Transition Time:  2022-11-01T03:47:01Z     Message:     Reason:                Ready     Status:                True     Type:                  Ready   Listeners:     Attached Routes:  1     Conditions:       Last Transition Time:  2022-11-01T03:47:01Z       Message:       Reason:                Ready       Status:                True       Type:                  Ready     Name:                    http     Supported Kinds:       Group:  gateway.networking.k8s.io       Kind:   HTTPRoute       <...> 

アプリケーションにトラフィックを送信する

クラスタに Gateway、Route、アプリケーションがデプロイされたら、アプリケーションにトラフィックを送信できます。Gateway は、ポート 80 の HTTP トラフィックのみを処理するように構成されています。TLS が個別に構成されていない場合、HTTPS で行われたリクエストは失敗する可能性があります。

  1. アプリケーションにトラフィックを送信できるように、Gateway から IP アドレスを取得します。

    kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}" 

    出力は IP アドレスです。

  2. クラスタに接続している仮想マシン(VM)インスタンスのシェルから、この IP アドレスにトラフィックを送信します。この目的で使用する VM を作成することもできます。Gateway に内部 IP アドレスが割り振られ、VPC ネットワーク内からのみアクセスされるため、この操作が必要になります。internal-http はリージョン ロードバランサです。クライアント シェルは GKE クラスタと同じリージョン内に存在する必要があります。

    store.example.com にリクエストを送信します。

    curl http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v 

    GATEWAY_IP_ADDRESS は、前の手順で取得した IP アドレスに置き換えます。

    デモアプリの出力には、アプリが実行されている場所に関する情報が含まれます。

    {   "cluster_name": "gke1",   "host_header": "store.example.com",   "metadata": "store-v1",   "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",   "pod_name": "store-v1-84b47c7f58-pmgmk",   "pod_name_emoji": "💇🏼‍♀️",   "project_id": "gateway-demo-243723",   "timestamp": "2022-10-25T13:31:17",   "zone": "ZONE_NAME" } 
  3. store.example.com/de にあるドイツ語版のストアサービスにアクセスして、パスの照合をテストします。

    curl http://store.example.com/de --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v 

    出力で、リクエストが store-german Pod で処理されたことを確認できます。

    {   "cluster_name": "gke1",   "host_header": "store.example.com",   "metadata": "Gutentag!",    "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal",   "pod_name": "store-german-5cb6474c55-lq5pl",    "pod_name_emoji": "🧞‍♀",   "project_id": "gateway-demo-243723",   "timestamp": "2022-10-25T13:35:37",   "zone": "ZONE_NAME" } 
  4. 最後に、env: canary HTTP ヘッダーを使用して、ストアの Service のカナリア バージョンにトラフィックを送信します。

    curl -H "env: canary" http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v 

    出力で、リクエストが store-v2 Pod で処理されたことを確認できます。

    {   "cluster_name": "gke1",   "host_header": "store.example.com",   "metadata": "store-v2",    "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",   "pod_name": "store-v2-5788476cbd-s9thb",    "pod_name_emoji": "🦰",   "project_id": "gateway-demo-243723",   "timestamp": "2022-10-25T13:38:26",   "zone": "ZONE_NAME" } 

外部ゲートウェイをデプロイする

外部ゲートウェイは、インターネットまたは VPC ネットワーク外のネットワークから到達可能なアプリケーションを公開します。これは内部ゲートウェイのデプロイと似ていますが、ゲートウェイが公共のインターネットにアクセスできるため、アプリケーションを保護する必要があります。

外部ゲートウェイを作成する場合、グローバル外部ゲートウェイを作成する方法とリージョン外部ゲートウェイを作成する方法があります。

  • グローバル外部ゲートウェイ: このゲートウェイは、ゲートウェイのフロントエンドとしてグローバル IP アドレス(またはエニーキャスト IP アドレス)を使用します。この IP アドレスは、すべての Google Cloud コンピューティング リージョンでアドバタイズされます。このエニーキャスト IP アドレスにトラフィックを送信するクライアントは、IP アドレスがアドバタイズされている最も近い Google ロケーションにルーティングされます。グローバル外部ゲートウェイは、Premium Network Service Tiers でのみ使用できます。
  • リージョン外部ゲートウェイ: このゲートウェイは、ゲートウェイのフロントエンドとしてリージョン IP アドレスを使用します。このゲートウェイの動作は、選択した Network Service Tiers によって異なります。
    • Standard Network Service Tiers(デフォルト)を選択した場合、リージョン IP アドレスは、リージョン外部ゲートウェイがデプロイされているローカル Google Cloud コンピューティング リージョンでのみアドバタイズされます。この IP アドレスにトラフィックを送信するクライアントは、ローカル ISP と公共インターネット経由でルーティングされてから、IP アドレスがアドバタイズされている Google リージョンに到達します。
    • Premium Network Service Tiers を選択すると、リージョン IP アドレスが Google のグローバル ネットワーク全体でアドバタイズされます。つまり、宛先がリージョン IP アドレスであっても、クライアント トラフィックはクライアントに可能な限り近い Google エッジ ピアリング ポイントで Google の高品質グローバル バックボーンに入ります。このロケーションでは、公共のインターネットを介してトラフィックが移動する距離を最小限に抑えることで、レイテンシを大幅に短縮し、パフォーマンスを向上させます。

グローバル外部ゲートウェイをデプロイする

次の例は、グローバル外部 Gateway に関連付けられ、Certificate Manager と HTTPRoute を使用して証明書マップにグループ化された複数の証明書を持つストア アプリケーションを公開する方法を示しています。

証明書マップを作成する

ゲートウェイごとに 15 個以上の証明書が必要な場合や、ワイルドカード証明書を使用する必要がある場合は、Certificate Manager を使用して証明書を管理することをおすすめします。

Kubernetes Secret または Google マネージド SSL 証明書を使用して外部ゲートウェイを保護することもできます。詳細については、Gateway のセキュリティをご覧ください。

このセクションでは、Certificate Manager を使用して証明書を作成し、クラスタ上で実行されるアプリケーションを保護します。

  1. Certificate Manager API を有効にします。

    gcloud services enable certificatemanager.googleapis.com 
  2. 証明書マップを作成します。

    gcloud beta certificate-manager maps create store-example-com-map 
  3. Google マネージド証明書と鍵を証明書に読み込みます。

    gcloud beta certificate-manager certificates create store-example-com-cert \     --certificate-file="CERTIFICATE_FILE" \     --private-key-file="PRIVATE_KEY_FILE" 

    次のように置き換えます。

    • CERTIFICATE_FILE: 証明書ファイルの名前。ファイルの拡張子は .pem にする必要があります。例: cert.pem
    • PRIVATE_KEY_FILE: 秘密鍵ファイルの名前。

    詳細については、秘密鍵と証明書を作成するをご覧ください。

  4. CertificateMapEntry を作成します。これにより、証明書を証明書マップに割り当てます。

    gcloud beta certificate-manager maps entries create store-example-com-map-entry \     --map=store-example-com-map \     --hostname=store.example.com \     --certificates=store-example-com-cert 

Kubernetes Secret や SSL 証明書など、証明書の他のソースを使用して Gateway を保護する方法については、Gateway を保護するをご覧ください。

ゲートウェイを作成する

Gateway リソースは、Kubernetes のトラフィックをルーティングするデータプレーンを表します。Gateway は、使用する GatewayClass に応じて、さまざまなロード バランシングとルーティングを表すことができます。

Gateway リソースの詳細については、Gateway リソースの説明または API 仕様をご覧ください。

このセクションでは、Gateway を作成します。アプリケーション チームは、Route を個別にデプロイして Gateway に安全に接続することで、Gateway を使用してアプリケーションをインターネットに公開できます。

  1. 次のマニフェストを gateway.yaml という名前のファイルに保存します。

    kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata:   name: external-http   annotations:     networking.gke.io/certmap: store-example-com-map spec:   # This GatewayClass uses a global external Application Load Balancer.   gatewayClassName: gke-l7-global-external-managed   listeners:   - name: https     protocol: HTTPS     port: 443  

    このマニフェストでは、次のプロパティを持つゲートウェイが記述されています。

    • gatewayClassName: gke-l7-global-external-managed: この Gateway の GatewayClass を指定します。このゲートウェイ クラスは、グローバル外部アプリケーション ロードバランサを使用します。
    • protocol: HTTPSport: 443: Gateway が HTTPS トラフィック用にポート 443 を公開することを指定します。これらのフィールドにより TLS が有効になります。
    • networking.gke.io/certmap: store-example-com-map: Certificate Manager の証明書マップの名前を指定します。

    TLS はアノテーション networking.gke.io/certmap を使用して Certificate Manager で構成されるため、TLS セクションはありません。

  2. マニフェストをクラスタに適用します。

    kubectl apply -f gateway.yaml 

    GKE がリソースをデプロイするまでに数分かかることがあります。

  3. Gateway のデプロイが成功したことを確認します。

    kubectl describe gateway 

    出力は次のようになります。

    Name:         external-http Namespace:    default Labels:       <none> ... Spec:   Gateway Class Name:  gke-l7-global-external-managed   Listeners:     Allowed Routes:       Namespaces:         From:  Same     Name:      https     Port:      443     Protocol:  HTTPS     Tls:       Certificate Refs:         Group:         Kind:   Secret         Name:   store-example-com       Mode:     Terminate  ... 

    この出力は、クラスタにデプロイされた Gateway にロードバランサとパブリック IP アドレスがあることを示しています。Gateway には Route がありません。つまり、バックエンドにトラフィックを送信できません。Route を使用しないと、すべてのトラフィックがデフォルトのバックエンドに転送され、HTTP 404 レスポンスが返されます。次のセクションでは Route をデプロイして、バックエンドにトラフィックを送信するように Gateway に指示します。

デモ アプリケーションをデプロイする

アプリケーション チームは、Gateway のデプロイとは別にアプリケーションと Route をデプロイできます。アプリケーション チームで Gateway を所有し、アプリケーション専用のリソースとしてデプロイすることもできます。Gateway と Route のさまざまな所有権モデルについては、Route のバインディングをご覧ください。この例では、ストアチームがアプリケーションと付属の HTTPRoute をデプロイし、前のセクションで作成した external-http Gateway 経由でアプリを公開します。

HTTPRoute フィールドの詳細については、API 仕様をご覧ください。

  1. サンプル アプリケーションをクラスタにデプロイします。

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml 

    このサンプル アプリケーションは、store-v1store-v2store-german という名前の 3 つの Deployment と 3 つの Service を作成します。

  2. アプリケーションのデプロイが成功したことを確認します。

    kubectl get pod 

    出力は次のようになります。

    NAME                            READY   STATUS    RESTARTS   AGE store-german-66dcb75977-5gr2n   1/1     Running   0          38s store-v1-65b47557df-jkjbm       1/1     Running   0          14m store-v2-6856f59f7f-sq889       1/1     Running   0          14m 
  3. Service が正常にデプロイされたことを確認します。

    kubectl get service 

    出力は次のようになります。

    NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE store-german   ClusterIP   10.48.3.183   <none>        8080/TCP   4s store-v1       ClusterIP   10.48.2.224   <none>        8080/TCP   5s store-v2       ClusterIP   10.48.4.48    <none>        8080/TCP   5s 

HTTPRoute を作成する

ルートリソースは、ゲートウェイから Kubernetes バックエンドにトラフィックをマッピングするためのプロトコル固有のルールを定義します。HTTPRoute リソースは、HTTP および HTTPS トラフィックの照合とフィルタリングを行います。これは、すべての gke-l7-* GatewayClass でサポートされています。

このセクションでは、HTTPRoute をデプロイします。これにより、サンプル アプリケーションに到達するために必要なルーティング ルールでゲートウェイが構成されます。

  1. 次のマニフェストを store-route-external.yaml という名前のファイルに保存します。

    kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata:   name: store-external spec:   parentRefs:   # Bind the route to the 'external-http' Gateway.   - kind: Gateway     name: external-http   hostnames:   - "store.example.com"   rules:   # Default rule for store.example.com that sends traffic to the store-v1 service.   - backendRefs:     - name: store-v1       port: 8080   # Match requests with the "env: canary" header and send them to the store-v2 service.   - matches:     - headers:       - name: env         value: canary     backendRefs:     - name: store-v2       port: 8080   # Match requests with the path "/de" and sends them to the store-german service.   - matches:     - path:         value: /de     backendRefs:     - name: store-german       port: 8080 

    このマニフェストでは、external-http Gateway を参照する HTTPRoute を記述しています。

  2. マニフェストをクラスタに適用します。

    kubectl apply -f store-route-external.yaml 

    store HTTPRoute は parentRefs プロパティを使用して external-http Gateway にバインドされます。次の図は、基盤となるロードバランサで構成されたルーティング ルールを示しています。

    ストアの HTTPRoute によって構成されたルーティング ルール

    ルーティング ルールは、HTTP トラフィックを次のように処理します。

    • store.example.com/de へのトラフィックは Service store-german に転送されます。
    • HTTP ヘッダー "env: canary" を含む store.example.com へのトラフィックは、Service store-v2 に転送されます。
    • store.example.com への残りのトラフィックは、Service store-v1 に転送されます。
  3. HTTPRoute がデプロイされていることを確認します。

    kubectl describe httproute store-external 

    出力は次のようになります。

    Name:         store-external Namespace:    default Labels:       <none> Annotations:  <none> API Version:  gateway.networking.k8s.io/v1 Kind:         HTTPRoute # Multiple lines are omitted here. Spec:   Hostnames:     store.example.com   Parent Refs:     Group:  gateway.networking.k8s.io     Kind:   Gateway     Name:   external-http   Rules:     Backend Refs:       Group:       Kind:    Service       Name:    store-v1       Port:    8080       Weight:  1     Matches:       Path:         Type:   PathPrefix         Value:  /     Backend Refs:       Group:       Kind:    Service       Name:    store-v2       Port:    8080       Weight:  1     Matches:       Headers:         Name:   env         Type:   Exact         Value:  canary       Path:         Type:   PathPrefix         Value:  /     Backend Refs:       Group:       Kind:    Service       Name:    store-german       Port:    8080       Weight:  1     Matches:       Path:         Type:   PathPrefix         Value:  /de Status:   Parents:     # This section shows the status of this route in relation to each Gateway attached.     Conditions:       Last Transition Time:  2022-11-01T05:42:31Z       Message:       Reason:                Accepted       Status:                True # Means that the Gateway has validated and accepted this route's configuration.       Type:                  Accepted       Last Transition Time:  2022-11-01T05:43:18Z       Message:       Reason:                ReconciliationSucceeded       Status:                True       Type:                  Reconciled     Controller Name:         networking.gke.io/gateway     Parent Ref:       Group:  gateway.networking.k8s.io       Kind:   Gateway       Name:   external-http Events:   Type     Reason  Age    From                   Message   ----     ------  ----   ----                   -------   Normal   ADD     2m48s  sc-gateway-controller  default/store-external   Normal  SYNC  61s (x3 over 2m27s)  sc-gateway-controller  Bind of HTTPRoute "default/store-external" to ParentRef Group:       "gateway.networking.k8s.io",   ... 
  4. HTTPRoute が Gateway にバインドされていることを確認します。

    kubectl describe gateway external-http 

    出力は次のようになります。

    Name:         external-http Namespace:    default Labels:       <none> # Multiple lines are omitted here. Status:   Addresses:     Type:   IPAddress     Value:  34.149.207.45   Conditions:     Last Transition Time:  2022-11-01T05:37:21Z     Message:     Reason:                Scheduled     Status:                True     Type:                  Scheduled     Last Transition Time:  2022-11-01T05:43:18Z     Message:     Reason:                Ready     Status:                True     Type:                  Ready   Listeners:     Attached Routes:  1     Conditions:       Last Transition Time:  2022-11-01T05:43:18Z       Message:       Reason:                Ready       Status:                True       Type:                  Ready     Name:                    https     Supported Kinds:       Group:  gateway.networking.k8s.io       Kind:   HTTPRoute       # Multiple lines are omitted here. 

アプリケーションにトラフィックを送信する

Gateway、Route、アプリケーションがクラスタにデプロイされたので、トラフィックをアプリケーションに渡します。

  1. Gateway の IP アドレスを取得します。

    kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}" 

    出力は IP アドレスです。

  2. VM を作成します。

    gcloud cloud-shell ssh 
  3. VM からゲートウェイ IP アドレスにトラフィックを送信します。example.com ホスト名を所有していないため、host ヘッダーを手動で設定する必要があります。

    curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v 

    GATEWAY_IP_ADDRESS は、前の手順のゲートウェイの IP アドレスに置き換えます。

    cacert.pem: 生成した証明書ファイル。Gateway への接続に使用しているマシンに、このファイルを保存する必要があります。

    出力には、アプリの実場所に関するデモアプリからの情報が表示されます。

    {   "cluster_name": "gke1",   "host_header": "store.example.com",   "metadata": "store-v1",   "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",   "pod_name": "store-v1-84b47c7f58-pmgmk",   "pod_name_emoji": "💇🏼‍♀️",   "project_id": "gateway-demo-243723",   "timestamp": "2022-09-25T13:31:17",   "zone": "us-central1-a" } 
  4. store.example.com/de にあるドイツ語版の store サービスにアクセスして、パスの照合をテストします。

    curl https://store.example.com/de --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v 

    出力で、リクエストが store-german Pod で処理されたことを確認できます。

    {   "cluster_name": "gke1",   "host_header": "store.example.com",   "metadata": "Gutentag!",   "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal",   "pod_name": "store-german-5cb6474c55-lq5pl",   "pod_name_emoji": "🧞‍♀",   "project_id": "gateway-demo-243723",   "timestamp": "2022-09-25T13:35:37",   "zone": "us-central1-a" } 
  5. env: canary HTTP ヘッダーを使用して、store Service のカナリア バージョンにトラフィックを送信します。

    curl -H "env: canary" https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v 

    出力で、リクエストが store-v2 Pod で処理されたことを確認できます。

    {   "cluster_name": "gke1",   "host_header": "store.example.com",   "metadata": "store-v2",   "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",   "pod_name": "store-v2-5788476cbd-s9thb",   "pod_name_emoji": "👩🏿",   "project_id": "gateway-demo-243723",   "timestamp": "2022-09-25T13:38:26",   "zone": "us-central1-a" } 

リージョン外部 Gateway をデプロイする

次の例は、セルフマネージド証明書と HTTPRoute を使用して、リージョン外部 Gateway に関連付けられた複数の証明書を持つストア アプリケーションを公開する方法を示しています。

リージョン Gateway のプロキシ サブネットを作成する

リージョン外部アプリケーション ロードバランサを使用する Gateway を作成する前に、プロキシ専用サブネットを構成する必要があります。リージョン外部アプリケーション ロードバランサを使用する VPC の各リージョンには、external_managed_proxy サブネットが必要です。このサブネットは、ロードバランサ プロキシに内部 IP アドレスを提供します。

証明書を作成してクライアント トラフィックを保護する

認証局(CA)から発行された検証済みの証明書を使用するか、自己署名証明書を作成できます。証明書の作成方法の詳細については、Kubernetes Secret に証明書を保存するをご覧ください。

クライアントとリージョン ゲートウェイの間のトラフィックを保護するには、次の方法を使用します。

  • Google マネージドまたはセルフマネージドの Certificate Manager 証明書
  • セルフマネージド リージョン SSL 証明書
  • Kubernetes Secret

CertificateMap または Google マネージド SSL 証明書は、リージョン ゲートウェイでサポートされていません。

詳細については、証明書と Google Cloud ロードバランサをご覧ください。

リージョン外部 HTTP(S) Gateway を作成する

  1. 外部ロードバランサのリージョン静的 IP アドレスを作成します。

    gcloud compute addresses create IP_ADDRESS_NAME \   --region=COMPUTE_REGION \   --network-tier=STANDARD 

    次のように置き換えます。

    • IP_ADDRESS_NAME: 新しい静的 IP アドレスの名前。
    • COMPUTE_REGION: クラスタが動作している Compute Engine リージョン。
  2. 次のようにセルフマネージド証明書を使用して、リージョン外部アプリケーション ロードバランサ ゲートウェイを作成し、マニフェストを regional-gateway.yaml として保存します。

      kind: Gateway   apiVersion: gateway.networking.k8s.io/v1   metadata:     name: external-regional-http   spec:     # Name of an existing GatewayClass.     gatewayClassName: gke-l7-regional-external-managed     # Listen for HTTPS traffic on port 443     listeners:     - name: https       protocol: HTTPS       port: 443       tls:         # Terminate the TLS session with the client at the Gateway.         mode: Terminate         # Certificates for the Gateway to use to create a new TLS session.         certificateRefs:         - name: store-example-com     # The name of the static IP address of the external load balancer.     # You can also use the `IPAddress` type to specify the actual IP address.     addresses:     - type: NamedAddress       value: IP_ADDRESS_NAME 
  3. regional-gateway マニフェストを適用します。

      kubectl apply -f regional-gateway.yaml 
  4. 構成を確認します。

      kubectl get gateway 

    出力は次のようになります。

    NAME            CLASS                              ADDRESS         READY   AGE external-http   gke-l7-regional-external-managed   35.118.32.224   True    49s 

    詳細を取得するには、describe コマンドを使用します。

    kubectl describe gateway 

    出力は次のようになります。

    Name:         external-regional-http Namespace:    default Labels:       <none> ... Spec:   Gateway Class Name:  gke-l7-regional-external-managed   Listeners:     Allowed Routes:       Namespaces:         From:  Same     Name:      https     Port:      443     Protocol:  HTTPS     Tls:       Certificate Refs:         Group:         Kind:   Secret         Name:   store-example-com       Mode:     Terminate   ... 

デモ アプリケーションをデプロイする

Gateway のデプロイとは別に、アプリケーションとルートをデプロイできます。

デモ アプリケーションのデプロイ方法については、デモ アプリケーションをデプロイするをご覧ください。

HTTPRoute を作成する

HTTP および HTTPS トラフィックの照合とフィルタリングを行うには、HTTPRoute を作成する必要があります。

アプリケーションにトラフィックを送信する

アプリケーションをデプロイして HTTPRoute を作成したら、アプリケーションにトラフィックを渡すことができます。

アプリケーションにトラフィックを送信する方法については、アプリケーションにトラフィックを送信するをご覧ください。

共有 Gateway を使用する

Gateway API は、個別のリソース(Gateway と Route のリソース)を使用して、ロードバランサとルーティング ルールをデプロイします。これは、1 つのリソースですべてを併用する Ingress とは異なります。リソース間で責任を分担することで、Gateway により、ロードバランサとルーティング ルールが別々にデプロイされ、異なるユーザーまたはチーム間でデプロイされるようになります。これにより、Gateway を複数の異なる Route で接続される共有 Gateway にし、Namespace が異なる場合でも、個々のチームで完全に所有し、管理できるようになります。

共有 Gateway に対するルートをデプロイする

この例は、内部 Gateway のデプロイでデプロイした internal-http Gateway を基盤としています。

この例では、サイトチームがアプリケーション、Service、HTTPRoute をデプロイして、Gateway からこれらの Service へのトラフィックを照合します。

  1. サンプル アプリケーションをデプロイします。

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/site.yaml 
  2. 次のマニフェストを site-route-internal.yaml という名前のファイルに保存します。

    kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata:   name: site-internal spec:   # Attach the HTTPRoute to the `internal-http` Gateway.   parentRefs:   - kind: Gateway     name: internal-http   # Route requests that have `site.example.com` in the Host header.   hostnames:   - "site.example.com"   # Send all requests to the `site-v1` Service.   rules:   - backendRefs:     - name: site-v1       port: 8080 

    このマニフェストでは、site.example.com のすべてのトラフィックを照合し、一致したものを site-v1 Service にルーティングする HTTPRoute を記述しています。

  3. マニフェストをクラスタに適用します。

    kubectl apply -f site-route-internal.yaml 
  4. HTTPRoute が Gateway に接続されていることを確認します。

    kubectl describe httproute.gateway.networking.k8s.io site-internal 

    出力は次のようになります。

    Status:   Parents:     Conditions:       Last Transition Time:  2023-01-09T15:05:43Z       Message:       Reason:                Accepted       Status:                True       Type:                  Accepted       Last Transition Time:  2023-01-09T15:05:43Z       Message:       Reason:                ReconciliationSucceeded       Status:                True       Type:                  Reconciled     Controller Name:         networking.gke.io/gateway     Parent Ref:       Group:  gateway.networking.k8s.io       Kind:   Gateway       Name:   internal-http       ... 

    Gateway の Accepted 条件が True の場合、HTTPRoute は Gateway に正常にバインドされています。[Status] フィールドの詳細については、ルートのステータスをご覧ください。

  5. Gateway へのトラフィックが正しくルーティングされていることを確認します。

    curl -H "host: site.example.com" GATEWAY_IP_ADDRESS curl -H "host: store.example.com" GATEWAY_IP_ADDRESS 

    GATEWAY_IP_ADDRESS は、内部 Gateway の IP アドレスに置き換えます。

    Gateway と同じ VPC で仮想マシン(VM)を使用する必要があります。

    出力は次のようになります。

    {   "cluster_name": "CLUSTER_NAME",   "host_header": "site.example.com",   "metadata": "site-v1",   "pod_name": "site-v1-5d64fc4d7d-fz6f6",   "pod_name_emoji": "👩🏼‍🍳",   "project_id": "PROJECT_ID",   "timestamp": "2022-11-02T19:07:01",   "zone": "ZONE_NAME" } ... {   "cluster_name": "CLUSTER_NAME",   "host_header": "store.example.com",   "metadata": "store-v1",   "pod_name": "store-v1-6d8d58d78-vz8pn",   "pod_name_emoji": "🧝🏻‍♂️",   "project_id": "PROJECT_ID",   "timestamp": "2022-11-02T19:07:01",   "zone": "ZONE_NAME" } 

    この出力は、site.example.com ホストヘッダーを含むリクエストが site-v1 Service に到達し、store.example.com ホストヘッダーを含むリクエストが store-v1 Service に到達することを示しています。

ネットワーク ティアを構成する

リージョン外部アプリケーション ロードバランサのリスナー アドレスのネットワーク ティアは、ゲートウェイ定義の addresses[] 配列内の type フィールドを使用して指定できます。ネットワーク ティアを指定しない場合、ゲートウェイはデフォルトでスタンダード ティアのエフェメラル IP アドレスを使用します。

type フィールドには、次の値を使用します。

  • networking.gke.io/premium-ephemeral-ipv4-address: プレミアム ティアの IP アドレスを割り当てます。
  • networking.gke.io/standard-ephemeral-ipv4-address: スタンダード ティアの IP アドレスを割り当てます。

両方のネットワーク ティアから IP アドレスを割り当てるには、addresses フィールドに両方のタイプを指定します。

次の例は、 Google Cloud でゲートウェイにプレミアム ティアの IP アドレスを割り当てる方法を示しています。スタンダード ティアの IP アドレスをプロビジョニングするには、networking.gke.io/standard-ephemeral-ipv4-address を使用します。

  1. 次のサンプル マニフェストを external-regional-http.yaml として保存します。

    kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata:   name: external-regional-http spec:   # Name of an existing GatewayClass.   gatewayClassName: gke-l7-regional-external-managed   # Listen for HTTPS traffic on port 443.   listeners:   - name: https     protocol: HTTPS     port: 443     tls:       # Terminate the TLS session with the client at the Gateway.       mode: Terminate       # Certificates for the Gateway to use to create a new TLS session.       certificateRefs:       - name: store-example-com     addresses:     # Request a Premium Tier ephemeral IPv4 address for the Gateway.     - type: networking.gke.io/premium-ephemeral-ipv4-address 
  2. サンプル マニフェストを適用します。

    kubectl apply -f external-regional-http.yaml 

ゲートウェイのデフォルト バックエンドを構成する

すべての gke-l7-* GatewayClass は、一致しないトラフィックに対して HTTP 404 を返します。一致しないトラフィックをユーザー指定の Service に送信する明示的なデフォルト Route を使用して、デフォルト バックエンドを構成できます。

明示的なバックエンド定義がなくても、404(Not Found)や 500(Server Error)などのエラーコードを処理するように Gateway が構成されています。デフォルトの動作は、Gateway の実装によって異なる場合があります。エラー処理をより細かく制御するには、カスタム バックエンドの構成を検討してください。

次の HTTPRoute は、デフォルトのバックエンドをカスタマイズする方法の一例です。次のような HTTPRoute を適用すると、暗黙的なデフォルト バックエンドよりも優先されます。

kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata:   name: custom-default-backend spec:   parentRefs:   - kind: Gateway     name: my-internal-gateway   # Omit the `hostnames` field to route all unmatched traffic from the   # attached Gateway.   rules:   - backendRefs:     - name: my-custom-default-backend-service       port: 8080 

この HTTPRoute は特定の Gateway のすべてのトラフィックに一致します。このようなルールは Gateway ごとに 1 つだけ設定できます。そうでない場合は、ルールが競合して優先順位が適用されます。

デフォルトのバックエンドを使用して、すべての Gateway トラフィックをルーティングするデフォルト ルートのバックエンドが作成されないようにすることができます。明示的な HTTPRoute は、競合するルーティング ルールを持つ新しい HTTPRoutes よりも常に優先されます。

Gateway に静的 IP アドレスを構成する

どのゲートウェイにもトラフィックのリッスンに使用する IP アドレスがあります。ゲートウェイの IP アドレスを指定しない場合、ゲートウェイ コントローラが自動的に IP アドレスを割り当てます。ゲートウェイのライフサイクルとは独立して IP アドレスが存在するように、静的 IP アドレスを作成することもできます。

ゲートウェイがデプロイされると、ステータス フィールドにゲートウェイの IP アドレスが表示されます。

kind: Gateway ... status:   addresses:     - value: 10.15.32.3 

GatewayClass に応じて、IP アドレスは次のサブネットから割り振られます。

GatewayClasses デフォルトの IP アドレスプール
  • gke-l7-rilb
  • gke-l7-rilb-mc
  • プライマリ ノードの IPv4 / IPv6 アドレス範囲のリージョン プライベート IP アドレス
  • gke-l7-regional-external-managed
  • gke-l7-regional-external-managed-mc
  • Google のリージョン外部 IPv4 / IPv6 範囲のリージョン パブリック IP アドレス
  • gke-l7-global-external-managed
  • gke-l7-global-external-managed-mc
  • gke-l7-gxlb
  • gke-l7-gxlb-mc
  • Google のグローバル外部 IPv4 / IPv6 範囲のグローバル パブリック IP アドレス

    addresses.NamedAddress フィールドを使用すると、Gateway とは無関係に IP アドレスを指定できます。ゲートウェイのデプロイ前に静的 IP アドレス リソースを作成できます。これらのリソースは、NamedAddress によって参照されます。Gateway が削除されても、静的 IP アドレスは再利用できます。

    名前付き IP アドレスを使用する

    IPv4 または IPv6 アドレスを構成するには、NamedAddress を指定します。Gateway を作成する前に、静的 IP アドレスをプロビジョニングする必要があります。

    1. 静的 IP アドレス リソースを作成します。

      gcloud compute addresses create IP_ADDRESS_NAME \     --purpose=SHARED_LOADBALANCER_VIP \     --region=COMPUTE_REGION \     --subnet=SUBNET \     --project=PROJECT_ID 

      次のように置き換えます。

      • IP_ADDRESS_NAME: 新しい静的 IP アドレスの名前
      • COMPUTE_REGION: リージョン Gateway の場合、クラスタが実行されている Compute Engine リージョン。このフラグは、グローバル外部 Gateway には必要ありません。
      • SUBNET: IP アドレスのサブネット。このフラグは、グローバル外部 Gateway には必要ありません。
      • PROJECT_ID: GKE クラスタが実行されているプロジェクト。
    2. 次のマニフェストを named-ip-gateway.yaml という名前のファイルに保存します。

      kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata:   name: internal-http spec:   gatewayClassName: gke-l7-rilb   listeners:   - name: http     protocol: HTTP     port: 80   addresses:   - type: NamedAddress     value: IP_ADDRESS_NAME 

      このマニフェストでは、指定された IP アドレスを参照する Gateway を記述しています。

    3. マニフェストをクラスタに適用します。

      kubectl apply -f named-ip-gateway.yaml 
    4. Gateway の IP アドレスを確認します。

      kubectl describe gateway internal-http 

      出力は次のようになります。

      Name:         internal-http Namespace:    default Labels:       <none> ... Spec:   Addresses:     Type:              NamedAddress     Value:             IP_ADDRESS_NAME   Gateway Class Name:  gke-l7-rilb   Listeners:     Allowed Routes:       Namespaces:         From:  Same     Name:      http     Port:      80     Protocol:  HTTP Status:   Addresses:     Type:   IPAddress     Value:  10.15.32.103 

    HTTP から HTTPS へのリダイレクトを構成する

    Cloud Load Balancing には、HTTP から HTTPS へのリダイレクト機能が用意されています。外部アプリケーション ロードバランサは、同じ IP アドレスを使用する HTTPS ロードバランサに、暗号化されていない HTTP リクエストをリダイレクトします。HTTP から HTTPS へのリダイレクトを有効にして Gateway を作成すると、この両方のロードバランサが自動的に作成されます。ポート 80 の Gateway の外部 IP アドレスへのリクエストは、ポート 443 の同じ外部 IP アドレスに自動的にリダイレクトされます。

    デフォルトでは、HTTP から HTTPS へのリダイレクトは Gateway で定義されていません。

    HTTP トラフィックを HTTPS にリダイレクトするには、HTTP と HTTPS の両方のトラフィックを処理するように Gateway を構成します。HTTP または HTTPS を無効にすると、Gateway はトラフィックをリダイレクトしません。

    次の例では、クライアントからウェブ アプリケーションに向うトラフィックが常に安全なページにリダイレクトされるようにするために、HTTP から HTTPS へのリダイレクトを使用する方法を示します。

    HTTP から HTTPS へのリダイレクトは、gke-l7-gxlbgke-l7-gxlb-mc の GatewayClass ではサポートされていません。各 GatewayClass でサポートされている機能の詳細については、GatewayClass の機能をご覧ください。

    インフラストラクチャ Namespace からの HTTP トラフィックをリダイレクトする

    場合によっては、インフラストラクチャやプラットフォームの管理チームとアプリケーション チームとの間に明確な違いがなく、Gateway の誤用防止が課題になることがあります。

    次の例では、HTTP リスナーの使用をさらに制限して、アプリケーション チームが誤ってセキュアでないプロトコルを使用しないようにします。この例では、ルートが otherInfra: httpToHttps ラベルを持つ名前空間にある場合にのみ HTTPRoute が HTTP リスナーを使用できるようにゲートウェイを構成します。ただし、ゲートウェイは、任意の名前空間の HTTPRoute が HTTPS リスナーを使用できるようにします。Kubernetes RBAC を使用して http-redirect 名前空間を制限することで、アプリケーション チームが誤ってこの名前空間に HTTPRoute を作成しないようにします。

    1. ゲートウェイの名前空間を作成し、マニフェストを gateway-namespace.yaml として保存します。

      apiVersion: v1 kind: Namespace metadata:   name: gateway-infra 
    2. 次のようにマニフェストを適用します。

      kubectl apply -f gateway-namespace.yaml 
    3. ゲートウェイの名前空間を作成し、マニフェストを redirect-namespace.yaml として保存します。

      apiVersion: v1 kind: Namespace metadata:   name: http-redirect   labels:     otherInfra: httpToHttps 

      この http-redirect 名前空間には otherInfra: httpToHttps ラベルがあります。

    4. 次のようにマニフェストを適用します。

      kubectl apply -f redirect-namespace.yaml 
    5. HTTP リスナーの使用を制限するには、次のマニフェストを使用して Gateway を作成します。マニフェストを external-gateway.yaml として保存します。

      kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata:   name: external-http   namespace: gateway-infra spec:   # Name of an existing GatewayClass.   gatewayClassName: gke-l7-global-external-managed   listeners:   - name: http     protocol: HTTP     port: 80     #  Allow only HTTPRoutes from namespaces that have the     # `otherInfra: httpToHttps` label to use this listener.     allowedRoutes:       kinds:       - kind: HTTPRoute       namespaces:         from: Selector         selector:           matchLabels:             otherInfra: httpToHttps   - name: https     protocol: HTTPS     port: 443     # Allow HTTPRoutes from any namespace to use this listener.     allowedRoutes:       kinds:       - kind: HTTPRoute       namespaces:         from: All     tls:       mode: Terminate       options:         networking.gke.io/pre-shared-certs: store-example-com 
      • namespace フィールドには、Gateway が gateway-infra Namespace に作成されることを指定します。

      • allowedRoutes セクションの namespaces フィールドは、HTTP リスナーをラベル otherInfra: httpToHttps と一致する Namespace に制限します。

    6. 次のようにマニフェストを適用します。

      kubectl apply -f external-gateway.yaml 
    7. HTTPS リダイレクトを強制するには、次のマニフェストを使用してデフォルトの HTTPRoute を作成します。マニフェストを http-redirect.yaml として保存します。

      kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata:   name: redirect   # Create the HTTPRoute in the `http-redirect` namespace.   namespace: http-redirect spec:   # Attach the HTTPRoute to the `http` listener in the `external-http`   # Gateway.   parentRefs:   - namespace: gateway-infra     name: external-http     sectionName: http   rules:   # Respond to the request with an HTTPS redirection.   - filters:     - type: RequestRedirect       requestRedirect:         scheme: https 
      • sectionName フィールドは、http リスナーのみで照合するように Gateway に指示します。RequestRedirect フィルタは、HTTPS リスナーへのリダイレクトを強制します。
    8. 次のようにマニフェストを適用します。

      kubectl apply -f http-redirect.yaml 
    9. 次のマニフェストを使用して、アプリケーションの Service を作成します。マニフェストを service-deployment.yaml として保存します。

      apiVersion: v1 kind: Service metadata:   name: store-v1 spec:   selector:     app: store     version: v1   ports:   - port: 8080     targetPort: 8080 --- apiVersion: apps/v1 kind: Deployment metadata:   name: store-v1 spec:   replicas: 2   selector:     matchLabels:       app: store       version: v1   template:     metadata:       labels:         app: store         version: v1     spec:       containers:       - name: whereami         image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1         ports:         - containerPort: 8080         env:         - name: METADATA           value: "store-v1" 
    10. 次のようにマニフェストを適用します。

      kubectl apply -f service-deployment.yaml 
    11. 次のマニフェストを使用して、HTTPS のみを許可するアプリケーションに HTTPRoute を作成します。マニフェストを http-route.yaml として保存します。

      kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata:   name: store-external   labels:     gateway: external-http spec:   # Attach the HTTPRoute to the HTTPS listener in the `external-http`   # Gateway.   parentRefs:   - name: external-http     namespace: gateway-infra     sectionName: https   # Match requests that have the `store.example.com` Host header.   hostnames:   - "store.example.com"   # Route requests to the `store-v1` Service.   rules:   - backendRefs:     - name: store-v1       port: 8080 
    12. 次のようにマニフェストを適用します。

      kubectl apply -f http-route.yaml 

    パス リダイレクトと URL の書き換えを構成する

    パス リダイレクトを使用すると、受信リクエストを 1 つの URL パスから別の URL パスにリダイレクトできます。パス リダイレクトを使用すると、古い URL や非推奨の URL を処理する必要がある場合に URL の構造を変更できます。

    URL の書き換えは、受信 URL を変更してからサーバーで処理する場合に役立ちます。これにより、基になるコンテンツやファイル構造を実際に変更することなく、URL の構造や形式を変更できます。URL の書き換えは、覚えやすく理解しやすい、ユーザー フレンドリーで SEO に適した URL を作成するのに便利です。デフォルトでは、パス リダイレクトと URL の書き換えは構成されていません。HTTPRoute のフィルタを使用して、これらのリダイレクトまたは書き換えを明示的に構成する必要があります。

    GKE Gateway はパス リダイレクトと URL の書き換えをサポートしています。詳細については、HTTP パス リダイレクトと書き換えをご覧ください。

    パス リダイレクトを構成する

    パス リダイレクトを構成して、パス全体または URL 内の接頭辞のみを置き換えることができます。

    パス全体を置き換える

    1. パス全体を置き換えるには、URL パスに接頭辞 /any-path を含む任意の URL を厳格な値 /new-path に置き換えるフィルタを HTTPRoute に構成します。

    2. 次のように HTTPRoute マニフェストを作成し、store.yaml という名前を付けます。

        apiVersion: gateway.networking.k8s.io/v1   kind: HTTPRoute   metadata:     name: store   spec:     parentRefs:     - kind: Gateway       name: external-http     hostnames:     - store.example.com     rules:     - matches:       - path:           # Match requests by a prefix, like `/any-path` and `/any-path/home`.           type: PathPrefix           value: /any-path       filters:       - type: RequestRedirect         requestRedirect:           path:             # Replace the full path with `/new-path`. For example, both             # `/any-path/home` and `/any-path` become `/new-path`.             type: ReplaceFullPath             replaceFullPath: /new-path           statusCode: 302 

      たとえば、このマニフェストでは、URL https://store.example.com/any-path/... へのルートが新しいロケーション https://store.example.com/new-path/ にリダイレクトされるように、HTTPRoute のルーティング ルールを設定しています。

    3. 次のようにマニフェストを適用します。

      kubectl apply -f store.yaml 

    このルーティング ルールは厳格なリダイレクト ルールに従っています。ブラウザは、リダイレクトをキャッシュに保存せず、最新バージョンにリダイレクトします。

    接頭辞のみを置き換える

    1. 接頭辞のみを置き換えるには、URL パスに接頭辞 /any-prefix が含まれる URL を厳格な値 /new-prefix に置き換えるフィルタを HTTPRoute に構成します。

    2. 次のように HTTPRoute マニフェストを作成し、store.yaml という名前を付けます。

      apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata:   name: store spec:   parentRefs:     - kind: Gateway       name: external-http   hostnames:   - store.example.com   rules:   - matches:       - path:           # Match requests by prefix, like `/any-prefix` and           # `/any-prefix/home`.           type: PathPrefix           value: /any-prefix     filters:     - type: RequestRedirect       requestRedirect:         path:           # Replace the matched prefix with `/new-prefix`. For example,           # `/any-prefix` becomes `/new-prefix` and `/any-prefix/home`           # becomes `/new-prefix/home`.           type: ReplacePrefixMatch           replacePrefixMatch: /new-prefix         statusCode: 302 

      たとえば、このマニフェストでは、URL https://store.example.com/any-path/v1/... へのルートが新しいロケーション https://store.example.com/new-path/v1/... にリダイレクトされるように、HTTPRoute のルーティング ルールを設定しています。

    3. 次のようにマニフェストを適用します。

        kubectl apply -f store.yaml 

    このルーティング ルールは、唯一のリダイレクト ルールに従っています。ブラウザは常に同じページにリダイレクトされます。

    URL の書き換えを構成する

    URL の書き換えを設定すると、ユーザーへの URL の表示方法を変更できます。URL の書き換えは、URL をよりユーザー フレンドリーにしたり、SEO を改善するために使用します。また、ユーザーを新しいページにリダイレクトする場合にも使用できます。

    ホスト名全体を書き換える

    ホスト名全体を書き換えるには:

    1. リクエスト ヘッダーの Host 情報を www.example.com から store.example.com に置き換えてから、リクエストをバックエンド サービスに転送するようにゲートウェイに指示するフィルタを HTTPRoute で構成します。

    2. 次のように HTTPRoute マニフェストを作成し、www.yaml という名前を付けます。

        apiVersion: gateway.networking.k8s.io/v1   kind: HTTPRoute   metadata:     name: www   spec:     parentRefs:       - kind: Gateway         name: external-http     hostnames:     - www.example.com     rules:     - filters:       - type: URLRewrite         # Replace the hostname in the URL with `store.example.com`.         urlRewrite:           hostname: store.example.com       backendRefs:       - name: store-v1         port: 8080 

      たとえば、上記の構成では、https://www.example.com へのリクエストは、Host: www.example.com ではなく、Host: store.example.com ヘッダーがあるバックエンド サービスに転送されます。

    3. 次のようにマニフェストを適用します。

        kubectl apply -f www.yaml 

    パス修飾子を使用して書き換える

    パス修飾子と組み合わせて書き換えを使用すると、リクエストをバックエンド サービスにリレーする前に、URL とパスに対して高度な変更を行うことができます。

    パス修飾子を使用して書き換えるには:

    1. www.example.comto store.example.com からのリクエスト ヘッダーで「ホスト」情報を置き換えるようにゲートウェイが指示するフィルタを HTTPRoute で構成し、値 /store を値 / に置き換えてから、リクエストをバックエンド サービスに転送します。

    2. 次のように HTTPRoute マニフェストを作成し、www.yaml という名前を付けます。

        apiVersion: gateway.networking.k8s.io/v1   kind: HTTPRoute   metadata:     name: www   spec:     parentRefs:       - kind: Gateway         name: external-http     hostnames:     - www.example.com     rules:     - matches:       - path:           type: PathPrefix           value: /store       filters:       - type: URLRewrite         # For URLs that have `/store` in the path, replace the hostname with         # store.example.com and replace the `/store` prefix with `/de`.         urlRewrite:           hostname: store.example.com           path:             type: ReplacePrefixMatch             replacePrefixMatch: /de       backendRefs:       - name: store-german         port: 8080 

      たとえば、上記の構成では、https://www.example.com/store/... へのリクエストはリクエスト ヘッダーに Host: www.example.com ではなく Host: store.example.com があるバックエンド サービスに転送され、/store/de に書き換えられます。

    3. 次のようにマニフェストを適用します。

      kubectl apply -f www.yaml 

    構成を確認する

    URL の書き換えフィルタまたはパス リダイレクト フィルタを使用して HTTPRoute の作成後にフィルタが適用されたことを確認するには、次の操作を行います。

    kubectl get httproute www -o yaml 

    出力は次のようになります。

      apiVersion: gateway.networking.k8s.io/v1   kind: HTTPRoute   metadata:     annotations:       kubectl.kubernetes.io/last-applied-configuration: |         {"apiVersion":"gateway.networking.k8s.io/v1","kind":"HTTPRoute","metadata":{"annotations":{},"name":"www","namespace":"default"},"spec":{"hostnames":["www.example.com"],"parentRefs":[{"kind":"Gateway","name":"external-http"}],"rules":[{"backendRefs":[{"name":"store-german","port":8080}],"filters":[{"type":"URLRewrite","urlRewrite":{"hostname":"store.example.com","path":{"replacePrefixMatch":"/de","type":"ReplacePrefixMatch"}}}],"matches":[{"path":{"type":"PathPrefix","value":"/store"}}]}]}}     creationTimestamp: "2023-06-22T01:00:42Z"     generation: 3     name: www     namespace: default     resourceVersion: "51268631"     uid: e516493e-806d-44d6-ae0d-1c9ff25682cf   spec:     hostnames:     - www.example.com     parentRefs:     - group: gateway.networking.k8s.io       kind: Gateway       name: external-http     rules:     - backendRefs:       - group: ""         kind: Service         name: store-german         port: 8080         weight: 1       filters:       - type: URLRewrite         urlRewrite:           hostname: store.example.com           path:             replacePrefixMatch: /de             type: ReplacePrefixMatch       matches:       - path:           type: PathPrefix           value: /store   status:     parents:     - conditions:       - lastTransitionTime: "2023-06-22T01:11:26Z"         message: ""         observedGeneration: 2         reason: Accepted         status: "True"         type: Accepted       - lastTransitionTime: "2023-06-22T01:11:26Z"         message: ""         observedGeneration: 2         reason: ReconciliationSucceeded         status: "True"         type: Reconciled       controllerName: networking.gke.io/gateway       parentRef:         group: gateway.networking.k8s.io         kind: Gateway         name: external-http  

    詳細を確認するには、describe コマンドを使用します。

    kubectl describe httproute 

    カスタム リクエストとレスポンス ヘッダーを構成する

    カスタム リクエスト ヘッダーとカスタム レスポンス ヘッダーを使用すると、HTTP(S) のリクエストとレスポンスに追加のヘッダーを指定できます。ロードバランサで検出された情報に応じて、これらのヘッダーには次の情報が含まれます。

    • クライアントまでのレイテンシ
    • クライアントの IP アドレスの地理的位置
    • TLS 接続のパラメータ

    デフォルトでは、バックエンド サービスとの間で送受信されるリクエストに追加されるカスタム ヘッダーはありません。HTTPRoute のフィルタを使用して、カスタム ヘッダーを明示的に構成する必要があります。

    カスタム ヘッダーを構成するには、次のように HTTPRoute のルールにフィルタ セクションを追加します。

    カスタム リクエスト ヘッダーを構成する

    RequestHeaderModifier フィルタを含む HTTPRoute マニフェストを作成し、http-route-request.yaml: として保存します。

      apiVersion: gateway.networking.k8s.io/v1   kind: HTTPRoute   metadata:     name: store   spec:     <...>     rules:         filters:           - type: RequestHeaderModifier             requestHeaderModifier:               <...> 

    次のようにマニフェストを適用します。

      kubectl apply -f http-route-request.yaml 

    カスタム レスポンス ヘッダーを構成する

    ResponseHeaderModifier フィルタを含む HTTPRoute マニフェストを作成し、http-route-response.yaml: として保存します。

    apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata:   name: store spec:   <...>   rules:       filters:         - type: ResponseHeaderModifier           responseHeaderModifier:             <...> 

    次のようにマニフェストを適用します。

      kubectl apply -f http-route-response.yaml 

    Gateway API の実装に説明されているように、ヘッダーの追加、設定、削除を行うことができます。Google Cloud でサポートされている変数を使用して、カスタム ヘッダーで HTTPRoute を構成できます。

    例 1:

    バックエンド サービスに送信する前にクライアントの位置情報を HTTP リクエストに追加する HTTPRoute を構成するには、HTTPRoute マニフェストを作成して external-http-request.yaml という名前を付けます。

      apiVersion: gateway.networking.k8s.io/v1   kind: HTTPRoute   metadata:     name: store   spec:     parentRefs:       - kind: Gateway         name: external-http     hostnames:     - store.example.com     rules:       - matches:         - path:             type: PathPrefix             value: /fr         filters:           # Add custom headers to requests that have `/fr` in the path.           - type: RequestHeaderModifier             requestHeaderModifier:               add:                 - name: X-Client-Geo-Location                   value: "{client_region},{client_city}"         backendRefs:           - name: store-french             port: 8080 

    たとえば、フランスのストラスブールにあるクライアントの場合、Gateway は X-Client-Geo-Location:FR,Strasbourg としてヘッダーを追加します。

    例 2:

    HTTP Strict Transport Security をサポートするカスタム レスポンス ヘッダーを追加する HTTPRoute を構成するには、HTTPRoute マニフェストを作成して external-http-response.yaml という名前を付けます。

      apiVersion: gateway.networking.k8s.io/v1   kind: HTTPRoute   metadata:     name: store   spec:     parentRefs:       - kind: Gateway         name: external-http     hostnames:     - store.example.com     rules:       - matches:         - path:             type: PathPrefix             value: /de         filters:           # Add custom headers to responses to requests that have `/de` in the           # path.           - type: ResponseHeaderModifier             responseHeaderModifier:               add:                 - name: Strict-Transport-Security                   value: max-age=63072000         backendRefs:           - name: store-german             port: 8080 

    構成を確認する

    1. カスタム リクエスト ヘッダーとカスタム レスポンス ヘッダーを構成した後に構成を確認するには、次の操作を行います。

        kubectl get httproute 

      出力は次のようになります。

        NAME    HOSTNAMES               AGE   store   ["store.example.com"]   4d23h 
    2. 詳細を確認するには、describe コマンドを使用します。

        kubectl describe httproute 

      出力は次のようになります。

        Name:         store   Namespace:    default   Labels:       <none>   Annotations:  <none>   API Version:  gateway.networking.k8s.io/v1   Kind:         HTTPRoute   Metadata:     Creation Timestamp:  2023-05-27T00:51:01Z     Generation:          5     Resource Version:    25418887     UID:                 2e07a1b8-420b-41b4-acd1-cecbfcd39f42   Spec:     Hostnames:       store.example.com     Parent Refs:       Group:  gateway.networking.k8s.io       Kind:   Gateway       Name:   external-http     Rules:       Backend Refs:         Group:         Kind:    Service         Name:    store-v1         Port:    8080         Weight:  1       Matches:         Path:           Type:   PathPrefix           Value:  /       Backend Refs:         Group:         Kind:    Service         Name:    store-v2         Port:    8080         Weight:  1       Matches:         Headers:           Name:   env           Type:   Exact           Value:  canary         Path:           Type:   PathPrefix           Value:  /       Backend Refs:         Group:         Kind:    Service         Name:    store-german         Port:    8080         Weight:  1       Filters:         Request Header Modifier:           Add:             Name:   X-Client-Geo-Location             Value:  {client_region},{client_city}         Type:       RequestHeaderModifier       Matches:         Path:           Type:   PathPrefix           Value:  /de   Status:     <...> 

    ルートのステータス

    HTTPRoute リソースは条件とイベントを出力します。これにより、HTTPRoute が 1 つ以上の Gateway と正常にバインドされたかどうか、または拒否されたかどうかを確認できます。

    HTTPRoute 条件

    HTTPRoute 条件は、Route とバインドされている Gateway のステータスを示します。1 つの Route は複数の Gateway にバインドできるため、これは、Gateway および Route と Gateway 間の個々の条件のリストとなります。

    • Accepted=True は、HTTPRoute が Gateway に正常にバインドされたことを示します。
    • Accepted=False は、HTTPRoute がこの Gateway とのバインディングで拒否されたことを示します。

    Gateway bindings 見出しに「Gateway」がない場合、HTTPRoute ラベルと Gateway ラベルセレクタが一致していない可能性場合があります。これは、どの Gateway も Route を選択していない場合に発生します。

    HTTPRoute イベント

    HTTPRoute イベントは、HTTPRoute のステータスの詳細を提供します。イベントは、次の理由でグループ化されます。

    • ADD イベントは、リソースの追加によってトリガーされます。
    • UPDATE イベントは、リソースの更新によってトリガーされます。
    • SYNC イベントは、定期的な調整でトリガーされます。

    ルートのマージ、優先度、検証

    ルートの優先順位

    Gateway API は、厳密な優先順位ルールを定義し、ルーティング ルールが重複している Route でトラフィックを照合する方法を制御します。重複する 2 つの HTTPRoute 間の優先順位は次のとおりです。

    1. ホスト名のマージ: 最も長い、または最も具体的なホスト名と一致。
    2. パスのマージ: 最も長い、または最も具体的なパスと一致。
    3. ヘッダーのマージ: 一致する HTTP ヘッダーの最大数。
    4. 競合: 前述の 3 つのルールが優先されない場合、最も古いタイムスタンプの HTTPRoute リソースが使用されます。

    ルートのマージ

    gke-l7 GatewayClasses の場合、特定の Gateway のすべての HTTPRoute は同じ URL マップリソースにマージされます。HTTPRoute をマージする方法は、HTTPRoute 間の重複のタイプによって異なります。前述の例の HTTPRoute は、ルートのマージと優先順位を示す 3 つの HTTPRoute に分割できます。

    1. ルートのマージ: 3 つの HTTPRoute はすべて同じ internal-http Gateway に接続されるため、1 つにマージされます。
    2. ホスト名のマージ: store.example.com の 3 つの Route がすべて一致するため、ホスト名ルールがマージされます。
    3. パスのマージ: store-german-route はより具体的なパス /de を持つため、マージされません。store-v1-route と store-v2-route はどちらも同じ /* パスと一致するため、これらのパスでマージされます。
    4. ヘッダーのマージ: store-v2-route には、store-v1-route よりも具体的な一連の HTTP ヘッダーの一致があるため、マージされません。
    5. 競合: Route をホスト名、パス、ヘッダーとマージできるため、競合は発生せず、すべてのルーティング ルールがトラフィックに適用されます。

    前述の例で使用した 1 つの HTTPRoute は、これらの 3 つのルートと同等です。

    kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata:   name: store-v1-route spec:   parentRefs:   - kind: Gateway     name: internal-http   hostnames:   - "store.example.com"   rules:   - backendRefs:     - kind: Service       name: store-v1       port: 8080 --- kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata:   name: store-v2-route spec:   parentRefs:   - kind: Gateway     name: internal-http   hostnames:   - "store.example.com"   rules:   - matches:     - headers:       - type: Exact         name: env         value: canary     backendRefs:     - kind: Service       name: store-v2       port: 8080 --- kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata:   name: store-german-route spec:   parentRefs:   - kind: Gateway     name: internal-http   hostnames:   - "store.example.com"   rules:   - matches:     - path:         type: PathPrefix         value: /de     backendRefs:     - kind: Service       name: store-german       port: 8080 

    Kubernetes Gateway と Istio Gateway

    Kubernetes Gateway API と Istio API にはどちらも Gateway という名前のリソースがあります。機能は似ていますが、同じリソースではありません。同じ Kubernetes クラスタで Istio と Gateway API を使用している場合、コマンドラインで kubectl を使用するときに名前の重複が発生します。kubectl get gateway は Kubernetes Gateway リソースを返すものの、Istio Gateway リソースは返さない場合があります。その逆も同様です。

    $ kubectl api-resources NAME       SHORTNAMES   APIGROUP                       NAMESPACED   KIND gateways   gw           networking.istio.io/v1beta1    true         Gateway gateways   gtw          networking.k8s.io/v1beta1      true         Gateway 

    Istio を使用して GKE 1.20 以降にアップグレードする場合は、Gateway リソースの省略名を使用するか、API グループを指定することをおすすめします。Kubernetes Gateway の省略名は gtw、Istio Gateway の省略名は gw です。次のコマンドは、Kubernetes Gateway リソースと Istio Gateway リソースをそれぞれ返します。

    # Kubernetes Gateway $ kubectl get gtw NAME                        CLASS multi-cluster-gateway       gke-l7-global-external-managed-mc  $ kubectl get gateway.networking.x-k8s.io NAME                        CLASS multi-cluster-gateway       gke-l7-global-external-managed-mc  # Istio Gateway $ kubectl get gw NAME               AGE bookinfo-gateway   64m  $ kubectl get gateway.networking.istio.io NAME               AGE bookinfo-gateway   64m 

    トラブルシューティング

    リージョンにプロキシ専用サブネットが存在しない

    症状:

    リージョン Gateway(内部または外部)を作成する際に、次の問題が発生する場合があります。

    generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/[REGION_NAME]/targetHttpProxies/gkegw-x5vt-default-internal-http-[ID]'. A reserved managed proxy subnetwork with purpose REGIONAL_MANAGED_PROXY is required. 

    理由:

    このエラー メッセージは、Gateway のリージョンにプロキシ専用サブネットが存在しないことを示します。

    回避策:

    この問題を解決するには、プロキシ専用サブネットを構成します。

    プロキシ専用サブネットが誤った目的でリージョンにすでに存在する

    症状:

    リージョン Gateway(内部または外部)にプロキシ専用サブネットを作成する際に、次の問題が発生する場合があります。

    ERROR: (gcloud.compute.networks.subnets.create) Could not fetch resource:  - The resource 'projects/[PROJECT_NAME]/regions/[REGION_NAME]/subnetworks/[PROXY_ONLY_SUBNET_NAME]' already exists 

    理由:

    このエラー メッセージは、すでにプロキシ専用サブネットが存在するリージョンにリージョン プロキシ専用サブネットを作成しようとしたことを示します。

    回避策:

    この問題を解決する手順は次のとおりです。

    1. リージョンにプロキシ専用サブネットがすでに存在することを確認し、目的が正しいことを確認します。

      1. サブネットを一覧取得して、リージョン内のプロキシ専用サブネットを見つけます。

        gcloud compute networks subnets list --regions=COMPUTE_REGION 

        COMPUTE_REGION は、リージョン Gateway を作成する Compute Engine リージョンに置き換えます。

      2. リージョン内のプロキシ専用サブネットの説明を取得して、目的を確認します。

        gcloud compute networks subnets describe PROXY_ONLY_SUBNET \     --region COMPUTE_REGION | grep -E 'name|purpose' 

        PROXY_ONLY_SUBNET は、プロキシ専用サブネットに置き換えます。

      GKE Gateway は、リージョン Gateway(内部またはリージョン)の REGIONAL_MANAGED_PROXY プロキシ専用サブネットのみをサポートします。

    2. リージョン内の既存のプロキシ専用サブネットが INTERNAL_HTTPS_LOAD_BALANCER の目的で作成された場合は、サブネットの目的を REGIONAL_MANAGED_PROXY に移行します。

    正常なアップストリームがない

    症状:

    Gateway を作成してもバックエンド サービスにアクセスできない場合(503 レスポンス コード)、次の問題が発生している可能性があります。

    no healthy upstream 

    理由:

    このエラー メッセージは、ヘルスチェック プローバーが正常なバックエンド サービスを見つけられないことを示します。バックエンド サービスは正常である可能性がありますが、ヘルスチェックのカスタマイズが必要になる場合もあります。

    回避策:

    この問題を解決するには、HealthCheckPolicy を使用して、アプリケーションの要件(/health など)に基づいてヘルスチェックをカスタマイズします。

    次のステップ