マルチネットワーク LoadBalancer Service をデプロイする

このドキュメントでは、GKE で Google Cloud 外部パススルー ネットワーク ロードバランサと内部パススルー ネットワーク ロードバランサのリソースを作成して、マルチネットワーク Pod を内部クライアントまたは外部クライアントに公開する方法について説明します。マルチネットワーク LoadBalancer サービスに必要な構成、機能、制限について説明します。

ワークロードを複数の VPC ネットワークに接続する場合は、タイプ LoadBalancer の Kubernetes Service を使用して、特定のセカンダリ ネットワーク上の Pod にトラフィックを転送します。Service を作成すると、GKE はこのトラフィックを管理するパススルー ネットワーク ロードバランサを作成します。

GKE のマルチネットワーキングの詳細については、Pod のマルチネットワーク サポートについてをご覧ください。

マルチネットワーク LoadBalancer Service の仕組み

マルチネットワーク ワークロードを公開するには、type: LoadBalancerService を作成します。Service には、セカンダリ インターフェースのネットワークに基づいて Pod をターゲットとする特別なセレクタを含める必要があります。内部ロードバランサと外部ロードバランサのどちらを作成するかを指定するアノテーションを追加します。

セレクタの networking.gke.io/network ラベルは、ネットワークでエンドポイントをフィルタします。このラベルにより、ロードバランサは指定されたネットワークに接続された Pod インターフェースにのみトラフィックを送信します。

制限事項

マルチネットワーク ロードバランサには次の制限があります。

  • externalTrafficPolicy: Cluster を使用するサービスはサポートされていません。
  • hostNetwork Pod をターゲットとするサービスはサポートされていません。
  • IPv6 とデュアルスタック ネットワーキングはサポートされていません。
  • 既存の Service のネットワークは変更できません。
  • レイヤ 3 ネットワークのみがサポートされます。
  • ターゲット プールまたはインスタンス グループのバックエンドに基づくロードバランサはサポートされていません。
  • ClusterIP Service と NodePort Service は、セカンダリ(デフォルト以外)ネットワークではサポートされていません。

始める前に

始める前に、次のタスクを完了します。

  1. Pod のマルチネットワーク サポートを設定するの手順に沿って、VPC ネットワークを準備し、追加のネットワークを使用して GKE クラスタを作成します。
  2. クラスタでレイヤ 4 内部ロードバランサのサブセット化が有効になっていることを確認します。この機能を有効にするには、クラスタの作成または更新時に --enable-l4-ilb-subsetting フラグを使用します。
  3. クラスタで GKE バージョン 1.37 以降が実行されていることを確認します。

マルチネットワーク Pod をデプロイする

Pod を追加のネットワークに接続するには、networking.gke.io/interfaces アノテーションを使用して Deployment を作成します。このアノテーションは、Pod のネットワークとインターフェースを指定します。

  1. 次のマニフェストを web-app-deployment.yaml として保存します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-app
      labels:
        app: web-app
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: web-app
      template:
        metadata:
          labels:
            app: web-app
          annotations:
            networking.gke.io/default-interface: 'eth1'
            networking.gke.io/interfaces: '[
              {"interfaceName":"eth0","network":"default"},
              {"interfaceName": "eth1","network": "dmz"}
            ]'
    spec:
      containers:
      - name: whereami
        image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1
        ports:
        - containerPort: 8080
    

    このマニフェストは、3 つの Pod を持つ web-app という名前の Deployment を作成します。Pod には、default ネットワークに接続された eth0dmz ネットワークに接続された eth1 の 2 つのインターフェースがあります。networking.gke.io/default-interface アノテーションは、Pod のデフォルト インターフェースとして eth1 を設定します。

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

    kubectl apply -f web-app-deployment.yaml
    

Service にデフォルト以外のインターフェースを使用する場合は、Pod 内でルーティングを構成する必要があります。ルーティングを構成するには、NET_ADMIN 機能を持つ initContainer を Pod 仕様に追加します。

次の例は、eth1 インターフェースのデフォルト ルートを追加する initContainer を示しています。

initContainers:
      - name: init-routes-busybox
        image: busybox
        command: ['sh', '-c', 'ip route add default dev eth1 table 200 && ip rule add from 172.16.1.0/24 table 200']
        securityContext:
          capabilities:
            add: ["NET_ADMIN"]

initContainer コマンドで、172.16.1.0/24 を Pod ネットワークのセカンダリ IP アドレス範囲に置き換えます。

内部 LoadBalancer Service をデプロイする

dmz ネットワークで web-app Deployment を公開するには、内部 LoadBalancer Service を作成します。

  1. 次のマニフェストを internal-lb-service.yaml として保存します。

    apiVersion: v1
    kind: Service
    metadata:
      name: web-app-internal-lb
      namespace: default
      annotations:
        networking.gke.io/load-balancer-type: "Internal"
    spec:
      externalTrafficPolicy: Local
      ports:
      -   port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        networking.gke.io/network: dmz
        app: web-app
      type: LoadBalancer
    

    このマニフェストは、次のプロパティを持つ Service を作成します。

    • networking.gke.io/load-balancer-type: "Internal": 内部パススルー ネットワーク ロードバランサを指定します。
    • selector: dmz ネットワークに接続されている app: web-app ラベルを持つ Pod を選択します。
  2. マニフェストをクラスタに適用します。

    kubectl apply -f internal-lb-service.yaml
    

外部 LoadBalancer Service をデプロイする

web-app Deployment を外部クライアントに公開するには、外部 LoadBalancer Service を作成します。

  1. 次のマニフェストを external-lb-service.yaml として保存します。

    apiVersion: v1
    kind: Service
    metadata:
      name: web-app-external-lb
      namespace: default
      annotations:
        cloud.google.com/l4-rbs: "enabled"
    spec:
      externalTrafficPolicy: Local
      ports:
      -   port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        networking.gke.io/network: dmz
        app: web-app
      type: LoadBalancer
    

    このマニフェストは、次のプロパティを持つ Service を作成します。

    • cloud.google.com/l4-rbs: "enabled": バックエンド サービスベースの外部パススルー ネットワーク ロードバランサを指定します。
    • selector: dmz ネットワークに接続されているラベル app: web-app を持つ Pod を選択します。
  2. マニフェストをクラスタに適用します。

    kubectl apply -f external-lb-service.yaml
    

サービスを確認する

Service をデプロイしたら、ロードバランサが作成され、正しく構成されていることを確認します。

  1. サービスのステータスを確認します。

    kubectl get services
    

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

    NAME                  TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
    web-app-external-lb   LoadBalancer   10.8.47.77    35.239.57.231   80:31550/TCP   5m
    web-app-internal-lb   LoadBalancer   10.8.43.251   172.16.0.43     80:32628/TCP   6m
    kubernetes            ClusterIP      10.8.32.1     <none>          443/TCP        43h
    

    内部ロードバランサの EXTERNAL-IP アドレスは dmz ネットワークに属しています。

  2. プロジェクト内の転送ルールを一覧表示します。

    gcloud compute forwarding-rules list
    

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

    NAME                                                   REGION        IP_ADDRESS     IP_PROTOCOL  TARGET
    af901673cc0f24907a6aa8c3ce4afc21                       us-central1   35.239.57.231  TCP          us-central1/backendServices/k8s2-xhvzqabw-default-web-app-external-lb-u4xbs4ot
    k8s2-tcp-xhvzqabw-default-web-app-internal-lb-vp1x1d6a us-central1   172.16.0.43    TCP          us-central1/backendServices/k8s2-xhvzqabw-default-web-app-internal-lb-vp1x1d6a
    
  3. 内部ロードバランサの転送ルールを説明して、正しいネットワークに接続されていることを確認します。

    gcloud compute forwarding-rules describe k8s2-tcp-xhvzqabw-default-web-app-internal-lb-vp1x1d6a --region=$REGION
    

    REGION は、クラスタのリージョンに置き換えます。

    出力は次のようになります。network フィールドと subnetwork フィールドが dmz ネットワークの詳細と一致していることを確認します。

    IPAddress: 172.16.0.43
    IPProtocol: TCP
    ...
    loadBalancingScheme: INTERNAL
    name: k8s2-tcp-xhvzqabw-default-web-app-internal-lb-vp1x1d6a
    network: https://www.googleapis.com/compute/v1/projects/projectId/global/networks/dmz-vpc
    ...
    subnetwork: https://www.googleapis.com/compute/v1/projects/projectId/regions/us-central1/subnetworks/dmz-subnet
    

ロードバランサをテストする

  1. 外部ロードバランサをテストするには、その外部 IP アドレスにリクエストを送信します。

    curl EXTERNAL_LB_IP:80
    

    EXTERNAL_LB_IP は、web-app-external-lb Service の外部 IP アドレスに置き換えます。

  2. 内部ロードバランサをテストするには、ロードバランサと同じ VPC 内のホストからリクエストを送信します。

    curl INTERNAL_LB_IP:80
    

    INTERNAL_LB_IP は、web-app-internal-lb Service の IP アドレスに置き換えます。

トラブルシューティング

このセクションでは、マルチネットワーク ロードバランサに関する問題のトラブルシューティング方法について説明します。

ロードバランサの作成が失敗する

ロードバランサの作成に失敗した場合は、Service イベントでエラー メッセージを確認します。

kubectl describe service SERVICE_NAME

SERVICE_NAME は、実際の Service 名に置き換えます。

network some-other-network does not exist などのエラー メッセージは、Service セレクタで指定されたネットワークがクラスタで定義されていないことを示します。ネットワークが存在することを確認します。

kubectl get networks

ネットワークが存在する場合は、Network オブジェクトが有効な GKENetworkParamSet リソースを正しく参照していることを確認します。構成エラーを確認するには、Network リソースのステータスを調べます。

kubectl get networks NETWORK_NAME -o yaml

NETWORK_NAME はネットワーク名に置き換えてください。

有効な構成では、ParamsReady 条件と Ready 条件の両方が True です。ParamsReadyTrue でない場合は、Network 仕様の parametersRef が既存の GKENetworkParamSet リソースの名前、種類、グループと正しく一致していることを確認します。

Network リソースが正しいのに準備ができていない場合は、参照先の GKENetworkParamSet のステータスを調べて、サブネットの欠落などのエラーがないか確認します。

kubectl get gkenetworkparamsets GNP_NAME -o yaml

GNP_NAME は、GKENetworkParamSet の名前で置き換えます。

ロードバランサにバックエンドがない

ロードバランサがプロビジョニングされているが、正常なバックエンドがない場合は、次の操作を行います。

  1. Service が使用するネットワークにネットワーク インターフェースを持つノードプールが存在することを確認します。
  2. Service によって選択された Pod が実行されていることを確認します。
  3. Service のエンドポイントを確認します。

    kubectl describe endpointslice -l kubernetes.io/service-name=SERVICE_NAME
    

    multinet-endpointslice-controller.gke.io コントローラは、マルチネットワーク エンドポイントを作成します。EndpointSlice にリストされている Pod の IP アドレスは、Service が使用するネットワークに属しています。EndpointSlice にエンドポイントがない場合は、Service セレクタのラベルが実行中の Pod と一致し、ネットワーク セレクタが Pod のネットワークと一致していることを確認します。

次のステップ