このページでは、複数の Google Kubernetes Engine(GKE)クラスタ(またはフリート)間で上り(内向き)トラフィックのロード バランシングを行う Kubernetes Gateway リソースをデプロイする方法について説明します。マルチクラスタ Gateway をデプロイする前に、マルチクラスタ Gateway の有効化を参照して環境を準備してください。
上り(内向き)トラフィックのロード バランシングを行う Gateway を単一の GKE クラスタにデプロイする場合は、Gateway のデプロイをご覧ください。
マルチクラスタ Gateway
マルチクラスタ Gateway は、複数の Kubernetes クラスタ間でトラフィックのロード バランシングを行う Gateway リソースです。GKE では、gke-l7-global-external-managed-mc
、gke-l7-regional-external-managed-mc
、gke-l7-rilb-mc
、gke-l7-gxlb-mc
の GatewayClass は、さまざまな GKE クラスタ、Kubernetes Namespace、さまざまなリージョンにまたがって、HTTP ルーティング、トラフィック分割、トラフィック ミラーリング、ヘルスチェック ベースのフェイルオーバーなどを実施するマルチクラスタ Gateway をデプロイします。マルチクラスタ Gateway を使用すると、インフラストラクチャ管理者に対して、多数のクラスタ間やチーム間でアプリケーション ネットワーキングを簡単に、安全に、スケーラブルにします。
このページでは、GKE Gateway コントローラを使用してマルチクラスタ Gateway をデプロイする方法を説明する 3 つの例を紹介します。
- 例 1: インターネット トラフィック用の 2 つの GKE クラスタ間でロード バランシングを行う外部マルチクラスタ Gateway。
- 例 2: 内部 VPC トラフィック用の 2 つの GKE クラスタ間で Blue/Green の重み付けに基づくトラフィック分割とトラフィック ミラーリング。
- 例 3: 最大容量に基づいて異なるバックエンドに対してリクエストのロード バランシングを行う容量ベースの Gateway。
それぞれの例では、同じストアとサイトのアプリケーションを使用して実際のシナリオをモデル化しています。このシナリオでは、複数のチームがオンライン ショッピング サービスとウェブサイト サービスを所有して管理し、これらのサービスを共有 GKE クラスタのフリート全体にデプロイしています。それぞれの例で、マルチクラスタ Gateway によって可能になるトポロジとユースケースについて説明します。
マルチクラスタ Gateway をデプロイする前に環境を用意する必要があります。続行する前に、マルチクラスタ Gateway の有効化の手順を行ってください。
最後に、お使いの環境で使用する前に、GKE Gateway コントローラの制限事項と既知の問題をご確認ください。
マルチクラスタ、マルチリージョン、外部 Gateway
このチュートリアルでは、2 つの GKE クラスタのアプリケーション間で外部トラフィックを分散させる外部マルチクラスタ Gateway を作成します。
以下のステップでは、次の操作を行います。
gke-west-1
クラスタとgke-east-1
クラスタにサンプルstore
アプリケーションをデプロイします。- フリートにエクスポートする各クラスタで Service を構成します(マルチクラスタ Service)。
- 外部のマルチクラスタ Gateway と HTTPRoute を構成クラスタ(
gke-west-1
)にデプロイします。
アプリケーションと Gateway リソースがデプロイされると、パスベースのルーティングを使用して 2 つの GKE クラスタ間のトラフィックを制御できます。
/west
へのリクエストは、gke-west-1
クラスタ内のstore
Pod に転送されます。/east
へのリクエストは、gke-east-1
クラスタ内のstore
Pod に転送されます。- 他のパスへのリクエストは、正常性、容量、リクエスト元クライアントへの近接性に応じて、いずれかのクラスタに転送されます。
デモ アプリケーションのデプロイ
マルチクラスタ Gateway の有効化でデプロイされた 3 つのクラスタすべてで、
store
Deployment と Namespace を作成します。kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml kubectl apply --context gke-west-2 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml kubectl apply --context gke-east-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml
各クラスタに次のリソースをデプロイします。
namespace/store created deployment.apps/store created
このページの例はすべて、この手順でデプロイしたアプリを使用します。残りの 3 つの手順を試す前に、アプリが 3 つのクラスタすべてにデプロイされていることを確認してください。この例では、クラスタ
gke-west-1
とgke-east-1
のみを使用しています。別の例ではgke-west-2
を使用しています。
マルチクラスタ Service
Service は、Pod をクライアントに公開する方法です。GKE Gateway Controller はコンテナ ネイティブのロード バランシングを使用するため、ClusterIP または Kubernetes のロード バランシングを使用して Pod にアクセスすることはありません。トラフィックはロードバランサから Pod の IP アドレスに直接送信されます。ただし、Service は引き続き、Pod のグループ化の論理 ID として重要な役割を果たします。
マルチクラスタ Service(MCS)はクラスタにまたがる Service の API 標準であり、その GKE コントローラが GKE クラスタ全体にサービス ディスカバリを提供します。マルチクラスタ Gateway コントローラは MCS API リソースを使用して Pod を Service にグループ化し、クラスタ全体または複数のクラスタ間でのアドレス指定を可能にします。
マルチクラスタ Services API は、次のカスタム リソースを定義します。
- ServiceExports は Kubernetes Service にマッピングされ、フリートに登録されているすべてのクラスタに、その Service のエンドポイントをエクスポートします。Service に対応する ServiceExport がある場合、Service はマルチクラスタ Gateway でアドレス指定できます。
- ServiceImports は、マルチクラスタ Service コントローラによって自動的に生成されます。ServiceExport と ServiceImport はペアで提供されます。ServiceExport がフリートに存在する場合、対応する ServiceImport が作成され、ServiceExport にマッピングされた Service にクラスタ間でアクセスできるようになります。
Service のエクスポートの仕組みは次のとおりです。ストア Service は、クラスタ内の Pod のグループを選択する gke-west-1
に存在します。ServiceExport がクラスタに作成され、gke-west-1
の Pod にフリート内の他のクラスタからアクセスできるようになります。ServiceExport は、ServiceExport リソースと同じ名前および Namespace を持つ Service にマッピングされ、公開されます。
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
次の図に、ServiceExport がデプロイされた後の流れを示します。ServiceExport と Service のペアが存在する場合、マルチクラスタ Service コントローラは、対応する ServiceImport をフリート内のすべての GKE クラスタにデプロイします。ServiceImport は、すべてのクラスタの store
Service のローカル表現です。これにより、gke-east-1
の client
Pod が ClusterIP またはヘッドレス Service を使用して gke-west-1
の store
Pod にアクセスできるようになります。このように使用すると、マルチクラスタ Service はクラスタ間で East-West のロード バランシングを行います。内部 LoadBalancer Service は必要ありません。クラスタ間のロード バランシングにマルチクラスタ Service を使用するには、マルチクラスタ Service の構成をご覧ください。
マルチクラスタ Gateway でも ServiceImport は使用されますが、クラスタ間のロード バランシングでは使用されません。Gateway は、別のクラスタに存在する Service または複数のクラスタにまたがる Service の論理 ID として ServiceImport を使用します。次の HTTPRoute は Service リソースではなく ServiceImport を参照します。ServiceImport を参照することで、1 つ以上のクラスタで実行されているバックエンド Pod のグループにトラフィックが転送されています。
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: store-route
namespace: store
labels:
gateway: multi-cluster-gateway
spec:
parentRefs:
- kind: Gateway
namespace: store
name: external-http
hostnames:
- "store.example.com"
rules:
- backendRefs:
- group: net.gke.io
kind: ServiceImport
name: store
port: 8080
次の図は、HTTPRoute が gke-west-1
と gke-east-1
の store
Pod に store.example.com
トラフィックを転送する方法を示しています。ロードバランサは、これを 1 つのバックエンドのプールとして扱います。一方のクラスタの Pod が異常な状態または到達不能になるか、トラフィック容量がなくなると、トラフィックの負荷はもう一方のクラスタの残りの Pod に分散されます。新しいクラスタの追加または削除は、store
Service と ServiceExport を使用して行います。これにより、ルーティング構成を明示的に変更することなく、バックエンド Pod を透過的に追加または削除できます。
Service のエクスポート
この時点で、アプリケーションは両方のクラスタで実行されています。次に、各クラスタに Service と ServiceExport をデプロイして、アプリケーションを公開してエクスポートします。
次のマニフェストを
gke-west-1
クラスタに適用して、store
Service、store-west-1
Service、ServiceExport を作成します。cat << EOF | kubectl apply --context gke-west-1 -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 namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store-west-1 namespace: store EOF
次のマニフェストを
gke-east-1
クラスタに適用して、store
Service、store-east-1
Service、ServiceExport を作成します。cat << EOF | kubectl apply --context gke-east-1 -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 namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store-east-1 namespace: store EOF
クラスタに正しい ServiceExport が作成されていることを確認します。
kubectl get serviceexports --context CLUSTER_NAME --namespace store
CLUSTER_NAME を
gke-west-1
とgke-east-1
に置き換えます。出力は次のようになります。# gke-west-1 NAME AGE store 2m40s store-west-1 2m40s # gke-east-1 NAME AGE store 2m25s store-east-1 2m25s
これは、
store
Service には両方のクラスタに対するstore
Pod が含まれているのに対し、store-west-1
Service とstore-east-1
Service には、それぞれのクラスタのstore
のみが含まれていることを示しています。この重複する Service は、複数のクラスタまたは単一クラスタの Pod のサブセットで Pod をターゲットにするために使用されます。数分後、フリート内のすべてのクラスタに、付属の
ServiceImports
がマルチクラスタ Service コントローラによって自動的に作成されたことを確認します。kubectl get serviceimports --context CLUSTER_NAME --namespace store
CLUSTER_NAME を
gke-west-1
とgke-east-1
に置き換えます。出力は次のようになります。# gke-west-1 NAME TYPE IP AGE store ClusterSetIP ["10.112.31.15"] 6m54s store-east-1 ClusterSetIP ["10.112.26.235"] 5m49s store-west-1 ClusterSetIP ["10.112.16.112"] 6m54s # gke-east-1 NAME TYPE IP AGE store ClusterSetIP ["10.72.28.226"] 5d10h store-east-1 ClusterSetIP ["10.72.19.177"] 5d10h store-west-1 ClusterSetIP ["10.72.28.68"] 4h32m
これは、フリートの両方のクラスタから 3 つの Service すべてにアクセスできることを示しています。ただし、フリートごとにアクティブな構成クラスタは 1 つのみであるため、これらの ServiceImport を参照する Gateway と HTTPRoute は
gke-west-1
にのみデプロイできます。構成クラスタ内の HTTPRoute がこれらの ServiceImport をバックエンドとして参照している場合、Gateway はエクスポート元のクラスタに関係なく Service にトラフィックを転送できます。
Gateway と HTTPRoute のデプロイ
アプリケーションがデプロイされたら、gke-l7-global-external-managed-mc
GatewayClass を使用して Gateway を構成できます。この Gateway は、ターゲット クラスタ間でトラフィックを分散するように構成された外部アプリケーション ロードバランサを作成します。
次の
Gateway
マニフェストを構成クラスタに適用します(この例ではgke-west-1
)。cat << EOF | kubectl apply --context gke-west-1 -f - kind: Gateway apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: external-http namespace: store spec: gatewayClassName: gke-l7-global-external-managed-mc listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute EOF
この Gateway 構成では、命名規則
gkemcg1-NAMESPACE-GATEWAY_NAME-HASH
に従って外部のアプリケーション ロードバランサ リソースがデプロイされます。この構成で作成されるデフォルトのリソースは次のとおりです。
- 1 つのロード バランサ:
gkemcg1-store-external-http-HASH
- 1 つのパブリック IP アドレス:
gkemcg1-store-external-http-HASH
- 1 つの転送ルール:
gkemcg1-store-external-http-HASH
- 2 つのバックエンド サービス:
- デフォルトの 404 バックエンド サービス:
gkemcg1-store-gw-serve404-HASH
- デフォルトの 500 バックエンド サービス:
gkemcg1-store-gw-serve500-HASH
- デフォルトの 404 バックエンド サービス:
- 1 つのヘルスチェック:
- デフォルトの 404 ヘルスチェック:
gkemcg1-store-gw-serve404-HASH
- デフォルトの 404 ヘルスチェック:
- 0 個のルーティング ルール(URLmap は空)
この段階では、GATEWAY_IP:80 に対するリクエストでデフォルト ページに「
fault filter abort
」というメッセージが表示されます。- 1 つのロード バランサ:
次の
HTTPRoute
マニフェストを構成クラスタに適用します(この例ではgke-west-1
)。cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: public-store-route namespace: store labels: gateway: external-http spec: hostnames: - "store.example.com" parentRefs: - name: external-http rules: - matches: - path: type: PathPrefix value: /west backendRefs: - group: net.gke.io kind: ServiceImport name: store-west-1 port: 8080 - matches: - path: type: PathPrefix value: /east backendRefs: - group: net.gke.io kind: ServiceImport name: store-east-1 port: 8080 - backendRefs: - group: net.gke.io kind: ServiceImport name: store port: 8080 EOF
この段階では、GATEWAY_IP:80 に対するリクエストでデフォルト ページに「
fault filter abort
」というメッセージが表示されます。デプロイされると、この HTTPRoute は次のルーティング動作を構成します。
store-west-1
ServiceExport によって選択された Pod はgke-west-1
クラスタ内にのみ存在するため、/west
へのリクエストはgke-west-1
クラスタ内のstore
Pod に転送されます。store-east-1
ServiceExport によって選択された Pod はgke-east-1
クラスタ内にのみ存在するため、/east
へのリクエストはgke-east-1
クラスタ内のstore
Pod に転送されます。- 他のパスへのリクエストは、正常性、容量、リクエスト元クライアントへの近接性に応じて、いずれかのクラスタ内の
store
Pod に転送されます。 - GATEWAY_IP:80 に対するリクエストを送信すると、デフォルト ページに「
fault filter abort
」というメッセージが表示されます。
特定のクラスタ内に異常な Pod が存在する場合(または Pod が存在しない場合)、
store
Service へのトラフィックは実際にstore
Pod が存在するクラスタにのみ送信されます。特定のクラスタに ServiceExport と Service が存在しても、そのクラスタにトラフィックが送信されるとは限りません。Pod が存在し、ロードバランサのヘルスチェックに肯定的なレスポンスを返す必要があります。そうでない場合、ロードバランサは他のクラスタ内の正常なstore
Pod にトラフィックを送信します。新しいリソースは次の構成で作成されます。
- 3 つのバックエンド サービス:
store
バックエンド サービス:gkemcg1-store-store-8080-HASH
store-east-1
バックエンド サービス:gkemcg1-store-store-east-1-8080-HASH
store-west-1
バックエンド サービス:gkemcg1-store-store-west-1-8080-HASH
- 3 つのヘルスチェック:
store
ヘルスチェック:gkemcg1-store-store-8080-HASH
store-east-1
ヘルスチェック:gkemcg1-store-store-east-1-8080-HASH
store-west-1
ヘルスチェック:gkemcg1-store-store-west-1-8080-HASH
- URLmap の 1 つのルーティング ルール:
store.example.com
ルーティング ルール:- 1 つのホスト:
store.example.com
- 新しいバックエンド サービスに転送する複数の
matchRules
次の図は、両方のクラスタにデプロイしたリソースを示しています。gke-west-1
は Gateway 構成クラスタであるため、Gateway コントローラが Gateway、HTTPRoute、ServiceImport を監視するクラスタになります。各クラスタには store
ServiceImport と、そのクラスタに固有の別の ServiceImport が存在します。どちらも同じ Pod を参照します。これにより、HTTPRoute はトラフィックの送信先を正確に指定できます。送信先は、特定のクラスタの store
Pod か、すべてのクラスタの store
Pod になります。
これは論理的なリソースモデルであり、トラフィック フローを表すものではありません。トラフィックはロードバランサからバックエンド Pod に直接送信されます。どのクラスタが構成クラスタかには直接関係ありません。
デプロイの検証
これで、マルチクラスタ Gateway にリクエストを発行し、トラフィックを複数の GKE クラスタに分散できるようになりました。
Gateway のステータスとイベントを調べて、Gateway と HTTPRoute が正常にデプロイされたことを確認します。
kubectl describe gateways.gateway.networking.k8s.io external-http --context gke-west-1 --namespace store
出力は次のようになります。
Name: external-http Namespace: store Labels: <none> Annotations: networking.gke.io/addresses: /projects/PROJECT_NUMBER/global/addresses/gkemcg1-store-external-http-laup24msshu4 networking.gke.io/backend-services: /projects/PROJECT_NUMBER/global/backendServices/gkemcg1-store-gw-serve404-80-n65xmts4xvw2, /projects/PROJECT_NUMBER/global/backendServices/gke... networking.gke.io/firewalls: /projects/PROJECT_NUMBER/global/firewalls/gkemcg1-l7-default-global networking.gke.io/forwarding-rules: /projects/PROJECT_NUMBER/global/forwardingRules/gkemcg1-store-external-http-a5et3e3itxsv networking.gke.io/health-checks: /projects/PROJECT_NUMBER/global/healthChecks/gkemcg1-store-gw-serve404-80-n65xmts4xvw2, /projects/PROJECT_NUMBER/global/healthChecks/gkemcg1-s... networking.gke.io/last-reconcile-time: 2023-10-12T17:54:24Z networking.gke.io/ssl-certificates: networking.gke.io/target-http-proxies: /projects/PROJECT_NUMBER/global/targetHttpProxies/gkemcg1-store-external-http-94oqhkftu5yz networking.gke.io/target-https-proxies: networking.gke.io/url-maps: /projects/PROJECT_NUMBER/global/urlMaps/gkemcg1-store-external-http-94oqhkftu5yz API Version: gateway.networking.k8s.io/v1beta1 Kind: Gateway Metadata: Creation Timestamp: 2023-10-12T06:59:32Z Finalizers: gateway.finalizer.networking.gke.io Generation: 1 Resource Version: 467057 UID: 1dcb188e-2917-404f-9945-5f3c2e907b4c Spec: Gateway Class Name: gke-l7-global-external-managed-mc 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: 34.36.127.249 Conditions: Last Transition Time: 2023-10-12T07:00:41Z 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-12T07:00:41Z Message: Observed Generation: 1 Reason: Accepted Status: True Type: Accepted Last Transition Time: 2023-10-12T07:00:41Z Message: Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-10-12T07:00:41Z 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-12T07:00:41Z Message: Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-10-12T07:00:41Z 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 UPDATE 35m (x4 over 10h) mc-gateway-controller store/external-http Normal SYNC 4m22s (x216 over 10h) mc-gateway-controller SYNC on store/external-http was a success
Gateway が正常にデプロイされたら、
external-http
Gateway から外部 IP アドレスを取得します。kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}" --context gke-west-1 --namespace store
次の手順の
VIP
は、出力として受け取る IP アドレスに置き換えます。ドメインのルートパスにトラフィックを送信します。これにより、クラスタ
gke-west-1
とgke-east-1
にあるstore
ServiceImport にトラフィックがロード バランシングされます。ロードバランサは、最も近いリージョンにトラフィックを送信します。このため、他のリージョンからのレスポンスが表示されない場合があります。curl -H "host: store.example.com" http://VIP
この出力で、リクエストが
gke-east-1
クラスタから Pod によって処理されたことを確認できます。{ "cluster_name": "gke-east-1", "zone": "us-east1-b", "host_header": "store.example.com", "node_name": "gke-gke-east-1-default-pool-7aa30992-t2lp.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-dg22z", "pod_name_emoji": "⏭", "project_id": "agmsb-k8s", "timestamp": "2021-06-01T17:32:51" }
次に、
/west
パスにトラフィックを送信します。これにより、gke-west-1
クラスタで実行されている Pod のみが存在するstore-west-1
ServiceImport にトラフィックが転送されます。store-west-1
などのクラスタ固有の ServiceImport を使用することで、アプリケーション オーナーはロードバランサに決定を委ねるのではなく、特定のクラスタにトラフィックを明示的に送信できるようになります。curl -H "host: store.example.com" http://VIP/west
この出力で、リクエストが
gke-west-1
クラスタから Pod によって処理されたことを確認できます。{ "cluster_name": "gke-west-1", "zone": "us-west1-a", "host_header": "store.example.com", "node_name": "gke-gke-west-1-default-pool-65059399-2f41.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-d25m5", "pod_name_emoji": "🍾", "project_id": "agmsb-k8s", "timestamp": "2021-06-01T17:39:15", }
最後に、
/east
パスにトラフィックを送信します。curl -H "host: store.example.com" http://VIP/east
この出力で、リクエストが
gke-east-1
クラスタから Pod によって処理されたことを確認できます。{ "cluster_name": "gke-east-1", "zone": "us-east1-b", "host_header": "store.example.com", "node_name": "gke-gke-east-1-default-pool-7aa30992-7j7z.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-hz6mw", "pod_name_emoji": "🧜🏾", "project_id": "agmsb-k8s", "timestamp": "2021-06-01T17:40:48" }
Gateway による Blue/Green マルチクラスタ ルーティング
gke-l7-global-external-managed-*
、gke-l7-regional-external-managed-*
、gke-l7-rilb-*
GatewayClass では、トラフィック分割、ヘッダー マッチング、ヘッダー操作、トラフィック ミラーリングなど、高度なトラフィック ルーティング機能を使用できます。この例では、重み付けに基づいてトラフィック分割を行い、2 つの GKE クラスタ間のトラフィックの比率を明示的に制御しています。
この例では、サービス オーナーがアプリケーションを新しい GKE クラスタに移動または拡張する際に行う具体的な手順を説明します。Blue/Green デプロイの目標は、新しいクラスタが正しく動作していることを確認する複数の検証手順を行い、リスクを減らすことです。この例では、デプロイの 4 つのステージについて説明します。
- 100% - ヘッダーに基づくカナリア: HTTP ヘッダーのルーティングを使用して、テストまたは合成トラフィックのみを新しいクラスタに送信します。
- 100% - トラフィックのミラーリング: カナリア クラスタへのユーザー トラフィックをミラーリングします。ユーザー トラフィックの 100% がこのクラスタにコピーされ、カナリア クラスタの容量がテストされます。
- 90%~10%: 10% のカナリア トラフィック分割で新しいクラスタをライブ トラフィックにゆっくり公開します。
- 0%~100%: エラーが観察された場合は、元に戻すオプションを使用して、新しいクラスタに完全にカットオーバーします。
この例は前のものと似ていますが、内部マルチクラスタ Gateway をデプロイしている点が異なります。この例では、VPC 内からのみプライベートでのアクセスが可能な内部アプリケーション ロードバランサをデプロイしています。別の Gateway を介してデプロイする場合を除き、前の手順でデプロイしたクラスタとアプリケーションを使用します。
前提条件
次の例では、外部マルチクラスタ Gateway のデプロイの一部の手順を使用しています。この例を続行する前に、次のことが完了していることを確認してください。
-
この例では、設定済みの
gke-west-1
クラスタとgke-west-2
クラスタを使用します。gke-l7-rilb-mc
GatewayClass はリージョンであり、同じリージョン内のクラスタ バックエンドのみをサポートしているため、これらのクラスタは同じリージョンにあります。 各クラスタに必要な Service と ServiceExport をデプロイします。前の例で Service と ServiceExports をデプロイした場合は、その一部がデプロイされています。
kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store-west-1-service.yaml kubectl apply --context gke-west-2 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store-west-2-service.yaml
各クラスタに同様のリソースセットをデプロイします。
service/store created serviceexport.net.gke.io/store created service/store-west-2 created serviceexport.net.gke.io/store-west-2 created
プロキシ専用サブネットの構成
内部 Gateway をデプロイしているリージョンごとに、プロキシ専用サブネットを設定します(まだ設定していない場合)。このサブネットは、ロードバランサのプロキシに内部 IP アドレスを提供するために使用されます。--purpose
を REGIONAL_MANAGED_PROXY
にのみ指定して設定する必要があります。
内部アプリケーション ロードバランサを管理する Gateway を作成する前に、プロキシ専用サブネットを作成する必要があります。内部アプリケーション ロードバランサを使用する Virtual Private Cloud(VPC)ネットワークの各リージョンに、プロキシ専用サブネットを作成する必要があります。
プロキシ専用サブネットを作成するには、gcloud compute networks subnets create
コマンドを使用します。
gcloud compute networks subnets create SUBNET_NAME \
--purpose=REGIONAL_MANAGED_PROXY \
--role=ACTIVE \
--region=REGION \
--network=VPC_NETWORK_NAME \
--range=CIDR_RANGE
次のように置き換えます。
SUBNET_NAME
: プロキシ専用サブネットの名前。REGION
: プロキシ専用サブネットのリージョン。VPC_NETWORK_NAME
: サブネットを含む VPC ネットワークの名前。CIDR_RANGE
: サブネットのプライマリ IP アドレス範囲。サブネット マスクの長さは/26
以下にして、リージョン内のプロキシで 64 個以上の IP アドレスを使用できるようにします。推奨のサブネット マスクは/23
です。
Gateway のデプロイ
次の Gateway は gke-l7-rilb-mc
GatewayClass から作成されています。これはリージョンの内部 Gateway で、同じリージョン内の GKE クラスタのみをターゲットにできます。
次の
Gateway
マニフェストを構成クラスタに適用します(この例ではgke-west-1
)。cat << EOF | kubectl apply --context gke-west-1 -f - kind: Gateway apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: internal-http namespace: store spec: gatewayClassName: gke-l7-rilb-mc listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute EOF
Gateway が正常に起動したことを確認します。次のコマンドを使用して、この Gateway のイベントのみを表示します。
kubectl get events --field-selector involvedObject.kind=Gateway,involvedObject.name=internal-http --context=gke-west-1 --namespace store
次のような出力の場合は、Gateway のデプロイに成功しています。
LAST SEEN TYPE REASON OBJECT MESSAGE 5m18s Normal ADD gateway/internal-http store/internal-http 3m44s Normal UPDATE gateway/internal-http store/internal-http 3m9s Normal SYNC gateway/internal-http SYNC on store/internal-http was a success
ヘッダーに基づくカナリア
ヘッダーに基づくカナリアでは、サービス オーナーは実際のユーザー以外からの合成テスト トラフィックを照合できます。これは、ユーザーを直接公開することなく、アプリケーションの基本ネットワークが機能していることを簡単に検証できる方法です。
次の
HTTPRoute
マニフェストを構成クラスタに適用します(この例ではgke-west-1
)。cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: # Matches for env=canary and sends it to store-west-2 ServiceImport - matches: - headers: - name: env value: canary backendRefs: - group: net.gke.io kind: ServiceImport name: store-west-2 port: 8080 # All other traffic goes to store-west-1 ServiceImport - backendRefs: - group: net.gke.io kind: ServiceImport name: store-west-1 port: 8080 EOF
デプロイされると、この HTTPRoute は次のルーティング動作を構成します。
env: canary
HTTP ヘッダーを使用しないstore.example.internal
への内部リクエストは、gke-west-1
クラスタのstore
Pod に転送されます。env: canary
HTTP ヘッダーを使用するstore.example.internal
への内部リクエストは、gke-west-2
クラスタのstore
Pod に転送されます。
Gateway IP アドレスにトラフィックを送信し、HTTPRoute が正しく機能していることを確認します。
internal-http
から内部 IP アドレスを取得します。kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}" --context gke-west-1 --namespace store
次の手順の VIP は、出力として受け取る IP アドレスに置き換えます。
env: canary
HTTP ヘッダーを使用して、Gateway にリクエストを送信します。これにより、トラフィックがgke-west-2
に転送されていることを確認します。GKE クラスタと同じ VPC のプライベート クライアントを使用して、リクエストが正しく転送されていることを確認します。次のコマンドは、Gateway IP アドレスへのプライベート アクセスがあるマシンで実行する必要があります。そうしないと、機能しません。curl -H "host: store.example.internal" -H "env: canary" http://VIP
この出力で、リクエストが
gke-west-2
クラスタから Pod によって処理されたことを確認できます。{ "cluster_name": "gke-west-2", "host_header": "store.example.internal", "node_name": "gke-gke-west-2-default-pool-4cde1f72-m82p.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-9kdb5", "pod_name_emoji": "😂", "project_id": "agmsb-k8s", "timestamp": "2021-05-31T01:21:55", "zone": "us-west1-a" }
トラフィック ミラーリング
このステージでは、トラフィックを目的のクラスタに送信するだけでなく、カナリア クラスタにトラフィックをミラーリングします。
ミラーリングを使用すると、クライアントへのレスポンスに影響を与えることなく、トラフィックの負荷がアプリケーションのパフォーマンスに与える影響を判断するのに役立ちます。すべての種類のロールアウトで必要になるとは限りませんが、パフォーマンスや負荷に影響を及ぼす可能性のある大規模な変更をロールアウトする場合に役立ちます。
次の
HTTPRoute
マニフェストを構成クラスタに適用します(この例ではgke-west-1
)。cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: # Sends all traffic to store-west-1 ServiceImport - backendRefs: - name: store-west-1 group: net.gke.io kind: ServiceImport port: 8080 # Also mirrors all traffic to store-west-2 ServiceImport filters: - type: RequestMirror requestMirror: backendRef: group: net.gke.io kind: ServiceImport name: store-west-2 port: 8080 EOF
プライベート クライアントを使用して、
internal-http
Gateway にリクエストを送信します。/mirror
パスを使用して、後の手順でアプリケーション ログを確認する際にこのリクエストを一意に識別できるようにします。curl -H "host: store.example.internal" http://VIP/mirror
この出力で、クライアントが
gke-west-1
クラスタの Pod からレスポンスを受信していることを確認します。{ "cluster_name": "gke-west-1", "host_header": "store.example.internal", "node_name": "gke-gke-west-1-default-pool-65059399-ssfq.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-brg5w", "pod_name_emoji": "🎖", "project_id": "agmsb-k8s", "timestamp": "2021-05-31T01:24:51", "zone": "us-west1-a" }
これにより、プライマリ クラスタがトラフィックに応答していることを確認します。また、移行先のクラスタがミラーリング対象トラフィックを受信していることも確認する必要があります。
gke-west-2
クラスタのstore
Pod のアプリケーション ログを確認します。このログは、Pod がロードバランサからミラーリングされたトラフィックを受け取ったことを確認するものです。kubectl logs deployment/store --context gke-west-2 -n store | grep /mirror
この出力では、
gke-west-2
クラスタの Pod も同じリクエストを受信していますが、これらのリクエストに対するレスポンスがクライアントに送信されていないことを確認できます。ログに記録された IP アドレスは、Pod と通信しているロードバランサの内部 IP アドレスになります。Found 2 pods, using pod/store-5c65bdf74f-vpqbs [2023-10-12 21:05:20,805] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:20] "GET /mirror HTTP/1.1" 200 - [2023-10-12 21:05:27,158] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:27] "GET /mirror HTTP/1.1" 200 - [2023-10-12 21:05:27,805] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:27] "GET /mirror HTTP/1.1" 200 -
トラフィック分割
トラフィック分割は、新しいコードをロールアウトするか、新しい環境に安全にデプロイする最も一般的な方法の 1 つです。サービス オーナーは、カナリア バックエンドに送信されるトラフィックの明示的な割合を設定します。これは通常、トラフィック全体に対してかなり少ない量になります。実際のユーザー リクエストに対して許容可能なリスク量も判断できます。
ごく少量のトラフィックでトラフィック分割を行うと、サービス オーナーはアプリケーションの状態とレスポンスを検査できます。すべてのシグナルが正常と思われる場合は、カットオーバーに進みます。
次の
HTTPRoute
マニフェストを構成クラスタに適用します(この例ではgke-west-1
)。cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: - backendRefs: # 90% of traffic to store-west-1 ServiceImport - name: store-west-1 group: net.gke.io kind: ServiceImport port: 8080 weight: 90 # 10% of traffic to store-west-2 ServiceImport - name: store-west-2 group: net.gke.io kind: ServiceImport port: 8080 weight: 10 EOF
プライベート クライアントを使用して、継続的 curl リクエストを
internal- http
Gateway に送信します。while true; do curl -H "host: store.example.internal" -s VIP | grep "cluster_name"; sleep 1; done
出力は次のようになります。90 / 10 のトラフィック分割が発生していることがわかります。
"cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-2", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", ...
トラフィックのカットオーバー
Blue/Green 移行の最終ステージでは、新しいクラスタへの完全なカットオーバーを行い、古いクラスタを削除します。サービス オーナーが 2 つ目のクラスタを既存のクラスタにオンボーディングした場合、最後のステップは異なります。最後のステップでは、両方のクラスタにトラフィックが送信されます。そのシナリオでは、gke-west-1
クラスタと gke-west-2
クラスタの両方の Pod を持つ単一の store
ServiceImport をおすすめします。これにより、ロードバランサは、近接性、健全性、容量に基づいて、アクティブ / アクティブなアプリケーションのトラフィックの送信先を決定できます。
次の
HTTPRoute
マニフェストを構成クラスタに適用します(この例ではgke-west-1
)。cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: - backendRefs: # No traffic to the store-west-1 ServiceImport - name: store-west-1 group: net.gke.io kind: ServiceImport port: 8080 weight: 0 # All traffic to the store-west-2 ServiceImport - name: store-west-2 group: net.gke.io kind: ServiceImport port: 8080 weight: 100 EOF
プライベート クライアントを使用して、継続的 curl リクエストを
internal- http
Gateway に送信します。while true; do curl -H "host: store.example.internal" -s VIP | grep "cluster_name"; sleep 1; done
出力は次のようになります。すべてのトラフィックが
gke-west-2
に送信されるようになります。"cluster_name": "gke-west-2", "cluster_name": "gke-west-2", "cluster_name": "gke-west-2", "cluster_name": "gke-west-2", ...
この最後のステップで、1 つの GKE クラスタから別の GKE クラスタへの Blue/Green アプリケーションを完全に移行します。
容量ベースのロード バランシングをデプロイする
このセクションの演習では、異なるリージョンの 2 つの GKE クラスタにアプリケーションをデプロイし、グローバル ロード バランシングと Service 容量のコンセプトを説明します。生成されたトラフィックを 1 秒あたりのリクエスト数(RPS)のさまざまなレベルで送信し、クラスタ間やリージョン間でのトラフィックのロード バランシングの方法を示します。
次の図は、デプロイするトポロジと、トラフィックが Service の容量を超えた場合にクラスタとリージョン間でトラフィックがオーバーフローする仕組みを示しています。
トラフィック管理の詳細については、GKE トラフィック管理をご覧ください。
環境を準備する
マルチクラスタ 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 EOF
cat << 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 EOF
Service は、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/v1beta1 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/v1beta1 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 について記述します。
store
ServiceImport は、両方のクラスタでstore
Service 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-armvfyupay1t
Google 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 disable
API を無効にします。
gcloud services disable \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ --project=PROJECT_ID
共有 VPC でマルチクラスタ Gateway を使用する
マルチクラスタ Gateway は、ユースケースに応じて異なるトポロジで共有 VPC 環境にデプロイすることもできます。
次の表に、共有 VPC 環境内でサポートされているマルチクラスタ Gateway トポロジを示します。
シナリオ | フリート ホスト プロジェクト | 構成クラスタ | ワークロード クラスタ |
---|---|---|---|
1 | 共有 VPC ホスト プロジェクト | 共有 VPC ホスト プロジェクト | 共有 VPC ホスト プロジェクト |
2 | 共有 VPC サービス プロジェクト | 共有 VPC サービス プロジェクト (フリート サービス プロジェクトと同じ) |
共有 VPC サービス プロジェクト (フリート サービス プロジェクトと同じ) |
共有 VPC 環境でマルチクラスタ Gateway を作成するには、次の手順を使用します。
共有 VPC を使用したマルチクラスタ Service を設定する手順に沿って操作します。
構成クラスタにサービスを作成してエクスポートします。
マルチクラスタの内部 Gateway を使用する場合は、プロキシ専用サブネットを作成します。
これらの手順を完了したら、トポロジに応じてデプロイを検証できます。
トラブルシューティング
内部 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 コントローラの詳細を確認する。