VPC ネットワーク間に内部ロードバランサを作成する

このページでは、VPC ネットワーク間に Google Kubernetes Engine(GKE)で内部パススルー ネットワーク ロードバランサを作成する方法について説明します。

このページを読む前に、次の内容をよく理解しておいてください。

始める前に

作業を始める前に、次のタスクが完了していることを確認してください。

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update コマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。

Private Service Connect を使用して内部ロードバランサを作成する

サービス プロデューサーとしてサービス アタッチメントを使用すると、Private Service Connect を使用して、他の VPC ネットワークのサービス コンシューマーがサービスを利用できるようになります。ServiceAttachment カスタム リソースを使用して、サービス アタッチメントを作成、管理、削除できます。

要件と制限事項

  • Private Service Connect の制限事項が適用されます。
  • サービス アタッチメントは、GKE バージョン 1.21.4-gke.300 以降で作成できます。
  • クラスタで HttpLoadBalancing アドオンが有効になっている必要があります。新しい GKE クラスタでは、HttpLoadBalancing アドオンがデフォルトで有効になっています。
  • 複数サービスのアタッチメント構成で同じサブネットを使用することができない。
  • 内部パススルー ネットワーク ロードバランサを使用する GKE サービスを作成する必要があります。
  • 1.22.4-gke.100 より前のバージョンの GKE では、別のプロジェクト(共有 VPC)のサブネットを指定することはできません。共有 VPC の場合は、共有 VPC の要件がすべて満たされていることを確認してください。
  • サービス アタッチメントを作成した後、内部ロードバランサを更新することはできません。ロードバランサの構成を変更するには、サービス アタッチメントを削除して再作成する必要があります。

ServiceAttachment を作成する

  1. サブネットを作成します。

    ServiceAttachment ごとに新しいサブネットを作成する必要があります。

    gcloud beta compute networks subnets create SUBNET_NAME \
        --project PROJECT_ID \
        --network NETWORK_NAME \
        --region REGION \
        --range SUBNET_RANGE \
        --purpose PRIVATE_SERVICE_CONNECT
    

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

    • SUBNET_NAME: 新しいサブネットの名前。1.22.4-gke.100 以降のバージョンの GKE では、このフィールドに完全修飾リソース URL を使用することで、別のプロジェクトのサブネットを指定できます。完全修飾されたリソース URL は、コマンド gcloud compute networks subnets describe を使用して取得できます。
    • PROJECT_ID: 実際の Google Cloudプロジェクトの ID。
    • NETWORK_NAME: サブネットの VPC ネットワークの名前。
    • REGION: 新しいサブネットのリージョン。作成するサービスと同じリージョンを使用する必要があります。
    • SUBNET_RANGE: サブネットに使用する IP アドレス範囲。
  2. ワークロードをデプロイします。

    以下のマニフェストは、サンプルのウェブ アプリケーション コンテナ イメージを実行する Deployment を記述しています。マニフェストを my-deployment.yaml として保存します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: psc-ilb
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: psc-ilb
      template:
        metadata:
          labels:
            app: psc-ilb
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1
            ports:
              - name: http
                containerPort: 8080
            readinessProbe:
              httpGet:
                path: /healthz
                port: 8080
                scheme: HTTP
              initialDelaySeconds: 5
              timeoutSeconds: 1
    
  3. マニフェストをクラスタに適用します。

    kubectl apply -f my-deployment.yaml
    
  4. サービスを作成します。次のマニフェストは、TCP ポート 8080 に内部パススルー ネットワーク ロードバランサを作成するサービスを示しています。マニフェストを my-service.yaml として保存します。

     apiVersion: v1
     kind: Service
     metadata:
       name: SERVICE_NAME
       annotations:
         networking.gke.io/load-balancer-type: "Internal"
     spec:
       type: LoadBalancer
       selector:
         app: psc-ilb
       ports:
       - port: 80
         targetPort: 8080
         protocol: TCP
    

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

    • SERVICE_NAME: 新しいサービスの名前。
  5. マニフェストをクラスタに適用します。

    kubectl apply -f my-service.yaml
    
  6. ServiceAttachment を作成します。

    次のマニフェストでは、作成したサービスをサービス コンシューマに提供する ServiceAttachment を記述しています。マニフェストを my-psc.yaml として保存します。

    apiVersion: networking.gke.io/v1
    kind: ServiceAttachment
    metadata:
     name: SERVICE_ATTACHMENT_NAME
     namespace: default
    spec:
     connectionPreference: ACCEPT_AUTOMATIC
     natSubnets:
     - SUBNET_NAME
     proxyProtocol: false
     resourceRef:
       kind: Service
       name: SERVICE_NAME
    

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

    • SERVICE_ATTACHMENT_NAME: 新しいサービス アタッチメントの名前。
    • SUBNET_NAME: 新しいサブネットの名前。1.22.4-gke.100 以降のバージョンの GKE では、このフィールドに完全修飾リソース URL を使用することで、別のプロジェクトのサブネットを指定できます。完全修飾されたリソース URL は、コマンド gcloud compute networks subnets describe を使用して取得できます。共有 VPC 構成の場合は、projects/HOST_PROJECT_ID/regions/COMPUTE_REGION/subnetworks/SUBNET_NAME の形式を使用します。

    マニフェスト フィールドの詳細については、サービス アタッチメントのフィールドをご覧ください。

  7. マニフェストをクラスタに適用します。

    kubectl apply -f my-psc.yaml
    
  8. Private Service Connect コントローラがサービス アタッチメントを作成したことを確認します。

    gcloud beta compute service-attachments list
    

    出力には、自動生成された名前のサービス アタッチメントが表示されます。

    NAME        REGION       PRODUCER_FORWARDING_RULE          CONNECTION_PREFERENCE
    k8s1-sa-... REGION_NAME  a3fea439c870148bdba5e59c9ea9451a  ACCEPT_AUTOMATIC
    

ServiceAttachment を確認する

ServiceAttachment の詳細を表示するには、次のコマンドを使用します。

kubectl describe serviceattachment SERVICE_ATTACHMENT_NAME

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

Name:        <sa-name>
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  networking.gke.io/v1beta1
Kind:         ServiceAttachment
Metadata:
  ...
Status:
  Forwarding Rule URL:      https://www.googleapis.com/compute/beta/projects/<project>/regions/<region>/forwardingRules/<fr-name>
  Last Modified Timestamp:  2021-07-08T01:32:39Z
  Service Attachment URL:   https://www.googleapis.com/compute/beta/projects/<projects>/regions/<region>/serviceAttachments/<gce-service-attachment-name>
Events:                     <none>

ServiceAttachment を使用する

別のプロジェクトのサービスを使用するには、次の手順を行います。

  1. ServiceAttachment の URL を取得します。

    kubectl get serviceattachment SERVICE_ATTACHMENT_NAME -o=jsonpath="{.status.serviceAttachmentURL}"
    

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

      serviceAttachmentURL: https://www.googleapis.com/compute/alpha/projects/<project>/region/<region>/serviceAttachments/k8s1-...my-sa
    
  2. ServiceAttachment の URL を使用して、Private Service Connect エンドポイントを作成します。

  3. コンシューマ プロジェクトの VM から curl コマンドを使用して、プロデューサー プロジェクトでデプロイした Service に接続できることを確認します。

    curl PSC_IP_ADDRESS
    

    PSC_IP_ADDRESS は、コンシューマ プロジェクトの転送ルールの IP アドレスに置き換えます。

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

    {
      "cluster_name":"cluster",
      "host_header":"10.128.15.200",
      "node_name":"gke-psc-default-pool-be9b6e0e-dvxg.c.gke_project.internal",
      "pod_name":"foo-7bf648dcfd-l5jf8",
      "pod_name_emoji":"👚",
      "project_id":"gke_project",
      "timestamp":"2021-06-29T21:32:03",
      "zone":"ZONE_NAME"
    }
    

ServiceAttachment の更新

ServiceAttachment を更新するには、次の手順を行います。

  1. my-psc.yamlServiceAttachment マニフェストを編集します。

    apiVersion: networking.gke.io/v1
    kind: ServiceAttachment
    metadata:
      name: my-sa
      namespace: default
    spec:
      connectionPreference: ACCEPT_AUTOMATIC
      natSubnets:
      - my-nat-subnet
      proxyProtocol: false
      resourceRef:
        kind: Service
        name: ilb-service
    
  2. マニフェストをクラスタに適用します。

    kubectl apply -f my-psc.yaml
    

ServiceAttachment の削除

サービス アタッチメントに接続されている内部パススルー ネットワーク ロードバランサは削除できません。サービス アタッチメントと GKE Service は個別に削除する必要があります。

  1. サービス アタッチメントを削除します。

    kubectl delete serviceattachment SERVICE_ATTACHMENT_NAME --wait=false
    

    このコマンドは、サービス アタッチメントに削除マークを付けますが、リソースは引き続き存在します。--wait フラグを省略して、削除の完了を待つこともできます。

  2. サービスを削除します。

    kubectl delete svc SERVICE_NAME
    
  3. サブネットを削除します。

    gcloud compute networks subnets delete SUBNET_NAME
    

ServiceAttachment フィールド

ServiceAttachment には次のフィールドがあります。

  • connectionPreference: コンシューマがサービスに接続する方法を決定する接続設定。ACCEPT_AUTOMATIC を使用してプロジェクトの自動承認を使用するか、ACCEPT_MANUAL を使用してプロジェクトを明示的に承認できます。詳細については、Private Service Connect を使用してサービスを公開するをご覧ください。
  • natSubnets: サービス アタッチメントに使用するサブネットワーク リソース名のリスト。
  • proxyProtocol: true に設定すると、リクエスト内でコンシューマ ソース IP と Private Service Connect の接続 ID を使用できるようになります。このフィールドは省略可能で、指定しない場合はデフォルトの false になります。
  • consumerAllowList: ServiceAttachment への接続が許可されているコンシューマ プロジェクトのリスト。このフィールドは、connectionPreferenceACCEPT_MANUAL の場合にのみ使用できます。このフィールドの詳細については、Private Service Connect を使用してサービスを公開するをご覧ください。
    • project: コンシューマ プロジェクトのプロジェクト ID または番号。
    • connectionLimit: コンシューマ プロジェクトの接続の上限。このフィールドは省略可能です。
    • forceSendFields: API リクエストに含めるフィールド名。このフィールドは省略可能です。
    • nullFields: API リクエストに null 値で含めるフィールド名。このフィールドは省略可能です。
  • consumerRejectList: コンシューマ プロジェクトの ID または番号のリスト。ServiceAttachment への接続は許可されません。このフィールドは、connectionPreferenceACCEPT_MANUAL の場合にのみ使用できます。このフィールドの詳細については、Private Service Connect を使用してサービスを公開するをご覧ください。
  • resourceRef: Kubernetes リソースへの参照。

    • kind: Kubernetes リソースのタイプ。Service を使用する必要があります。
    • name: 内部パススルー ネットワーク ロードバランサと同じ名前空間に存在する必要がある Kubernetes リソースの名前。

トラブルシューティング

次のコマンドを使用すると、エラー メッセージを表示できます。

kubectl get events -n NAMESPACE

NAMESPACE は、内部パススルー ネットワーク ロードバランサの Namespace に置き換えます。

内部パススルー ネットワーク ロードバランサの削除エラー

サービス アタッチメントで使用されている内部パススルー ネットワーク ロードバランサを削除しようとすると、次のようなエラー メッセージが表示されます。内部パススルー ネットワーク ロードバランサを削除するには、まず ServiceAttachment を削除する必要があります。

Error syncing load balancer: failed to ensure load balancer: googleapi:
Error 400: The forwarding_rule resource '<fwd-rule-URL>' is already being used
by '<svc-attachment-URL>', resourceInUseByAnotherResource.

グローバル アクセスの有効化中にエラーが発生しました

Private Service Connect サービス アタッチメントを使用する内部パススルー ネットワーク ロードバランサでグローバル アクセスを有効にすると、エラーが発生することがあります。

症状:

GKE Service マニフェストを更新して networking.gke.io/internal-load-balancer-allow-global-access: "true" アノテーションを設定し、グローバル アクセスを有効にすると、マニフェストの適用時に更新が失敗します。kubectl get events コマンドを実行すると、次のエラー メッセージが表示されます。

Error syncing load balancer: failed to ensure load balancer: googleapi: Error 400: The forwarding_rule resource '...' is already being used by '...', resourceInUseByAnotherResource

Reason:

このエラーは、GKE コントロール プレーンがグローバル アクセスを有効にするためにロードバランサの転送ルールの再作成を試行するために発生します。ただし、転送ルールは ServiceAttachment で使用されているため、ルールを削除して再作成することはできません。そのため、エラーが発生します。

回避策:

ダウンタイムを最小限に抑えながらロードバランサでグローバル アクセスを有効にするには、GKE Service 構成を更新し、転送ルールを手動で更新する必要があります。

  1. GKE Service マニフェストを更新する: networking.gke.io/internal-load-balancer-allow-global-access: "true" アノテーションを含めるように GKE Service マニフェストを更新します。

  2. 転送ルールでグローバル アクセスを手動で有効にする: グローバル アクセスを有効にするの手順に沿って、Google Cloud コンソール、Google Cloud CLI、または Compute Engine API のいずれかを使用して、ロードバランサの転送ルールを更新します。

次のステップ