このドキュメントでは、異なるリージョンの 2 つの GKE クラスタにサンプル アプリケーションをデプロイする方法と、マルチクラスタ Gateway が Service 容量の上限を超えた場合にトラフィックをインテリジェントにルーティングする方法について説明します。
容量ベースのロード バランシングは、信頼性と復元力の高いアプリケーションの構築に役立つマルチクラスタ Gateway の機能です。サービスの容量を定義することで、サービスが過負荷になるのを防ぎ、ユーザーに一貫したエクスペリエンスを提供できます。1 つのクラスタの Service が容量に達すると、ロードバランサは使用可能な容量を持つ別のクラスタにトラフィックを自動的にリダイレクトします。トラフィック管理の詳細については、GKE トラフィック管理をご覧ください。
このチュートリアルでは、サンプル store アプリケーションを使用して、オンライン ショッピング サービスを複数のチームが所有して管理し、共有 GKE クラスタのフリート全体にデプロイしている実際のシナリオをシミュレートします。
始める前に
マルチクラスタ Gateway をデプロイする前に環境を用意する必要があります。続行する前に、マルチクラスタ Gateway 用に環境を準備するの手順を行ってください。
GKE クラスタをデプロイします。
クラスタをフリートに登録します(まだ登録されていない場合)。
マルチクラスタ Service コントローラとマルチクラスタ Gateway コントローラを有効にします。
最後に、お使いの環境でコントローラを使用する前に、GKE Gateway コントローラの制限事項と既知の問題をご確認ください。
容量ベースのロード バランシングをデプロイする
このセクションの演習では、異なるリージョンの 2 つの GKE クラスタにアプリケーションをデプロイし、グローバル ロード バランシングと Service 容量のコンセプトを説明します。生成されたトラフィックを 1 秒あたりのリクエスト数(RPS)のさまざまなレベルで送信し、クラスタ間やリージョン間でのトラフィックのロード バランシングの方法を示します。
次の図は、デプロイするトポロジと、トラフィックが Service の容量を超えた場合にクラスタとリージョン間でトラフィックがオーバーフローする仕組みを示しています。
環境を準備する
マルチクラスタ Gateway の環境を準備するに沿って環境を準備します。
GatewayClass リソースが構成クラスタにインストールされていることを確認します。
kubectl get gatewayclasses --context=gke-west-1出力は次のようになります。
NAME CONTROLLER ACCEPTED AGE gke-l7-global-external-managed networking.gke.io/gateway True 16h gke-l7-global-external-managed-mc networking.gke.io/gateway True 14h gke-l7-gxlb networking.gke.io/gateway True 16h gke-l7-gxlb-mc networking.gke.io/gateway True 14h gke-l7-regional-external-managed networking.gke.io/gateway True 16h gke-l7-regional-external-managed-mc networking.gke.io/gateway True 14h gke-l7-rilb networking.gke.io/gateway True 16h gke-l7-rilb-mc networking.gke.io/gateway True 14h
アプリケーションをデプロイする
両方のクラスタにサンプルのウェブ アプリケーション サーバーをデプロイします。
kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/store-traffic-deploy.yaml
kubectl apply --context gke-east-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/store-traffic-deploy.yaml
出力は次のようになります。
namespace/store created
deployment.apps/store created
Service、Gateway、HTTPRoute をデプロイする
次の
Serviceマニフェストをgke-west-1クラスタとgke-east-1クラスタの両方に適用します。cat << EOF | kubectl apply --context gke-west-1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: traffic-test annotations: networking.gke.io/max-rate-per-endpoint: "10" spec: ports: - port: 8080 targetPort: 8080 name: http selector: app: store type: ClusterIP --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: traffic-test EOFcat << EOF | kubectl apply --context gke-east-1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: traffic-test annotations: networking.gke.io/max-rate-per-endpoint: "10" spec: ports: - port: 8080 targetPort: 8080 name: http selector: app: store type: ClusterIP --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: traffic-test EOFService は、1 秒あたり 10 リクエストに設定された
max-rate-per-endpointでアノテーションされます。クラスタあたり 2 つのレプリカがある場合、各 Service にはクラスタごとに 20 RPS の容量があります。Service の Service 容量レベルを選択する方法の詳細については、Service の容量を決定するをご覧ください。
次の
Gatewayマニフェストを構成クラスタに適用します(この例ではgke-west-1)。cat << EOF | kubectl apply --context gke-west-1 -f - kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: store namespace: traffic-test spec: gatewayClassName: gke-l7-global-external-managed-mc listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute EOFこのマニフェストでは、一般公開された IP アドレスを持つ外部アプリケーション ロードバランサをデプロイする、グローバルな外部マルチクラスタ Gateway について記述します。
次の
HTTPRouteマニフェストを構成クラスタに適用します(この例ではgke-west-1)。cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store namespace: traffic-test labels: gateway: store spec: parentRefs: - kind: Gateway namespace: traffic-test name: store rules: - backendRefs: - name: store group: net.gke.io kind: ServiceImport port: 8080 EOFこのマニフェストでは、すべてのトラフィックをストア ServiceImport に転送するルーティング ルールで Gateway を構成する HTTPRoute について記述します。
storeServiceImport は、両方のクラスタでstoreService Pod をグループ化し、ロードバランサでそれらの Pod を 1 つの Service としてアドレス指定できます。数分後に Gateway のイベントをチェックして、デプロイが完了したかどうかを確認できます。
kubectl describe gateway store -n traffic-test --context gke-west-1出力は次のようになります。
... Status: Addresses: Type: IPAddress Value: 34.102.159.147 Conditions: Last Transition Time: 2023-10-12T21:40:59Z 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: 2023-10-12T21:40:59Z Message: Observed Generation: 1 Reason: Accepted Status: True Type: Accepted Last Transition Time: 2023-10-12T21:40:59Z Message: Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-10-12T21:40:59Z Message: The OSS Gateway API has altered the "Ready" condition semantics and reservedit 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 Listeners: Attached Routes: 1 Conditions: Last Transition Time: 2023-10-12T21:40:59Z Message: Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-10-12T21:40:59Z Message: The OSS Gateway API has altered the "Ready" condition semantics and reservedit 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 Name: http Supported Kinds: Group: gateway.networking.k8s.io Kind: HTTPRoute Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 12m mc-gateway-controller traffic-test/store Normal SYNC 6m43s mc-gateway-controller traffic-test/store Normal UPDATE 5m40s (x4 over 12m) mc-gateway-controller traffic-test/store Normal SYNC 118s (x6 over 10m) mc-gateway-controller SYNC on traffic-test/store was a successこの出力は、Gateway が正常にデプロイされたことを示しています。Gateway をデプロイしてからトラフィックが通過し始めるまでに数分かかることがあります。次のステップで使用するため、この出力の IP アドレスをメモしておきます。
トラフィックを確認する
curl コマンドを使用して、Gateway の IP アドレスをテストし、トラフィックがアプリケーションに渡されることを確認します。
curl GATEWAY_IP_ADDRESS
出力は次のようになります。
{
"cluster_name": "gke-west-1",
"host_header": "34.117.182.69",
"pod_name": "store-54785664b5-mxstv",
"pod_name_emoji": "👳🏿",
"project_id": "project",
"timestamp": "2021-11-01T14:06:38",
"zone": "us-west1-a"
}
この出力には、リクエストが提供されたリージョンを示す Pod メタデータが表示されます。
負荷テストを使用してトラフィックを確認する
ロードバランサが機能していることを確認するには、gke-west-1 クラスタにトラフィック生成ツールをデプロイします。トラフィック生成ツールは、さまざまな負荷レベルでトラフィックを生成し、ロードバランサの容量とオーバーフロー機能を実証します。次の手順では、3 つのレベルの負荷を示します。
- 10 RPS。これは
gke-west-1内のストア Service の容量を下回っています。 - 30 RPS。これは
gke-west-1ストア Service の容量を超えているため、トラフィックがgke-east-1にオーバーフローします。 - 60 RPS。これは、両方のクラスタで Service の容量を超えています。
ダッシュボードを構成
Gateway の基盤となっている URL マップの名前を取得します。
kubectl get gateway store -n traffic-test --context=gke-west-1 -o=jsonpath="{.metadata.annotations.networking\.gke\.io/url-maps}"出力は次のようになります。
/projects/PROJECT_NUMBER/global/urlMaps/gkemcg1-traffic-test-store-armvfyupay1tGoogle Cloud コンソールで、Metrics Explorer のページに移動します。
[指標を選択] で、[CODE: MQL] をクリックします。
次のクエリを入力して、2 つのクラスタ全体にわたるストア Service のトラフィック指標を確認します。
fetch https_lb_rule | metric 'loadbalancing.googleapis.com/https/backend_request_count' | filter (resource.url_map_name == 'GATEWAY_URL_MAP') | align rate(1m) | every 1m | group_by [resource.backend_scope], [value_backend_request_count_aggregate: aggregate(value.backend_request_count)]GATEWAY_URL_MAPは、前の手順での URL マップ名に置き換えます。[クエリを実行] をクリックします。次のセクションで負荷生成ツールをデプロイしてから、指標がグラフに表示されるまで、少なくとも 5 分は待ちます。
10 RPS でテストする
Pod を
gke-west-1クラスタにデプロイします。kubectl run --context gke-west-1 -i --tty --rm loadgen \ --image=cyrilbkr/httperf \ --restart=Never \ -- /bin/sh -c 'httperf \ --server=GATEWAY_IP_ADDRESS \ --hog --uri="/zone" --port 80 --wsess=100000,1,1 --rate 10'GATEWAY_IP_ADDRESSは、前の手順で取得した Gateway IP アドレスに置き換えます。出力は次のようになります。これは、トラフィック生成ツールがトラフィックを送信していることを示しています。
If you don't see a command prompt, try pressing enter.負荷生成ツールは Gateway に継続的に 10 RPS を送信します。トラフィックが Google Cloud リージョン内から送信されていても、ロードバランサは米国西海岸から送信されるクライアント トラフィックとして扱います。現実的なクライアント多様性をシミュレートするために、負荷生成ツールは各 HTTP リクエストを新しい TCP 接続として送信します。つまり、トラフィックはバックエンド Pod 間でより均等に分散されます。
生成ツールがダッシュボードのトラフィックを生成するまでに最大 5 分かかります。
Metrics Explorer ダッシュボードを表示します。各クラスタにロードバランシングされるトラフィックの量を示す 2 つの行が表示されます。

us-west1-aが約 10 RPS のトラフィックを受信しているのに対し、us-east1-bはトラフィックを受信していないことがわかります。トラフィック生成ツールはus-west1で実行されているため、すべてのトラフィックはgke-west-1クラスタ内の Service に送信されます。Ctrl+C を使用して負荷生成ツールを停止してから、Pod を削除します。
kubectl delete pod loadgen --context gke-west-1
30 RPS でテストする
負荷生成ツールを再度デプロイしますが、送信は 30 RPS となるよう構成します。
kubectl run --context gke-west-1 -i --tty --rm loadgen \ --image=cyrilbkr/httperf \ --restart=Never \ -- /bin/sh -c 'httperf \ --server=GATEWAY_IP_ADDRESS \ --hog --uri="/zone" --port 80 --wsess=100000,1,1 --rate 30'生成ツールがダッシュボードのトラフィックを生成するまでに最大 5 分かかります。
Cloud Ops ダッシュボードを表示します。

約 20 RPS が
us-west1-aに送信され、10 RPS がus-east1-bに送信されていることがわかります。これは、gke-west-1の Service が完全に使用されており、10 RPS のトラフィックがgke-east-1の Service へオーバーフローしていることを示しています。Ctrl+C を使用して負荷生成ツールを停止してから、Pod を削除します。
kubectl delete pod loadgen --context gke-west-1
60 RPS でテストする
60 RPS を送信するように構成された負荷生成ツールをデプロイします。
kubectl run --context gke-west-1 -i --tty --rm loadgen \ --image=cyrilbkr/httperf \ --restart=Never \ -- /bin/sh -c 'httperf \ --server=GATEWAY_IP_ADDRESS \ --hog --uri="/zone" --port 80 --wsess=100000,1,1 --rate 60'5 分待ってから、Cloud Ops ダッシュボードを表示します。両方のクラスタが約 30 RPS を受信していることがわかります。すべての Service はグローバルで過剰に使用されているため、トラフィックのスピルオーバーはなく、各 Service は可能な限りすべてのトラフィックを吸収します。

Ctrl+C を使用して負荷生成ツールを停止してから、Pod を削除します。
kubectl delete pod loadgen --context gke-west-1
クリーンアップ
このドキュメントの演習を完了したら、アカウントで不要な請求が発生しないように、以下の手順でリソースを削除します。
他の目的で登録する必要がない場合は、フリートからクラスタの登録を解除します。
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 を作成してもバックエンド サービスにアクセスできない場合(503 レスポンス コード)、次の問題が発生している可能性があります。
no healthy upstream
理由:
このエラー メッセージは、ヘルスチェック プローバーが正常なバックエンド サービスを見つけられないことを示します。バックエンド サービスは正常である可能性がありますが、ヘルスチェックのカスタマイズが必要になる場合もあります。
回避策:
この問題を解決するには、HealthCheckPolicy を使用して、アプリケーションの要件(/health など)に基づいてヘルスチェックをカスタマイズします。
次のステップ
- Gateway コントローラの詳細を確認する。