このドキュメントでは、内部マルチクラスタ Gateway をデプロイして、VPC ネットワーク内のトラフィックを 2 つの異なる GKE クラスタで実行されているアプリケーションにルーティングする実践的な例について説明します。
マルチクラスタ Gateway は、複数の GKE クラスタにデプロイされたサービスのトラフィックを管理する強力な方法を提供します。Google のグローバル ロード バランシング インフラストラクチャを使用すると、アプリケーションの単一のエントリ ポイントを作成できるため、管理が簡素化され、信頼性が向上します。このチュートリアルでは、サンプル store アプリケーションを使用して、オンライン ショッピング サービスを複数のチームが所有して管理し、共有 GKE クラスタのフリート全体にデプロイしている実際のシナリオをシミュレートします。
始める前に
マルチクラスタ Gateway をデプロイする前に環境を用意する必要があります。続行する前に、マルチクラスタ Gateway 用に環境を準備するの手順を行ってください。
GKE クラスタをデプロイします。
クラスタをフリートに登録します(まだ登録されていない場合)。
マルチクラスタ Service コントローラとマルチクラスタ Gateway コントローラを有効にします。
最後に、お使いの環境でコントローラを使用する前に、GKE Gateway コントローラの制限事項と既知の問題をご確認ください。
リージョン間で内部マルチクラスタ Gateway をデプロイする
複数のリージョンの GKE クラスタ間で内部レイヤ 7 ロード バランシングを提供するマルチクラスタ Gateway をデプロイできます。これらの Gateway は gke-l7-cross-regional-internal-managed-mc GatewayClass を使用します。この GatewayClass は、クロスリージョン内部アプリケーション ロードバランサをプロビジョニングします。これは Google Cloud によって管理され、VPC ネットワーク内のクライアントがアクセスできる内部 VIP を有効にします。これらの Gateway は、Gateway を使用して特定のリージョンのアドレスをリクエストするだけで、選択したリージョンのフロントエンドで公開できます。内部 VIP は単一の IP アドレスにすることも、複数のリージョンの IP アドレスにすることもできます。リージョンごとに 1 つの IP アドレスが Gateway で指定されます。トラフィックは、リクエストを処理できる最も近い正常なバックエンド GKE クラスタに転送されます。
前提条件
プロジェクト ID を使用して
gcloud環境を構成し、プロジェクトとシェルを設定します。export PROJECT_ID="YOUR_PROJECT_ID" gcloud config set project ${PROJECT_ID}複数のリージョンに GKE クラスタを作成します。
この例では、
us-west1のgke-west-1とus-east1のgke-east-1の 2 つのクラスタを使用します。Gateway API が有効(--gateway-api=standard)で、クラスタがフリートに登録されていることを確認します。gcloud container clusters create gke-west-1 \ --location=us-west1-a \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --project=${PROJECT_ID} \ --enable-fleet \ --gateway-api=standard gcloud container clusters create gke-east-1 \ --location=us-east1-c \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --project=${PROJECT_ID} \ --enable-fleet \ --gateway-api=standardアクセスしやすいようにコンテキストの名前を変更します。
gcloud container clusters get-credentials gke-west-1 \ --location=us-west1-a \ --project=${PROJECT_ID} gcloud container clusters get-credentials gke-east-1 \ --location=us-east1-c \ --project=${PROJECT_ID} kubectl config rename-context gke_${PROJECT_ID}_us-west1-a_gke-west-1 gke-west1 kubectl config rename-context gke_${PROJECT_ID}_us-east1-c_gke-east-1 gke-east1マルチクラスタ Service(MCS)とマルチクラスタ Ingress(MCI / Gateway)を有効にします。
gcloud container fleet multi-cluster-services enable --project=${PROJECT_ID} # Set the config membership to one of your clusters (e.g., gke-west-1) # This cluster will be the source of truth for multi-cluster Gateway and Route resources. gcloud container fleet ingress enable \ --config-membership=projects/${PROJECT_ID}/locations/us-west1/memberships/gke-west-1 \ --project=${PROJECT_ID}プロキシ専用サブネットを構成します。プロキシ専用サブネットは、GKE クラスタが配置される各リージョンと、ロードバランサが動作するリージョンに必要です。クロスリージョン内部アプリケーション ロードバランサでは、このサブネットの目的を
GLOBAL_MANAGED_PROXYに設定する必要があります。# Proxy-only subnet for us-west1 gcloud compute networks subnets create us-west1-proxy-only-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=us-west1 \ --network=default \ --range=10.129.0.0/23 # Choose an appropriate unused CIDR range # Proxy-only subnet for us-east1 gcloud compute networks subnets create us-east1-proxy-only-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=us-east1 \ --network=default \ --range=10.130.0.0/23 # Choose an appropriate unused CIDR rangeデフォルトのネットワークを使用していない場合は、
defaultを VPC ネットワークの名前に置き換えます。CIDR 範囲が一意であり、重複していないことを確認します。storeなどのデモ アプリケーションを両方のクラスタにデプロイします。gke-networking-recipesのstore.yamlファイルの例では、storeNamespace と Deployment が作成されます。kubectl apply --context gke-west1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml kubectl apply --context gke-east1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml各クラスタで Kubernetes
ServiceリソースとServiceExportリソースを作成して、各クラスタから Service をエクスポートします。これにより、フリート全体で Service を検出できるようになります。次の例では、各クラスタから汎用のstoreService とリージョン固有の Service(store-west-1、store-east-1)をエクスポートします。これらはすべてstoreNamespace 内にあります。gke-west1に適用:cat << EOF | kubectl apply --context gke-west1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: store --- apiVersion: v1 kind: Service metadata: name: store-west-1 # Specific to this cluster namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store-west-1 # Exporting the region-specific service namespace: store EOFgke-east1に適用:cat << EOF | kubectl apply --context gke-east1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: store --- apiVersion: v1 kind: Service metadata: name: store-east-1 # Specific to this cluster namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store-east-1 # Exporting the region-specific service namespace: store EOFServiceImport を確認します。
ServiceImportリソースが各クラスタのstoreNamespace 内に作成されていることを確認します。作成には数分かかることがあります。bash kubectl get serviceimports --context gke-west1 -n store kubectl get serviceimports --context gke-east1 -n storestore、store-west-1、store-east-1(または、伝播に基づく関連エントリ)が一覧表示されます。
内部マルチリージョン Gateway を構成する
gke-l7-cross-regional-internal-managed-mc GatewayClass を参照する Gateway リソースを定義します。このマニフェストは、指定の構成クラスタ(gke-west-1 など)に適用します。
spec.addresses フィールドでは、特定リージョンのエフェメラル IP アドレスをリクエストすることも、事前に割り振られた静的 IP アドレスを使用することもできます。
エフェメラル IP アドレスを使用するには、次の
Gatewayマニフェストをcross-regional-gateway.yamlとして保存します。# cross-regional-gateway.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-cross-region-gateway namespace: store # Namespace for the Gateway resource spec: gatewayClassName: gke-l7-cross-regional-internal-managed-mc addresses: # Addresses across regions. Address value is allowed to be empty or matching # the region name. - type: networking.gke.io/ephemeral-ipv4-address/us-west1 value: "us-west1" - type: networking.gke.io/ephemeral-ipv4-address/us-east1 value: "us-east1" listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute # Only allow HTTPRoute to attach前の YAML ファイルの一部のフィールドの定義を以下に示します。
metadata.namespace: Gateway リソースが作成される Namespace(例:store)。spec.gatewayClassName: GatewayClass の名前。必ずgke-l7-cross-regional-internal-managed-mcを指定します。spec.listeners.allowedRoutes.kinds: 関連付けることができる Route オブジェクトの種類(HTTPRouteなど)。spec.addresses:type: networking.gke.io/ephemeral-ipv4-address/REGION: エフェメラル IP アドレスをリクエストします。value: アドレスのリージョンを指定します("us-west1"、"us-east1"など)。
マニフェストを構成クラスタ(例:
gke-west1)に適用します。kubectl apply --context gke-west1 -f cross-regional-gateway.yaml
HTTPRoute を Gateway に接続する
トラフィック ルーティングを管理する HTTPRoute リソースを定義して、構成クラスタに適用します。
次の
HTTPRouteマニフェストをstore-route.yamlとして保存します。# store-route.yaml kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store-route namespace: store labels: gateway: cross-regional-internal spec: parentRefs: - name: internal-cross-region-gateway namespace: store # Namespace where the Gateway is deployed hostnames: - "store.example.internal" # Hostname clients will use rules: - matches: # Rule for traffic to /west - path: type: PathPrefix value: /west backendRefs: - group: net.gke.io # Indicates a multi-cluster ServiceImport kind: ServiceImport name: store-west-1 # Targets the ServiceImport for the west cluster port: 8080 - matches: # Rule for traffic to /east - path: type: PathPrefix value: /east backendRefs: - group: net.gke.io kind: ServiceImport name: store-east-1 # Targets the ServiceImport for the east cluster port: 8080 - backendRefs: # Default rule for other paths (e.g., /) - group: net.gke.io kind: ServiceImport name: store # Targets the generic 'store' ServiceImport (any region) port: 8080前の YAML ファイルの一部のフィールドの定義を以下に示します。
spec.parentRefs: このルートをstoreNamespace のinternal-cross-region-gatewayに関連付けます。spec.hostnames: クライアントが Service にアクセスするために使用するホスト名を表します。spec.rules: ルーティング ロジックを定義します。この例では、パスベースのルーティングを使用します。/westトラフィックはstore-west-1ServiceImport に転送されます。/eastトラフィックはstore-east-1ServiceImport に転送されます。/などの他のすべてのトラフィックは、汎用のstoreServiceImport に送信されます。
backendRefs:group: net.gke.ioとkind: ServiceImportはマルチクラスタ Service をターゲットにします。
HTTPRouteマニフェストを構成クラスタに適用します。kubectl apply --context gke-west1 -f store-route.yaml
Gateway と Route のステータスを確認する
Gateway のステータスを確認します。
kubectl get gateway internal-cross-region-gateway -n store -o yaml --context gke-west1type:Programmedandstatus: "True" の条件を探します。. You should see IP addresses assigned in thestatus.addressesfield, corresponding to the regions you specified (e.g., one forus-west1and one forus-east1`).HTTPRoute のステータスを確認します。
kubectl get httproute store-route -n store -o yaml --context gke-west1status.parents[].conditionsで、type: Accepted(またはResolvedRefs)およびstatus: "True"の条件を探します。
トラフィックを確認する
IP アドレスを Gateway に割り当てたら、VPC ネットワーク内のいずれかのリージョン(Gateway の IP アドレスに接続できるリージョン)にあるクライアント VM からトラフィックをテストできます。
Gateway の IP アドレスを取得します。
次のコマンドは、JSON 出力の解析を試みます。正確な構造に基づいて
jsonpathを調整する必要がある場合があります。kubectl get gateway cross-region-gateway -n store --context gke-west1 -o=jsonpath="{.status.addresses[*].value}".このコマンドの出力には、
VIP1_WESTやVIP2_EASTなどの VIP が含まれているはずです。VPC 内のクライアント VM からテスト リクエストを送信します。
# Assuming VIP_WEST is an IP in us-west1 and VIP_EAST is an IP in us-east1 # Traffic to /west should ideally be served by gke-west-1 curl -H "host: store.example.internal" http://VIP_WEST/west curl -H "host: store.example.internal" http://VIP_EAST/west # Still targets store-west-1 due to path # Traffic to /east should ideally be served by gke-east-1 curl -H "host: store.example.internal" http://VIP_WEST/east # Still targets store-east-1 due to path curl -H "host: store.example.internal" http://VIP_EAST/east # Traffic to / (default) could be served by either cluster curl -H "host: store.example.internal" http://VIP_WEST/ curl -H "host: store.example.internal" http://VIP_EAST/レスポンスには、リクエストを処理したバックエンド Pod を示す
storeアプリケーションの詳細(cluster_nameやzoneなど)が含まれているはずです。
静的 IP アドレスを使用する
エフェメラル IP アドレスの代わりに、事前に割り振られた静的内部 IP アドレスを使用できます。
使用するリージョンに静的 IP アドレスを作成します。
gcloud compute addresses create cross-region-gw-ip-west --region us-west1 --subnet default --project=${PROJECT_ID} gcloud compute addresses create cross-region-gw-ip-east --region us-east1 --subnet default --project=${PROJECT_ID}デフォルトのサブネットを使用していない場合は、
defaultを、割り振る IP アドレスを持つサブネットの名前に置き換えます。これらのサブネットは、プロキシ専用サブネットではなく、通常のサブネットです。cross-regional-gateway.yamlファイルのspec.addressesセクションを変更して、Gateway マニフェストを更新します。# cross-regional-gateway-static-ip.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-cross-region-gateway # Or a new name if deploying alongside namespace: store spec: gatewayClassName: gke-l7-cross-regional-internal-managed-mc addresses: - type: networking.gke.io/named-address-with-region # Use for named static IP value: "regions/us-west1/addresses/cross-region-gw-ip-west" - type: networking.gke.io/named-address-with-region value: "regions/us-east1/addresses/cross-region-gw-ip-east" listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute更新された Gateway マニフェストを適用します。
kubectl apply --context gke-west1 -f cross-regional-gateway.yaml
デフォルト以外のサブネットに関する特別な考慮事項
デフォルト以外のサブネットを使用する場合は、次の点に注意してください。
同じ VPC ネットワーク: 静的 IP アドレス、プロキシ専用サブネット、GKE クラスタなど、ユーザーが作成したすべてのリソースが同じ VPC ネットワーク内に存在する必要があります。
アドレス サブネット: Gateway の静的 IP アドレスを作成すると、指定したリージョンの通常のサブネットから割り振られます。
クラスタ サブネットの命名: 各リージョンに、MCG 構成クラスタが存在するサブネットと同じ名前のサブネットが必要です。
- たとえば、
gke-west-1構成クラスタがprojects/YOUR_PROJECT/regions/us-west1/subnetworks/my-custom-subnetにある場合、アドレスをリクエストするリージョンにもmy-custom-subnetサブネットが必要です。us-east1リージョンとus-centra1リージョンでアドレスをリクエストする場合は、これらのリージョンにもmy-custom-subnetという名前のサブネットが存在する必要があります。
- たとえば、
クリーンアップ
このドキュメントの演習を完了したら、アカウントで不要な請求が発生しないように、以下の手順でリソースを削除します。
他の目的で登録する必要がない場合は、フリートからクラスタの登録を解除します。
multiclusterservicediscovery機能を無効にします。gcloud container fleet multi-cluster-services disableマルチクラスタ Ingress を無効にします。
gcloud container fleet ingress disableAPI を無効にします。
gcloud services disable \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ --project=PROJECT_ID
トラブルシューティング
内部 Gateway のプロキシ専用サブネットが存在しない
内部 Gateway に次のイベントがある場合、そのリージョンにはプロキシ専用サブネットは存在しません。この問題を解決するには、プロキシ専用サブネットをデプロイします。
generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/us-west1/targetHttpProxies/gkegw-x5vt-default-internal-http-2jzr7e3xclhj'. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.
正常なアップストリームがない
症状:
Gateway を作成してもバックエンド サービスにアクセスできない場合(503 レスポンス コード)、次の問題が発生している可能性があります。
no healthy upstream
理由:
このエラー メッセージは、ヘルスチェック プローバーが正常なバックエンド サービスを見つけられないことを示します。バックエンド サービスは正常である可能性がありますが、ヘルスチェックのカスタマイズが必要になる場合もあります。
回避策:
この問題を解決するには、HealthCheckPolicy を使用して、アプリケーションの要件(/health など)に基づいてヘルスチェックをカスタマイズします。
次のステップ
- Gateway コントローラの詳細を確認する。