Google Kubernetes Engine(GKE)Autopilot クラスタと Standard クラスタを使用して、マルチクラスタ ネットワーキングに移行する

マルチクラスタ ネットワーキングは、リージョンごとの可用性を高める、レイテンシを短縮するためにグローバルに分散されたユーザーに接近する、チーム間で組織を分離する、などのユースケースを可能にする貴重なツールです。Google Kubernetes Engine(GKE)にはマルチクラスタ ネットワーキングの機能が組み込まれており、GKE クラスタのフリート全体で有効にして大規模に使用できます。この機能を使用すると、GKE Standard と Autopilot 間でデプロイされたインフラストラクチャの結合や移行を行って、各アプリケーションのアーキテクチャ ニーズに対応することもできます。

GKE Autopilot クラスタでは、Google がコントロール プレーンやノードなどのインフラストラクチャを管理します。代わりにノードを構成および管理する場合、GKE にはStandard モードが用意されています。モードの違いについては、クラスタ オペレーション モードの選択をご覧ください。

このドキュメントでは、いくつかのデプロイ トポロジを使用して、これらの機能について説明します。1 つの GKE クラスタにデプロイされたアプリケーションを、GKE Standard クラスタと Autopilot クラスタ間のマルチクラスタ デプロイに移行する方法について学習します。East-West トラフィックには GKE マルチクラスタ サービスを使用し、North-South マルチクラスタ ネットワーキングを有効にするためにマルチクラスタ Gateway を使用します。

このページは、複数の Kubernetes クラスタにサービスをデプロイするために GKE を使用または計画するクラウド アーキテクトと運用チームを対象としています。このページを読む前に、Kubernetes について理解しておいてください。

マルチクラスタ Service とマルチクラスタ Gateway

Kubernetes は、異なるクラウドゾーン間で単一のコントロール プレーンを使用して動作し、サービスに復元力と高い可用性を実現できます。GKE では、この手順をさらに進めて、クラスタ間のサービス ディスカバリと呼び出しメカニズムを提供する GKE マルチクラスタ サービス(MCS)を提供します。この機能を使用するサービスは、仮想 IP を持つクラスタ間で検出とアクセスが可能になり、これは、クラスタでアクセス可能な ClusterIP Service の動作と適合します。このアプローチには次のような利点があります。

  • サービスは、同じリージョンまたは異なるリージョンの複数のクラスタ(East-West トラフィック)間でロードバランスできます。
  • クロスリージョン サービスの高可用性オプションを実現します。
  • ステートフル ワークロードとステートレス ワークロードは、個別のクラスタにデプロイして管理できます。
  • 共有サービスは複数のクラスタで使用できます。

MCS をデプロイする方法の詳細については、マルチクラスタ Service の構成をご覧ください。

GKE は、GKE Gateway Controller を使用する Kubernetes Gateway API の実装を実現します。Gateway を使用すると、GKE は Google Cloud ロードバランサをデプロイし、GKE にデプロイされたサービスに対してインバウンド(north-south)トラフィックの転送を実現できます。また、GKE は GKE Gateway Controller を拡張して、異なる GKE クラスタにデプロイされたサービスにトラフィックを転送するマルチクラスタ Gateway(MCG)も備えています。

次の図は、MCS と MCG を組み合わせる場合に、サービスのデプロイとトラフィック ルーティングの補完的な側面を単一のコントロール プレーンから管理する方法を示しています。

マルチクラスタ サービスは、クラスタ内のサービス間の通信を容易にします。マルチクラスタ Gateway では、クラスタ間でトラフィックをルーティングするためにロードバランサをデプロイします。

詳細については、マルチクラスタ Gateway のデプロイをご覧ください。

移行の概要

GKE のマルチクラスタ ネットワーク機能は、さまざまなプロファイルのワークロードにメリットをもたらします。たとえば、トラフィックが急増しているステートレス コンポーネントで、より効率的なコストモデルを実現するために Autopilot に移行することが必要な場合があります。

また、アプリケーションのフロントエンドをユーザーの近くに配置したいと考える場合もあります。このアプローチは、レイテンシを短縮しキャッシュ保存を行うことで、アプリケーションのパフォーマンスとユーザー エクスペリエンスを改善します。また、1 つのロケーションにしか存在できないステートフル コンポーネントにアプリケーションが依存している場合があります。このような構成で、クライアント トラフィックをそのロケーションにある適切なクラスタに送信するには North-South マルチクラスタ ロード バランシングが必要になります。また、クラスタ間でトラフィックを送信してそのステートフル コンポーネントに到達させるには、East-West マルチクラスタ ロード バランシングも必要です。

このドキュメントでは、Online Boutique のクラウド マイクロサービスのデモ アプリケーションを使用して、シングルゾーン デモのデプロイを強化するために使用できるマルチクラスタ パターンについて説明します。アプリケーションのシングルゾーン バージョンから始めます。さらに、マルチクラスタ Service とマルチクラスタ Gateway を使用して高可用性と復元性の要素を追加し、Autopilot を活用して運用作業を軽減します。

単一クラスタの最初のデプロイ

次の図では、Online Boutique アプリケーションは、最初に std-west という名前の単一の GKE Standard モードクラスタにデプロイされ、LoadBalancer Service を使用して公開されます。

通常の HTTP 外部 LoadBalancer Service により公開されたすべてのサービスを実行する単一の Standard モードの GKE クラスタ。

マルチクラスタ Service への移行

次の中間ステップでは、2 つの追加クラスタを作成し、ステートレス サービスを追加のリージョンにデプロイします。単一の std-west GKE Standard クラスタとは別の 2 つの個別のリージョンに auto-east と auto-central という名前の 2 つの GKE Autopilot クラスタを作成し、そのクラスタを Google Cloud フリートに登録します。

フリートとは、複数のクラスタと他のリソースを論理的に編成するための Google Cloud コンセプトです。フリートを使用することによって、マルチクラスタ機能の使用と管理、複数のシステム間での一貫したポリシーの適用が可能になります。

ServiceExport を使用して、onlineboutique Namespace 内の std-west クラスタの cartservice を新しいフリート クラスタにエクスポートします。Online Boutique の frontend Service を 3 つのクラスタすべてにデプロイし、ClusterIP サービスを介して公開します。次に、ServiceExports を使用してサービスをフリートにエクスポートします。Online Boutique のミドルウェア レイヤなどのサービス(productcatalogshippingadservice など)も、3 つのクラスタすべてにデプロイされます。

フリート内の任意のクラスタで実行される Pod は、そのサービスの ClusterSet URI にリクエストを送信することで、エクスポートされた Service にアクセスできます。リクエストは、サービスをバックアップするエンドポイントに転送されます。

frontend Service は、ミドルウェア サービス(productcatalogservicecurrencyservice など)を同じクラスタ内でローカルに利用できます。このアーキテクチャは、受信リクエストをフロントエンドがリクエストに応答するリージョンにローカルに維持し、不要なリージョン間ネットワーク トラフィック課金を回避します。

次の図は、2 つのマルチクラスタ サービスを示しています。ステートレス フロントエンド サービスが 3 つのクラスタにデプロイされ、ステートフル バックエンド カートサービスが 1 つのクラスタにデプロイされます。また、この中間ステップでは、フロントエンドの外部 LoadBalancer サービスによって作成された外部パススルー ネットワーク ロードバランサを使用して、フロントエンド サービスの受信トラフィックが引き続き us-west1 の元の GKE Standard クラスタにルーティングされることを示しています。

マルチクラスタ サービスは 3 つの GKE クラスタで実行されますが、トラフィックは通常の HTTP 外部ロードバランサ サービスで単一のクラスタに転送されます。

マルチクラスタ Gateway への移行

最後のステップでは、マルチクラスタ Gateway を使用して、frontend Service のインバウンド トラフィックを外部クライアント リクエストからフリート内の複数のクラスタのサービスにルーティングします。

この構成の一部として作成される GatewayHTTPRoute リソースの構成をホストして管理するために、config-central という名前の 4 番目のクラスタがフリートに追加されます。HTTPRoute リソースは、/ 接頭辞をフロントエンドの ServiceImport にマッピングします。Online Boutique のフロントエンドのトラフィックは、使用可能ないずれかのリージョンの正常なエンドポイントに送信されます。このアプローチにより、Online Boutique アプリケーション アーキテクチャに高可用性の要素が追加されます。

次の図では、マルチクラスタ Gateway がグローバル クラウド ロードバランサをデプロイしています。このロードバランサは、フリート内の 3 つのアプリケーション クラスタそれぞれにデプロイされたステートレスの frontend Service に外部トラフィックをルーティングします。

マルチクラスタ Service は 3 つの GKE クラスタで実行され、トラフィックはマルチクラスタの外部 Gateway を使用してすべてのクラスタのフロントエンド サービスに分散されます。

最終状態では、この独自のパターンは、アプリケーションのステートフル部分(cartservice と redis-cart)とステートレス部分(frontend、emailservice、checkoutservice、recommendationservice、paymentservice、productcatalogservice、currencyservice、shippingservice、adservice)の間の疎結合を示しています。このページの範囲外ですが、このアプローチにより、復元力と高可用性をステートフル サービスレイヤに追加できるようになります。

環境を準備する

このチュートリアルでは、Cloud Shell を使用してコマンドを入力します。Cloud Shell を使用すると、Google Cloud コンソールでコマンドラインにアクセスできます。また、Google Cloud SDK や Google Cloud CLI などのツールも含まれています。Cloud Shell は、Google Cloud コンソールの下部にウィンドウとして表示されます。初期化が完了するまでに数分かかることもありますが、ウィンドウはすぐに表示されます。

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  2. Cloud Shell で、このガイドで使用される環境変数を定義します。PROJECT_ID は実際のプロジェクト ID に置き換えます。

    export PROJECT=PROJECT_ID
    gcloud config set project ${PROJECT}
    
  3. このページの手順に必要なサービスを有効にします。

    gcloud services enable \
        gkehub.googleapis.com \
        multiclusteringress.googleapis.com \
        dns.googleapis.com \
        trafficdirector.googleapis.com \
        cloudresourcemanager.googleapis.com \
        multiclusterservicediscovery.googleapis.com \
        container.googleapis.com
    
    gcloud container fleet multi-cluster-services enable
    

    マルチクラスタ サービスでは、Cloud DNS、ファイアウォール ルール、Cloud Service Mesh などの Google Cloud コンポーネントを管理しているため、これらの API も有効にする必要があります。詳細については、Cloud Service Mesh の概要をご覧ください。

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

    Operation "operations/acf.p2-822685001869-ee4ebe78-6dd8-465e-b0fd-3b0e5f964bad"
    finished successfully.
    
    Waiting for Feature Multi-cluster Services to be created...done.
    
  4. マルチクラスタ Service が ACTIVE 状態になっていることを確認します。

    gcloud container fleet multi-cluster-services describe
    

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

    createTime: '2021-11-30T21:59:25.245190894Z'
    name: projects/PROJECT_ID/locations/global/features/multiclusterservicediscovery
    resourceState:
      state: ACTIVE
    spec: {}
    updateTime: '2021-11-30T21:59:27.459063070Z'
    

    state の値が ACTIVE でない場合は、マルチクラスタ サービスのトラブルシューティングの詳細をご覧ください。

  5. GKE クラスタを作成して構成する

    マルチクラスタ パターンを示すために、3 つの独立したクラウド リージョンの 3 つのアプリケーション クラスタと、Gateway リソースの構成をホストする 1 つのクラスタを使用します。プロジェクトに関連付けられたフリートにすべてのクラスタを登録します。 Google Cloud プロジェクトに関連付けることができるフリートは 1 つのみです。このプロジェクトは、フリート ホスト プロジェクトと呼ばれます。

    1. Standard および Autopilot GKE クラスタを作成します。

      gcloud container clusters create std-west \
          --location us-west1-a \
          --num-nodes=6 \
          --enable-ip-alias \
          --release-channel regular \
          --workload-pool=${PROJECT}.svc.id.goog \
          --async
      
      gcloud container clusters create-auto auto-east \
          --location us-east1 \
          --release-channel regular \
          --async
      
      gcloud container clusters create-auto auto-central \
          --location us-central1 \
          --release-channel regular \
          --async
      
      gcloud container clusters create config-central \
          --location us-central1 \
          --num-nodes=1 \
          --enable-ip-alias \
          --release-channel regular \
          --workload-pool=${PROJECT}.svc.id.goog \
          --async
      

      Workload Identity Federation for GKE は、GKE Autopilot クラスタでデフォルトで有効になるため、GKE Standard クラスタの場合と同様、これらのクラスタの作成時に --workload-pool フラグを使用する必要はありません。

    2. クラスタの STATUSPROVISIONING から RUNNING に変わるまで待ちます。この処理には 10 分ほどかかることがあります。ウォッチループを使用して進行状況をモニタリングできます。

      watch -n 20 --difference=permanent "gcloud container clusters list"
      

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

      NAME: auto-central
      LOCATION: us-central1
      MASTER_VERSION: 1.21.5-gke.1802
      MASTER_IP: 107.178.213.138
      MACHINE_TYPE: e2-medium
      NODE_VERSION: 1.21.5-gke.1802
      NUM_NODES: 3
      STATUS: PROVISIONING
      
      NAME: config-central
      LOCATION: us-central1
      MASTER_VERSION: 1.21.5-gke.1802
      MASTER_IP:
      MACHINE_TYPE: e2-medium
      NODE_VERSION: 1.21.5-gke.1802
      NUM_NODES: 9
      STATUS: PROVISIONING
      
      NAME: auto-east
      LOCATION: us-east1
      MASTER_VERSION: 1.21.5-gke.1802
      MASTER_IP: 35.229.88.209
      MACHINE_TYPE: e2-medium
      NODE_VERSION: 1.21.5-gke.1802
      NUM_NODES: 3
      STATUS: PROVISIONING
      
      NAME: std-west
      LOCATION: us-west1-a
      MASTER_VERSION: 1.21.5-gke.1802
      MASTER_IP: 35.197.93.113
      MACHINE_TYPE: e2-medium
      NODE_VERSION: 1.21.5-gke.1802
      NUM_NODES: 6
      STATUS: PROVISIONING
      
    3. すべてのクラスタが RUNNING 状態になったら、CTRL-C を押してコマンドを中断します。

    4. フリート ホスト プロジェクトの MCS サービス アカウントに、自身のプロジェクトのネットワーク ユーザー ロールを付与する Identity and Access Management(IAM)ポリシー バインディングを追加します。

      gcloud projects add-iam-policy-binding ${PROJECT} \
          --member "serviceAccount:${PROJECT}.svc.id.goog[gke-mcs/gke-mcs-importer]" \
          --role "roles/compute.networkViewer"
      

      Workload Identity Federation for GKE を使用して、プロジェクトの VPC ネットワーク構成に対する読み取りアクセス権を MCS サービスに付与します。そのため、フリート ホスト プロジェクトの MCS インポータ GKE サービス アカウントにはこのロールが必要です。

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

      - members:
        - serviceAccount:PROJECT_ID.svc.id.goog[gke-mcs/gke-mcs-importer]
        role: roles/compute.networkViewer
      [...]
      
    5. GKE Standard クラスタと Autopilot クラスタをプロジェクト フリートに登録します。詳細については、クラスタの登録をご覧ください。このステップには最長で 5 分ほどかかります

      gcloud container fleet memberships register std-west \
          --gke-cluster us-west1-a/std-west \
          --enable-workload-identity \
          --project=${PROJECT}
      
      gcloud container fleet memberships register auto-east \
          --gke-cluster us-east1/auto-east \
          --enable-workload-identity \
          --project=${PROJECT}
      
      gcloud container fleet memberships register auto-central \
          --gke-cluster us-central1/auto-central \
          --enable-workload-identity \
          --project=${PROJECT}
      
      gcloud container fleet memberships register config-central \
          --gke-cluster us-central1/config-central \
          --enable-workload-identity \
          --project=${PROJECT}
      

      各コマンドの出力は次の例のようになります。

      Waiting for membership to be created...done.
      Created a new membership [projects/PROJECT_ID/locations/global/memberships/std-west] for the cluster [std-west]
      Generating the Connect Agent manifest...
      Deploying the Connect Agent on cluster [std-west] in namespace [gke-connect]...
      Deployed the Connect Agent on cluster [std-west] in namespace [gke-connect].
      Finished registering the cluster [std-west] with the Hub.
      
    6. クラスタに接続して kubeconfig エントリを生成します。

      gcloud container clusters get-credentials std-west \
          --location us-west1-a --project $PROJECT
      
      gcloud container clusters get-credentials auto-east \
          --location us-east1 --project $PROJECT
      
      gcloud container clusters get-credentials auto-central \
          --location us-central1 --project $PROJECT
      
      gcloud container clusters get-credentials config-central \
          --location us-central1 --project $PROJECT
      

      各コマンドの出力は次の例のようになります。

      Fetching cluster endpoint and auth data.
      kubeconfig entry generated for std-west.
      
    7. このページの以降の部分で作業しやすくなるように、クラスタのコンテキストの名前を変更します。

      kubectl config rename-context \
          gke_${PROJECT}_us-west1-a_std-west \
          std-west
      
      kubectl config rename-context \
          gke_${PROJECT}_us-east1_auto-east \
          auto-east
      
      kubectl config rename-context \
          gke_${PROJECT}_us-central1_auto-central \
          auto-central
      
      kubectl config rename-context \
          gke_${PROJECT}_us-central1_config-central \
          config-central
      

      このガイドでは、コンテキストは場所に基づいて命名されます。代替名を指定することもできますが、このガイドの残りの手順では、この手順で使用されている名前を使用します。

    GKE Standard に Online Boutique をデプロイする

    デモデプロイの最初のステップでは、Online Boutique アプリケーション サービスの完全なセットを、us-west1 にある単一の GKE Standard クラスタ std-west にデプロイします。

    1. std-westonlineboutique という名前空間を作成します。

      kubectl create namespace onlineboutique --context std-west
      

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

      namespace/onlineboutique created
      
    2. Online Boutique GitHub リポジトリのクローンを作成し、WORKDIR 変数を設定します。

      cd ~
      
      git clone --branch release/v0.4.1 \
          https://github.com/GoogleCloudPlatform/microservices-demo.git
      
      cd microservices-demo/release && export WORKDIR=`pwd`
      
    3. Online Boutique を std-west にデプロイします。このプロセスでは、Online Boutique のマイクロサービスのすべてに DeploymentsServices が作成され、また Online Boutique のフロントエンド サービスを外部に公開する LoadBalancer Service も含まれます。

      cd $WORKDIR
      
      kubectl apply -f kubernetes-manifests.yaml \
          -n onlineboutique --context=std-west
      
    4. LoadBalancer Service が外部 IP を取得するまで待ちます。

      watch -n 20 --difference=permanent \
           "kubectl get svc frontend-external -n onlineboutique --context=std-west"
      

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

      NAME                TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
      frontend-external   LoadBalancer   10.60.5.62   <pending>     80:30359/TCP   43s
      

      Service の準備が整うと、EXTERNAL-IP 列にロードバランサのパブリック IP アドレスが表示されます。

    5. Service の準備ができたら、ロードバランサの外部 IP アドレスを取得し、curl を使用してフロントエンドの準備ができていることを確認します。この curl コマンドでエラーが返ってくる場合は、しばらく待ってからもう一度お試しください。

        curl $(kubectl get svc frontend-external \
            -n onlineboutique --context=std-west \
            -o=jsonpath="{.status.loadBalancer.ingress[0].ip}") | \
              grep -e Cluster -e Zone -e Pod
      

      curl コマンドの正常な出力は次の例のようになります。

      <b>Cluster: </b>std-west<br/>
      <b>Zone: </b>us-west1-a<br/>
      <b>Pod: </b>frontend-b7bddcc97-wdjsk
      

    これで、us-west1-a で実行される Online Boutique のシングルゾーン バージョンが作成されました。ウェブブラウザを使用して、frontend-external LoadBalancer Service に割り当てられた外部 IP に移動し、アプリケーションにアクセスしてその動作を観察することもできます。次の図に、この最初の単一デプロイを示しています。

    通常の HTTP 外部 LoadBalancer サービスにより公開されたすべてのサービスを実行する単一の Standard モードの GKE クラスタ。

    cartservice をマルチクラスタ サービスとしてエクスポートする

    このセクションでは、高可用性の要素をアプリケーションに追加することを開始します。バックエンド cartservice をマルチクラスタ Service として GKE Autopilot クラスタにエクスポートします。

    1. 残りのクラスタに onlineboutique という名前空間を作成します。

      kubectl create namespace onlineboutique --context auto-east
      
      kubectl create namespace onlineboutique --context auto-central
      
      kubectl create namespace onlineboutique --context config-central
      

      各コマンドの出力は次の例のようになります。

      namespace/onlineboutique created
      
    2. cartservicestd-west クラスタから ClusterSet の他のすべてのクラスタにエクスポートします。ServiceExport オブジェクトは、名前空間 onlineboutique が存在するフリート内のすべてのクラスタにエクスポートするために、GKE マルチクラスタ Service を使用して cartservice Service を登録します。詳細については、エクスポートするサービスの登録をご覧ください。

      cat <<EOF>> $WORKDIR/cartservice-export.yaml
      kind: ServiceExport
      apiVersion: net.gke.io/v1
      metadata:
       namespace: onlineboutique
       name: cartservice
      
      EOF
      
      kubectl apply -f $WORKDIR/cartservice-export.yaml \
          -n onlineboutique --context=std-west
      

    マルチクラスタ パターンのアプリケーション マニフェストを適用する

    このセクションでは、キュレートされた 2 つのマニフェストを適用して、マルチクラスタ パターンをデプロイします。これらのマニフェストには、以前に std-west クラスタに適用した kubernetes-manifests.yaml の選択された部分が含まれます。

    • 最初のマニフェストは frontendDeploymentServiceServiceExport に使用されます。
    • 2 番目のマニフェストは、ミドルウェア Servicesemailservicecheckoutservicerecommendationservicepaymentserviceproductcatalogservicecurrencyserviceshippingserviceadservice)を、frontend が実行されているすべてのリージョンにデプロイします。リクエストをできるだけリージョンにローカルに保つことで、リージョン間で不要なネットワーク トラフィックが発生することを回避できます。

    フリート内の任意のクラスタで実行される Pod は、そのサービスの ClusterSet URI に SERVICE_NAME.NAMESPACE.svc.clusterset.local の形式でリクエストを送信することで、エクスポートされた Service にアクセスできます。たとえば、3 つのサンプル クラスタの frontend Deploymentsは、cartservice.onlineboutique.svc.clusterset.local へリクエスト送信することで、onlineboutique 名前空間で cartservice を使用できます。

    このため、各マニフェストでは cartservice のホスト名を ClusterSet URI に更新しています。ですから、この演習は大変重要です。このサービスのホスト名が更新されていない場合、frontend Service は cartservice.onlineboutique.svc.clusterset.local ではなく kube-dns を cartservice にリクエストします。この動作により、ローカル バージョンの cartservice が使用できないクラスタで HTTP Status 500 エラーが発生し、frontend Pod が異常になります。

    1. マニフェストを含む GitHub リポジトリの環境変数を設定します。

      export MANIFEST_REPO_PATH=https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/cluster-migration
      
    2. マニフェストを適用して、3 つのワークロード クラスタすべてにフロントエンド レイヤをデプロイします。

      kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-frontend-manifests.yaml \
          -n onlineboutique --context=std-west
      
      kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-frontend-manifests.yaml \
          -n onlineboutique --context=auto-east
      
      kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-frontend-manifests.yaml \
          -n onlineboutique --context=auto-central
      
    3. マニフェストを適用して、3 つのワークロード クラスタすべてにミドルウェア レイヤをデプロイします。

      kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-middleware-manifests.yaml \
          -n onlineboutique --context=std-west
      
      kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-middleware-manifests.yaml \
          -n onlineboutique --context=auto-east
      
      kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-middleware-manifests.yaml \
          -n onlineboutique --context=auto-central
      

    フロントエンドの DeploymentServiceServiceExportが、クラスタ std-westauto-eastauto-central で有効になりました。また、各クラスタには、Online Boutique ミドルウェア サービスが実行されています。ただし、次の図に示すように、外部トラフィックは us-west1 の初期クラスタで実行される Service にのみ引き続きルーティングされます。

    マルチクラスタ サービスは 3 つの GKE クラスタで実行されますが、トラフィックは通常の HTTP 外部ロードバランサ サービスで単一のクラスタに転送されます。

    マルチクラスタ Gateway を有効にして構成する

    このセクションでは、3 つのクラスタすべてにトラフィックをルーティングし、すべてのクラスタのフロントエンド間で外部トラフィックをロード バランシングします。この構成を実現するには、マルチクラスタ Gateway(MCG)を使用します。これらの MCG を設定する手順は、マルチクラスタ Gateway の有効化で詳しく説明されているガイダンスに従っています。

    これらの手順では、config-central クラスタを使用して、Gateway リソースの構成をホストします。

    1. すべてのクラスタが正常にフリートに登録されたことを確認します。

      gcloud container fleet memberships list --project=$PROJECT
      

      次の出力例は、すべてのクラスタが正常に登録されたことを示しています。

      NAME: auto-central
      EXTERNAL_ID: 21537493-32ea-4a41-990d-02be2c1b319f
      
      NAME: config-central
      EXTERNAL_ID: 4369423e-ea7b-482d-a0eb-93b560e67b98
      
      NAME: std-west
      EXTERNAL_ID: 7fcb048b-c796-476b-9698-001a00f91ab3
      
      NAME: auto-east
      EXTERNAL_ID: aae2d2ff-b861-4a38-bcaf-612f14810012
      
    2. config-central クラスタに Gateway API カスタム リソース定義をインストールします。

      kubectl --context=config-central kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.5.0" \
          | kubectl apply -f -
      

      この手順では、GatewayClass リソース、Gateway リソース、HTTPRoute リソースなどの Gateway API カスタム リソースの定義をインストールします。カスタム リソースの定義は、Kubernetes Network Special Interest Group によって管理されています。インストールが完了すると、GKE Gateway Controller を使用できます。

    3. フリートのマルチクラスタ Ingress をまだ有効にしていない場合は、有効にします。この機能を有効にすると、マルチクラスタ Gateway コントローラも有効になります。

      gcloud container fleet ingress enable \
          --config-membership=config-central \
          --project=$PROJECT
      
      gcloud container fleet ingress describe --project=$PROJECT
      

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

      createTime: '2021-12-08T23:10:52.505888854Z'
      name: projects/PROJECT_ID/locations/global/features/multiclusteringress
      resourceState:
        state: ACTIVE
      spec:
        multiclusteringress:
          configMembership: projects/zl-mcs-expf61cbd13/locations/global/memberships/config-central
      state:
        state:
          code: OK
          description: Ready to use
          updateTime: '2021-12-08T23:11:37.994971649Z'
      updateTime: '2021-12-08T23:11:38.098244178Z'
      

      state の値が ACTIVE でない場合は、マルチクラスタ Ingress のトラブルシューティングとオペレーションをご覧ください。

    4. GatewayClassesconfig-central クラスタで利用可能なことを確認します。

      kubectl get gatewayclasses --context=config-central
      

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

      NAME                                  CONTROLLER                  AGE
      gke-l7-global-external-managed        networking.gke.io/gateway   18s
      gke-l7-global-external-managed-mc     networking.gke.io/gateway   19s
      gke-l7-regional-external-managed      networking.gke.io/gateway   18s
      gke-l7-regional-external-managed-mc   networking.gke.io/gateway   19s
      gke-l7-gxlb                           networking.gke.io/gateway   74s
      gke-l7-gxlb-mc                        networking.gke.io/gateway   16s
      gke-l7-rilb                           networking.gke.io/gateway   74s
      gke-l7-rilb-mc                        networking.gke.io/gateway   16s
      

      GatewayClass リソースによって機能が異なります。どのタイプをいつ使用するかについては、GatewayClass の機能をご覧ください。

    5. external-http Gateway リソースを config-central にデプロイします。

      cat <<EOF>> $WORKDIR/external-http-gateway.yaml
      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: external-http
        namespace: onlineboutique
      spec:
        gatewayClassName: gke-l7-global-external-managed-mc
        listeners:
        - protocol: HTTP
          port: 80
          name: http
      EOF
      
      kubectl apply -f external-http-gateway.yaml \
          -n onlineboutique --context=config-central
      

      gatewayClassName フィールドで示されているように、このリソースは GatewayClassgke-l7-global-external-managed-mc で、レイヤ 7 外部 Cloud Load Balancing を管理し、マルチクラスタ アプリケーションを公開します。

    6. config-central に public-frontend-route という名前の HTTPRoute をデプロイします。

      cat <<EOF>> $WORKDIR/public-frontend-route.yaml
      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: public-frontend-route
        namespace: onlineboutique
      spec:
        parentRefs:
        - name: "external-http"
        hostnames:
        - "store.example.com"
        rules:
        - matches:
          - path:
              type: PathPrefix
              value: /
          backendRefs:
          - name: frontend
            group: net.gke.io
            kind: ServiceImport
            port: 80
      EOF
      
      kubectl apply -f public-frontend-route.yaml \
          -n onlineboutique --context=config-central
      

      デプロイされた HTTPRoute リソースは外部レイヤ 7 Cloud Load Balancing リソースを作成し、std-westauto-eastauto-central クラスタで実行中のフロントエンド サービスにより、フロントエンド ServiceImport を公開します。

      次の図は、マルチクラスタ Gateway がデプロイされた後に、3 つのアプリケーション クラスタのいずれかのフロントエンド マルチクラスタ Service のいずれかにトラフィックをルーティングする方法を示しています。

      マルチクラスタ Service は 3 つの GKE クラスタで実行され、トラフィックはマルチクラスタの外部 Gateway を使用してすべてのクラスタのフロントエンド サービスに分散されます。

    7. プロビジョニングされた外部 IP アドレスがロードバランサで使用できる状態になるまで待ってから、次のステップに進みます。IP アドレスが割り振られるまで 10 分ほどかかることがあります。ウォッチループを使用して進行状況をモニタリングできます。ロードバランサには、gkemcg-onlineboutique-external-http-k09mfhk74gop のようなパターンの名前が付いています。

      watch -n 20 --difference=permanent \
          "gcloud compute forwarding-rules list \
              | grep -A 5 NAME..*external-http"
      

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

      NAME: gkemcg-onlineboutique-external-http-k09mfhk74gop
      REGION:
      IP_ADDRESS: 34.149.29.176
      IP_PROTOCOL: TCP
      TARGET: gkemcg-onlineboutique-external-http-k09mfhk74gop
      
    8. ロードバランサの準備が完了したら、Cloud Shell で次のコマンドを実行して、external-http-gateway.yamlpublic-frontend-route.yaml マニフェストを適用して作成したロードバランサの外部 IP アドレスをエクスポートします。

      export EXTERNAL_LB_IP=$(kubectl --context=config-central \
                                  -n onlineboutique get gateway external-http \
                                  -o=jsonpath='{.status.addresses[0].value}')
      
    9. 適切なヘッダーを使用してロードバランサにリクエストを送信すると、フロントエンド サービスによって配信される HTML コンテンツが返されます。たとえば、store.example.com ホスト名をフロントエンドの ServiceImport にマッピングするように HTTPRoute リソースを構成したため、HTTP リクエストを送信する場合は HOST ヘッダーを指定する必要があります。次の curl の例でエラーが返ってくる場合は、数分待ってからもう一度お試しください。

      curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
          grep -e Cluster -e Zone -e Pod
      

      curl コマンドの正常な出力は次の例のようになります。

      <b>Cluster: </b>auto-central<br/>
      <b>Zone: </b>us-central1-f<br/>
      <b>Pod: </b>frontend-7c7d596ddc-jdh8f
      

    アプリケーションのマルチリージョン ルーティング動作をテストする

    マルチクラスタ サービスとマルチクラスタ Gateway を使用して得られる優れた機能の一つは、外部リクエストが地理的に最も近いクラスタにルーティングされることです。

    アプリケーションのマルチリージョンの動作をテストするには、クラスタをデプロイしたさまざまなリージョンから発信されるトラフィックを生成します。サービス提供クラスタ(std-westauto-eastauto-central)のそれぞれに 1 つずつ、3 つ小規模な Pod を作成し、HTTP リクエストをロードバランサ エンドポイントに送信するために使用できます。結果では、どのフロントエンド Pod が応答するかを確認できます。

    1. クライアント Pod を作成します。

      kubectl run --context=std-west \
                  --image=radial/busyboxplus:curl client-west \
                  -- sh -c 'while sleep 3600; do :; done'
      
      kubectl run --context=auto-east \
                  --image=radial/busyboxplus:curl client-east \
                  -- sh -c 'while sleep 3600; do :; done'
      
      kubectl run --context=auto-central \
                  --image=radial/busyboxplus:curl client-central \
                  -- sh -c 'while sleep 3600; do :; done'
      
    2. Pod が使用可能になったら、curl コマンドを使用して、std-west クラスタのクライアント Pod からロードバランサ エンドポイントにリクエストを送信し、レスポンスを確認します。

      kubectl exec -it --context=std-west client-west \
          -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
                 grep -e Cluster -e Zone -e Pod
      

      curl コマンドの正常な出力は次の例のようになります。

      <b>Cluster: </b>std-west<br/>
      <b>Zone: </b>us-west1-a<br/>
      <b>Pod: </b>frontend-7cf48b79cf-trzc4
      
    3. auto-east クラスタのクライアント Pod から同じ curl リクエストを実行し、レスポンスを確認します。

      kubectl exec -it --context=auto-east client-east \
          -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
                 grep -e Cluster -e Zone -e Pod
      

      curl コマンドの正常な出力は次の例のようになります。

      <b>Cluster: </b>auto-east<br/>
      <b>Zone: </b>us-east1-d<br/>
      <b>Pod: </b>frontend-6784b6df98-scdws
      

      これは Autopilot クラスタであるため、Pod をスケジュールするために、クラスタで追加のリソースのプロビジョニングが必要になることがあります。次の例のような出力が表示された場合は、しばらく待ってから再試行してください。

       Error from server (BadRequest): pod client-east does not have a host assigned
      
    4. auto-central クラスタのクライアント Pod から curl を実行し、レスポンスを確認します。

      kubectl exec -it --context=auto-central client-central \
          -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
              grep -e Cluster -e Zone -e Pod
      

      curl コマンドの正常な出力は次の例のようになります。

      <b>Cluster: </b>auto-central<br/>
      <b>Zone: </b>us-central1-b<br/>
      <b>Pod: </b>frontend-6784b6df98-x2fv4
      

      この結果により、トラフィックがリクエスト元に最も近いロケーションの対応する Pod にルーティングされることが確認できます。

    アプリケーションのマルチリージョンの復元性をテストする

    効率的なトラフィック ルーティングに加えて、複数のリージョンでサービスを実行すると、発生する可能性は低いが依然として発生する可能性はあるインフラストラクチャ障害の復元力を高めることができます。

    特定のクラスタで frontend Deployments を削除して動作をテストしてから、そのリージョンのクライアント Pod から curl コマンドを再試行します。アプリケーションがまだ使用可能であることを確認し、リクエストに応答する Pod のロケーションを確認します。

    1. std-west クラスタの client-west Pod から curl コマンドを実行し、結果が us-west1 のフロントエンドから届いたものであることを確認します。

      kubectl exec -it --context=std-west client-west \
          -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP  | \
                 grep -e Cluster -e Zone -e Pod
      

      curl コマンドの正常な出力は次の例のようになります。

      <b>Cluster: </b>std-west<br/>
      <b>Zone: </b>us-west1-a<br/>
      <b>Pod: </b>frontend-7cf48b79cf-trzc4
      
    2. std-west クラスタの frontend Deployment を削除します。

      kubectl delete deploy frontend \
          -n onlineboutique --context=std-west
      

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

      deployment.apps "frontend" deleted
      
    3. std-west クラスタの client-west Pod から別のリクエストを送信します。auto-east クラスタか auto-central クラスタにある残りの frontend Deployments のうちの 1 つからレスポンスが届くはずです。

      kubectl exec -it --context=std-west client-west \
          -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
                 grep -e Cluster -e Zone -e Pod
      

      次の例のような出力は、このリクエストに応答する正常な Pod のロケーションを示しています。

      <b>Cluster: </b>auto-central<br/>
      <b>Zone: </b>us-central1-b<br/>
      <b>Pod: </b>frontend-6784b6df98-x2fv4
      

      または

      <b>Cluster: </b>auto-east<br/>
      <b>Zone: </b>us-east1-d<br/>
      <b>Pod: </b>frontend-6784b6df98-scdws
      

      このコマンドを数回実行して、結果が交互に変わるのを確認します。

    このデモデプロイでは、マルチクラスタ Service とマルチクラスタ Gateway を使用して、Online Boutique アプリケーションに復元力と地理的分散の要素を追加しています。リクエストは地理的に最も近いリージョンにルーティングされ、あるリージョンのフロントエンドやミドルウェア サービスで障害が発生しても、エンドユーザーはアプリケーションを正常に使用できます。