マルチクラスタ Service の構成


このページでは、マルチクラスタ Service(MCS)を有効にして使用する方法を説明します。MCS の仕組みとその利点の詳細については、マルチクラスタ Service をご覧ください。

Google Kubernetes Engine(GKE)MCS 機能は、クラスタ境界を超えて Kubernetes Service の範囲を拡張し、複数の GKE クラスタ間で Service を検出して呼び出せるようにします。既存の Service のサブセットまたは新しい Service をエクスポートできます。

MCS を使用して Service をエクスポートすると、その Service はフリート内のすべてのクラスタで使用可能になります。

MCS によって管理される Google Cloud リソース

MCS は、Google Cloud の次のコンポーネントを管理します。

  • Cloud DNS: MCS は、フリート クラスタ内のエクスポートされた Service ごとに Cloud DNS ゾーンとレコードを構成します。これにより、他のクラスタで実行されている Service に接続できます。これらのゾーンとレコードは、複数のクラスタにエクスポートする Service に基づいて作成、読み取り、更新、削除されます。

  • ファイアウォール ルール: MCS は、フリート内のクラスタ間での Pod の相互通信を可能にするファイアウォール ルールを構成します。ファイアウォール ルールの作成、読み取り、更新、削除は、フリートに追加するクラスタに応じて行われます。これらのルールは、GKE クラスタ内の Pod 間の通信を有効にするために GKE が作成するルールと類似しています。

  • Traffic Director: MCS は、Traffic Director をコントロール プレーンとして使用して、クラスタ間でエンドポイントとそのヘルスを追跡します。

要件

MCS の要件は次のとおりです。

  • MCS では、Google Cloud 上の VPC ネイティブ GKE クラスタからの Service のエクスポートのみがサポートされています。詳細については、VPC ネイティブ クラスタの作成をご覧ください。VPC ネイティブ以外の GKE Standard クラスタは使用できません。

  • クラスタ間の接続が可能かどうかは、それらのクラスタが同じ VPC ネットワーク内、ピアリングした VPC ネットワーク内、または共有 VPC ネットワーク内で稼働しているかどうかに依存します。そうしないと、外部サービスの呼び出しはネットワーク境界を越えることができません。

  • フリートが複数の Google Cloud プロジェクトと VPC ネットワークにまたがることがありますが、単一のマルチクラスタ Service を単一のプロジェクトと単一の VPC ネットワークからエクスポートする必要があります。

  • MCS はネットワーク ポリシーではサポートされていません。

  • クラスタで HttpLoadBalancing アドオンを有効にする必要があります。HttpLoadBalancing アドオンが有効になっていることを確認します。HttpLoadBalancing アドオンはデフォルトで有効になっています。無効にしないでください。

料金

マルチクラスタ Service は GKE クラスタの管理料金に含まれており、追加料金なしで使用できます。Traffic Director API を有効にする必要がありますが、MCS では Traffic Director エンドポイントの料金は発生しません。MCS の使用に GKE Enterprise ライセンスは必要ありません。

始める前に

作業を始める前に、次のことを確認してください。

  1. Google Cloud SDK をインストールします。

  2. Google Kubernetes Engine API を有効にします。

    Google Kubernetes Engine API の有効化

  3. MCS、フリート(ハブ)、Resource Manager、Traffic Director、Cloud DNS API を有効にします。

    gcloud services enable \
        multiclusterservicediscovery.googleapis.com \
        gkehub.googleapis.com \
        cloudresourcemanager.googleapis.com \
        trafficdirector.googleapis.com \
        dns.googleapis.com \
        --project=PROJECT_ID
    

    PROJECT_ID は、クラスタをフリートに登録する予定のプロジェクトのプロジェクト ID に置き換えます。

プロジェクトで MCS を有効にする

MCS では、参加する GKE クラスタが同じフリートに登録されている必要があります。フリートで MCS 機能が有効になると、すべてのクラスタがフリート内のクラスタ間で Service をエクスポートできます。

MCS ではフリートへの登録が必要ですが、GKE Enterprise プラットフォームを有効にする必要はありません。

GKE Enterprise

他の GKE Enterprise コンポーネントを使用するための前提条件として、フリート ホスト プロジェクトで GKE Enterprise API が有効になっている場合、プロジェクトのフリートに登録されているクラスタは、GKE Enterprise の料金に従って課金されます。この料金モデルでは、登録済みクラスタ上で GKE Enterprise のすべての機能を 1 vCPU あたりの料金で利用できます。GKE Enterprise API が有効になっているかどうかを確認するには、次のコマンドを使用します。

gcloud services list --project=PROJECT_ID | grep anthos.googleapis.com

出力が次のような場合は、完全な GKE Enterprise プラットフォームが有効になっており、フリートに登録されているすべてのクラスタで GKE Enterprise の料金が発生します。

anthos.googleapis.com                        Anthos API

これが想定外である場合は、プロジェクト管理者にお問い合わせください。

空の出力は、GKE Enterprise が有効になっていないことを示します。

GKE クラスタで MCS を有効にする

  1. プロジェクトのフリートで MCS 機能を有効にします。

    gcloud container fleet multi-cluster-services enable \
        --project PROJECT_ID
    

    PROJECT_ID は、クラスタをフリートに登録する予定のプロジェクトのプロジェクト ID に置き換えます。これはフリート ホスト プロジェクトです。

  2. GKE クラスタをフリートに登録しますGKE 用 Workload Identity 連携を有効にしてクラスタを登録することを強くおすすめします。GKE 用 Workload Identity 連携を有効にしない場合は、認証用の Google Cloud サービス アカウントにクラスタを登録し、サービス アカウントの認証の追加手順を完了する必要があります。

    GKE 用 Workload Identity 連携にクラスタを登録するには、次のコマンドを実行します。

    gcloud container fleet memberships register MEMBERSHIP_NAME \
       --gke-cluster CLUSTER_LOCATION/CLUSTER_NAME \
       --enable-workload-identity \
       --project PROJECT_ID
    

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

    • MEMBERSHIP_NAME: フリート内のクラスタを一意に表すように選択したメンバーシップ名。通常、クラスタのフリート メンバーシップ名はクラスタ名ですが、フリート内に元の名前の別のクラスタがすでに存在している場合は、新しい名前を指定する必要があります。
    • CLUSTER_LOCATION: クラスタが配置されているゾーンまたはリージョン。
    • CLUSTER_NAME: クラスタの名前。
  3. MCS インポータを使用するために必要な Identity and Access Management(IAM)権限を付与します。

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

    PROJECT_ID は、フリートホスト プロジェクトのプロジェクト ID に置き換えます。

  4. フリート内の各クラスタに、Service を共有する Namespace があることを確認します。必要に応じて、次のコマンドを使用して Namespace を作成します。

    kubectl create ns NAMESPACE
    

    NAMESPACE は Namespace の名前に置き換えます。

  5. MCS が有効になっていることを確認するには、次のコマンドを実行します。

    gcloud container fleet multi-cluster-services describe \
        --project PROJECT_ID
    

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

    createTime: '2021-08-10T13:05:23.512044937Z'
    membershipStates:
      projects/PROJECT_ID/locations/global/memberships/MCS_NAME:
        state:
          code: OK
          description: Firewall successfully updated
          updateTime: '2021-08-10T13:14:45.173444870Z'
    name: projects/PROJECT_NAME/locations/global/features/multiclusterservicediscovery
    resourceState:
      state: ACTIVE
    spec: {}
    

    state の値が ACTIVE でない場合は、トラブルシューティング セクションをご覧ください。

サービス アカウントの認証

サービス アカウントを使用して GKE クラスタをフリートに登録した場合は、サービス アカウントを認証するための追加手順を行う必要があります。MCS は、gke-mcs-importer というコンポーネントをデプロイします。このコンポーネントは Traffic Director からエンドポイントの更新を受信するため、MCS の有効化の一環として、サービス アカウントに Traffic Director から情報を読み取るための権限を付与する必要があります。

サービス アカウントを使用する場合、Compute Engine のデフォルトのサービス アカウントまたは独自のノード サービス アカウントを使用できます。

MCS の使用

以下のセクションでは、MCS の使用方法を説明します。MCS は Kubernetes マルチクラスタ サービス API を使用します。

エクスポートする Service の登録

エクスポートする Service をフリート内の他のクラスタに登録するには、次の手順を行います。

  1. export.yaml という名前の ServiceExport オブジェクトを作成します。

    # export.yaml
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
     namespace: NAMESPACE
     name: SERVICE_EXPORT_NAME
    

    以下を置き換えます。

    • NAMESPACE: ServiceExport オブジェクトの Namespace。この Namespace は、エクスポートする Service の Namespace と一致する必要があります。
    • SERVICE_EXPORT_NAME: クラスタで、フリート内の他のクラスタにエクスポートする Service の名前。
  2. 次のコマンドを実行して ServiceExport リソースを作成します。

    kubectl apply -f export.yaml
    

Service の最初のエクスポートでは、フリートに登録されているクラスタと同期するまでに約 5 分を要します。Service がエクスポートされると、それに続いてエンドポイントの同期が直ちに行われます。

複数のクラスタから同じ Service をエクスポートして、クラスタ間でトラフィック分配を行う単一の高可用性マルチクラスタ Service エンドポイントを作成できます。同じ名前と Namespace を持つ Service をエクスポートする前に、この方法でグループ化するかを確認してください。defaultkube-system の Namespace に Service をエクスポートすることはおすすめしません。なぜなら、意図しない名前の競合が高確率で発生して、意図しないグループ化が行われるからです。同じ名前と Namespace の 6 つ以上の Service をエクスポートすると、インポートされた Service のトラフィック分配が、5 つのエクスポートされた Service に限定される場合があります。

クラスタ間の Service を使用する

MCS は ClusterSetIP とヘッドレス Service のみをサポートしています。DNS「A」レコードのみを使用できます。

ServiceExport オブジェクトを作成すると、次のドメイン名は、フリート クラスタ内の任意の Pod からエクスポートされた Service に解決されます。

 SERVICE_EXPORT_NAME.NAMESPACE.svc.clusterset.local

出力には次の値が含まれます。

  • SERVICE_EXPORT_NAMENAMESPACE: ServiceExport オブジェクトで定義した値。

ClusterSetIP Service では、ドメインが ClusterSetIP に解決されます。この値は、ServiceExport オブジェクトが作成された Namespace 内のクラスタに含まれる ServiceImport オブジェクトで確認できます。ServiceImport オブジェクトは自動的に作成されます。

次に例を示します。

kind: ServiceImport
apiVersion: net.gke.io/v1
metadata:
 namespace: EXPORTED-SERVICE-NAMESPACE
 name: external-svc-SERVICE-EXPORT-TARGET
status:
 ports:
 - name: https
   port: 443
   protocol: TCP
   targetPort: 443
 ips: CLUSTER_SET_IP

MCS は、クラスタへの Service のインポートの一部として、Endpoints オブジェクトを作成します。このオブジェクトを調べることで、Service のインポートの進行状況をモニタリングできます。Endpoints オブジェクトの名前を調べるには、インポートした Service に対応する ServiceImport オブジェクトでアノテーション net.gke.io/derived-service の値を探します。次に例を示します。

kind: ServiceImport
apiVersion: net.gke.io/v1
annotations: net.gke.io/derived-service: DERIVED_SERVICE_NAME
metadata:
 namespace: EXPORTED-SERVICE-NAMESPACE
 name: external-svc-SERVICE-EXPORT-TARGET

次に、Endpoints オブジェクトを探して、MCS がインポートするクラスタにエンドポイントをすでに伝播しているかどうかを確認します。Endpoints オブジェクトは、ServiceImport オブジェクトと同じ Namespace に、net.gke.io/derived-service アノテーションに格納されている名前で作成されます。次に例を示します。

kubectl get endpoints DERIVED_SERVICE_NAME -n NAMESPACE

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

  • DERIVED_SERVICE_NAME: ServiceImport オブジェクトのアノテーション net.gke.io/derived-service の値。
  • NAMESPACE: ServiceExport オブジェクトの Namespace。

エンドポイントのヘルス ステータスの詳細は、Google Cloud コンソールの Traffic Director ダッシュボードを使用して知ることができます。

ヘッドレス Service の場合、ドメインはエクスポート側クラスタ内のエンドポイントの IP アドレスリストに解決されます。ホスト名を持つ各バックエンド Pod は、次の形式のドメイン名を使用して個別にアドレス指定することもできます。

 HOSTNAME.MEMBERSHIP_NAME.LOCATION.SERVICE_EXPORT_NAME.NAMESPACE.svc.clusterset.local

出力には次の値が含まれます。

  • SERVICE_EXPORT_NAMENAMESPACE: ServiceExport オブジェクトで定義した値。
  • MEMBERSHIP_NAME: Pod が配置されているクラスタのフリート内にある一意の識別子
  • LOCATION: メンバーシップのロケーション。メンバーシップが global であるか、またはそのロケーションが、Pod が配置されているリージョンまたはゾーンのいずれか(us-central1 など)です。
  • HOSTNAME: Pod のホスト名。

次の形式のドメイン名を使用して、グローバル メンバーシップに登録されたクラスタからエクスポートされたホスト名でバックエンド Pod をアドレス指定することもできます。

HOSTNAME.MEMBERSHIP_NAME.SERVICE_EXPORT_NAME.NAMESPACE.svc.clusterset.local

MCS の無効化

MCS を無効にするには、次の手順を行います。

  1. フリート内の各クラスタから、作成した各 ServiceExport オブジェクトを削除します。

    kubectl delete serviceexport SERVICE_EXPORT_NAME \
        -n NAMESPACE
    

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

    • SERVICE_EXPORT_NAME: ServiceExport オブジェクトの名前。
    • NAMESPACE: ServiceExport オブジェクトの Namespace。
  2. 他の目的で登録する必要がない場合は、フリートからクラスタの登録を解除します。

  3. multiclusterservicediscovery 機能を無効にします。

    gcloud container fleet multi-cluster-services disable \
        --project PROJECT_ID
    

    PROJECT_ID は、クラスタを登録したプロジェクトのプロジェクト ID に置き換えます。

  4. MCS の API を無効にします。

    gcloud services disable multiclusterservicediscovery.googleapis.com \
        --project PROJECT_ID
    

    PROJECT_ID は、クラスタを登録したプロジェクトのプロジェクト ID に置き換えます。

制限事項

以下の上限は適用されません。クラスタやプロジェクトの負荷およびエンドポイントのチャーンレートによっては、これらの上限を超える場合もあります。ただし、これらの上限を超えると、パフォーマンスの問題が発生する可能性があります。

  • クラスタのエクスポート: 名前空間名で識別される単一の Service を最大 5 つのクラスタから同時に安全にエクスポートできます。この上限を超えると、使用するクラスタにエンドポイントのサブセットのみがインポートされる可能性があります。クラスタの異なるサブセットから、それぞれ異なる Service をエクスポートできます。

  • 単一の Service の背後の Pod 数: 単一の Service の背後の Pod 数を 250 未満に抑えていれば安全です。これは、単一のクラスタ Service の上限と同じです。比較的静的なワークロードと少数のマルチクラスタ Service では、この数を大幅に上回って Service ごとのエンドポイント数が何千にもなる可能性があります。単一クラスタ Service と同様に、すべてのエンドポイントは各ノードの kube-proxy で監視されます。特に複数のクラスタから同時にエクスポートする場合、この上限を超えると、より大きいノードが必要になる場合があります。

  • 同時にエクスポートするマルチクラスタ Service の数: Service を同時にエクスポートする場合、一意の Service ポートが 50 個を超えないようにすることをおすすめします。一意の Service ポートは Service の名前空間名と宣言されたポートによって識別されます。たとえば、ポート 80 と 443 を公開する Service をエクスポートすると、50 個の一意の Service ポート上限のうちの 2 つとカウントされます。複数のクラスタからエクスポートされた同じ名前空間名の Service は、単一の一意の Service としてカウントされます。前述の 2 ポートのサービスは、5 つのクラスタから同時にエクスポートされた場合のみ、2 つのポートとしてカウントされます。各マルチクラスタ Service はバックエンド サービスの割り当てに計上され、各エクスポート側クラスタまたはゾーンがネットワーク エンドポイント グループ(NEG)を作成します。

  • Service のタイプ: MCS は ClusterSetIP とヘッドレス Service のみをサポートします。NodePort と LoadBalancer Service はサポートされておらず、予期しない動作が発生する可能性があります。

  • MCS での IPmasq エージェントの使用: デフォルトまたはその他のマスカレードされていない Pod IP 範囲を使用すると、MCS は期待どおりに動作します。

    カスタム Pod IP 範囲またはカスタム IPmasq エージェント ConfigMap を使用すると、MCS トラフィックがマスカレードされる可能性があります。ファイアウォール ルールで Pod IP からのトラフィックのみが許可されるため、MCS は機能しません。

    この問題を回避するには、デフォルトの Pod IP 範囲を使用するか、IPmasq エージェント ConfigMapnonMasqueradeCIDRs フィールドにすべての Pod IP 範囲を指定します。Autopilot を使用しているか、デフォルト以外の Pod IP 範囲を使用する必要があるときに、ConfigMap ですべての Pod IP 範囲を指定できない場合は、Egress NAT ポリシーを使用して IP マスカレードを構成する必要があります。

複数のプロジェクトでクラスタを持つ MCS

同じ名前と Namespace のフリート内にある別のプロジェクトで、他のクラスタによってすでにその Service がエクスポートされている場合、その Service のエクスポートはできません。他のプロジェクト内のフリートにある他のクラスタの Service にはアクセスできますが、それらのクラスタが同じ Namespace 内の同じ Service をエクスポートすることはできません。

トラブルシューティング

以降のセクションでは、MCS のトラブルシューティングのヒントを紹介します。

featureState の表示

機能の状態を表示すると、MCS が正常に構成されているかどうかを確認するのに役立ちます。MCS 機能の状態を表示するには、次のコマンドを使用します。

gcloud container fleet multi-cluster-services describe

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

createTime: '2021-08-10T13:05:23.512044937Z'
membershipStates:
 projects/PROJECT_ID/locations/global/memberships/MCS_NAME:
   state:
     code: OK
     description: Firewall successfully updated
     updateTime: '2021-08-10T13:14:45.173444870Z'
name: projects/PROJECT_NAME/locations/global/features/multiclusterservicediscovery
resourceState:
 state: ACTIVE
spec: {}

トラブルシューティングに最も役立つフィールドは codedescription です。

featureState 内のコード

コードは、MCS に関するメンバーの全般的な状態を示します。これらのフィールドは state.code フィールドで確認できます。次の 3 つのコードがあります。

  • OK: メンバーシップは MCS に正常に追加され、使用できる状態です。

  • WARNING: MCS は、メンバーシップ設定の調整中です。説明フィールドで、このコードの原因に関する詳細情報を確認できます。

  • FAILED: このメンバーシップは MCS に追加されませんでした。OK コードを使用したフリート内の他のメンバーは、この FAILED メンバーシップの影響を受けません。説明フィールドで、このコードの原因に関する詳細情報を確認できます。

  • ERROR: このメンバーシップにはリソースがありません。OK コードを使用したフリート内の他のメンバーは、この ERROR メンバーシップの影響を受けません。説明フィールドで、このコードの原因に関する詳細情報を確認できます。

featureState 内の説明

この説明は MCS のメンバーシップの状態に関する詳細情報を提供します。これらの説明は state.description フィールドで確認できます。次の説明が表示されます。

  • Firewall successfully created: このメッセージは、メンバーシップのファイアウォール ルールが正常に作成または更新されたことを示します。メンバーシップのコードは OK です。

  • Firewall creation pending: このメッセージは、メンバーシップのファイアウォール ルールの作成または更新が保留中であることを示します。メンバーシップのコードは WARNING です。このメンバーシップでは、ファイアウォール ルールが保留中の間、新しいマルチクラスタ Service と追加したメンバーシップに対する更新と接続に関する問題が発生する可能性があります。

  • GKE Cluster missing: このメッセージは、登録された GKE クラスタが使用できないか、削除されていることを示します。このメンバーシップのコードは ERROR です。GKE クラスタを削除した後、手動でこのメンバーシップのフリートへの登録を解除する必要があります。

  • Project that member lives in is missing required permissions and/or has not enabled all required APIs - additional setup steps are required: このメッセージは、内部 StatusForbidden(403)エラーが発生したことを示します。メンバーシップのコードは FAILED です。このエラーは、次のような状況で発生します。

    • メンバーのプロジェクトで必要な API が有効にされていない。

      メンバーのクラスタがフリートとは別のプロジェクトに存在する場合は、プロジェクト間の設定を参照して、必要なすべての手順が完了していることを確認してください。すべての手順が完了したら、次のコマンドを使用して、登録プロジェクトで次の API が有効であることを確認します。

      gcloud services enable multiclusterservicediscovery.googleapis.com --project PROJECT_ID
      gcloud services enable dns.googleapis.com --project PROJECT_ID
      gcloud services enable trafficdirector.googleapis.com --project PROJECT_ID
      gcloud services enable cloudresourcemanager.googleapis.com --project PROJECT_ID
      

      PROJECT_ID は、クラスタを登録したプロジェクトのプロジェクト ID に置き換えます。

    • mcsd または gkehub のサービス アカウントには、メンバーのプロジェクトで追加の権限が必要です。

      mcsd および gkehub サービス アカウントはフリートホスト プロジェクト内に自動的に作成され、必要なすべての権限が付与されているはずです。サービス アカウントが存在することを確認するには、次のコマンドを実行します。

      gcloud projects get-iam-policy PROJECT_ID | grep gcp-sa-mcsd
      gcloud projects get-iam-policy PROJECT_ID | grep gcp-sa-gkehub
      

      PROJECT_ID は、フリートホスト プロジェクトのプロジェクト ID に置き換えます。

    これらのコマンドにより、mcsd および gkehub サービス アカウントの完全な名前が表示されます。

  • Multiple VPCs detected in the hub - VPC must be peered with other VPCs for successful connectivity: このメッセージは、複数の異なる VPC でホストされているクラスタが同じフリートに登録されたことを示します。メンバーシップ ステータスは OK です。クラスタの VPC ネットワークは、その NetworkConfig のネットワークにより定義されます。マルチクラスタ Service にはフラット ネットワークが必要であり、マルチクラスタ Service が正常に相互接続するためには、これらの VPC がアクティブにピアリングされる必要があります。詳細については、VPC ネットワーク ピアリングの設定例をご覧ください。

  • Member does not exist in the same project as hub - additional setup steps are required, errors may occur if not completed.: このメッセージは、プロジェクト間クラスタに追加の設定手順が必要であることを示します。メンバーシップ ステータスは OK です。プロジェクト間のメンバーシップが、フリートと同じプロジェクトに存在していない、メンバー クラスタとして定義されています。詳しくは、プロジェクト間の設定をご覧ください。

  • Non-GKE clusters are currently not supported: このメッセージは、MCS では GKE クラスタのみがサポートされることをお知らせするものです。GKE 以外のクラスタを MCS に追加することはできません。メンバーシップ ステータスは FAILED です。

既知の問題

複数のポートを持つ MCS サービス

GKE Dataplane V2 に複数の(TCP/UDP)ポートがあるマルチクラスタ Service には、一部のエンドポイントがデータプレーンでプログラムされないという既知の問題があります。この問題は、1.26.3-gke.400 より前の GKE バージョンに影響します。

回避策として、GKE Dataplane V2 を使用する場合は、複数のポートを持つ 1 つの MCS ではなく、単一のポートを持つ複数の MCS を使用します。

共有 VPC を持つ MCS

MCS の現在の実装では、同じ共有 VPC に複数のフリートをデプロイすると、フリート間でメタデータが共有されます。1 つのフリートで Service が作成されると、同じ共有 VPC に属し、ユーザーに表示される他のすべてのフリートで、Service のメタデータがエクスポートまたはインポートされます。

この動作は、今後の MCS リリースで修正される予定です。

ヘルスチェックで containerPort の代わりに使用されるデフォルト ポート

Deployment の名前付きポートを参照する targetPort フィールドを使用して Service をデプロイすると、MCS は指定された containerPort ではなく、ヘルスチェックのデフォルト ポートを構成します。

この問題を回避するには、名前付きの値ではなく、Service フィールド ports.targetPort と Deployment フィールド readinessProbe.httpGet.port で数値を使用します。

この動作は、今後の MCS リリースで修正される予定です。

次のステップ