混合プロトコル ロードバランサを作成する

このドキュメントでは、TCP トラフィックと UDP トラフィックの両方に混合プロトコルの外部または内部 LoadBalancer Service を使用して、Google Kubernetes Engine(GKE)クラスタで実行されているアプリケーションを公開する方法について説明します。

L4 ロードバランサの詳細については、LoadBalancer Service についてをご覧ください。

概要

TCP プロトコルと UDP プロトコルの両方を使用するアプリケーションは、手動で調整された共有 IP アドレスを使用して、2 つの別々の GKE LoadBalancer Service を使用して公開できます。ただし、このアプローチは非効率的です。単一のアプリケーションに対して複数の Service を管理する必要があり、構成エラーや IP アドレス割り当ての枯渇などの問題が発生する可能性があります。

混合プロトコル LoadBalancer Service を使用すると、単一の Service で TCP と UDP の両方のトラフィックを管理できます。単一の Service を使用すると、両方のプロトコルに単一の IP アドレスと統合された転送ルールを使用できるため、構成が簡素化されます。この機能は、リージョン外部パススルー ネットワーク ロードバランサと内部パススルー ネットワーク ロードバランサの両方でサポートされています。

GKE は、IPv4、IPv6、デュアルスタック構成の混合プロトコル Service をサポートしています。混合プロトコル サービスは、レイヤ 3(L3)転送ルールを使用します。これらのルールは、ロードバランサの仮想 IP(VIP)アドレスに到達したすべてのトラフィックをクラスタノードに直接転送するように設計されています。

セキュリティを維持するため、GKE は、Service マニフェストで定義された特定の TCP トラフィックと UDP トラフィックのみを許可する優先度 999 のファイアウォール ルールを自動的に作成して管理します。ロードバランサの VIP アドレスに転送される他のすべての未承認トラフィックは、優先度 1000 の GKE マネージド ファイアウォール ルールによってブロックされます。優先度の高いファイアウォール ルールを作成する場合は、承認されていないトラフィックが誤ってノードに到達しないようにしてください。詳細については、GKE Service のファイアウォール ルールをご覧ください。

始める前に

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

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API を有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化します。gcloud CLI をインストール済みの場合は、gcloud components update コマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。
  • すでに Autopilot クラスタまたは Standard クラスタが存在していることを確認する。新しいクラスタを作成するには、Autopilot クラスタの作成をご覧ください。

要件

混合プロトコルを使用する LoadBalancer Service を作成するには、クラスタが次の要件を満たしている必要があります。

  • 混合プロトコル ロード バランシングは、GKE バージョン 1.36.2-gke.1498000 以降で一般提供されています。一般提供版は、IPv4、IPv6、デュアルスタック構成の外部ロードバランサと内部ロードバランサの両方をサポートしています。
  • バージョン 1.34.1-gke.2190000 から 1.36.2-gke.1498000 では、混合プロトコル ロード バランシングは IPv4 アドレスを使用する外部ロードバランサでのみサポートされます。
  • クラスタで HttpLoadBalancing アドオンが有効になっている必要があります。
  • 内部ロードバランサの場合、クラスタで GKE サブセット化を有効にする必要があります。
  • 新しい内部 LoadBalancer Service の場合は、Service マニフェストで spec.loadBalancerClass フィールドの値を networking.gke.io/l4-regional-internal に設定します。既存の内部 Service の場合、マニフェストにはすでに networking.gke.io/load-balancer-type: "Internal" アノテーションが含まれているため、アノテーションはそのままにしておくことができます。
  • 新しい外部 LoadBalancer Service の場合は、ロードバランサがバックエンド サービスベースのリージョン外部パススルー ネットワーク ロードバランサであることを確認します。GKE 1.37 以降では、この構成がデフォルトです。以前のバージョンでは、Service マニフェストで spec.loadBalancerClass フィールドを networking.gke.io/l4-regional-external に設定します。既存の外部 Service の場合、マニフェストにはすでに cloud.google.com/l4-rbs: "enabled" アノテーションが含まれているため、アノテーションはそのままにしておきます。

制限事項

  • バージョン 1.34.1-gke.2190000 から 1.36.2-gke.1498000 では、混合プロトコル ロードバランサは IPv4 アドレスのみをサポートします。
  • gke.networking.io/l4-ilb-v1 または gke.networking.io/l4-netlb-v1 ファイナライザーを含む既存の Service は、混合プロトコル ロード バランシングに使用できません。これらのサービスで混合プロトコルを使用する場合は、上記の要件に従ってサービスを削除して再作成する必要があります。
  • Service のポートを更新すると、ロードバランサを介して転送されるすべてのトラフィックが一時的に中断されることがあります。
  • Private Service Connect を混合プロトコル サービスに接続することはできません。

料金

Google Cloud は、転送ルールごと、外部 IP アドレスごと、送信されたデータごとに課金します。次の表に、指定された構成で使用される転送ルールと外部 IP アドレスの数を示します。詳細については、VPC ネットワークの料金をご覧ください。

タイプ トランスポート層 インターネット層 転送ルールの数 外部 IP アドレスの数
内部 単一または混合(TCP、UDP、または両方) IPv4 1 0
IPv6 1 0
IPv4 と IPv6(DualStack) 2 0
外部 単一または混合(TCP、UDP、または両方) IPv4 1 1
IPv6 1 1
IPv4 と IPv6(DualStack) 2 2

ワークロードをデプロイする

このセクションでは、TCP ポートと UDP ポートの両方でリッスンするサンプル ワークロードをデプロイする方法について説明します。混合プロトコル LoadBalancer Service を使用しているか、2 つの個別の単一プロトコル LoadBalancer Service を使用しているかに関係なく、Deployment 構成は同じです。

  1. 次のマニフェストは、TCP と UDP の両方のトラフィックをポート 8080 でリッスンするサンプル アプリケーション用です。次のマニフェストを mixed-app-deployment.yaml として保存します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: mixed-app-deployment
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: mixed-app
      template:
        metadata:
          labels:
            app: mixed-app
        spec:
          containers:
          - image: gcr.io/kubernetes-e2e-test-images/agnhost:2.6
            name: agnhost
            args: ["serve-hostname", "--port=8080", "--tcp=true", "--udp=true", "--http=false"]
            ports:
              - name: tcp8080
                protocol: TCP
                containerPort: 8080
              - name: udp8080
                protocol: UDP
                containerPort: 8080
    
  2. マニフェストをクラスタに適用します。

    kubectl apply -f mixed-app-deployment.yaml
    

混合プロトコル ロードバランサを作成する

Deployment を TCP トラフィックと UDP トラフィックの両方に公開する LoadBalancer タイプの Service を作成します。外部ロードバランサまたは内部ロードバランサのいずれかを作成できます。

  1. 外部ロードバランサを作成するには、次のマニフェストを mixed-protocol-lb.yaml として保存します。

    apiVersion: v1
    kind: Service
    metadata:
      name: mixed-protocol-external-lb
    spec:
      loadBalancerClass: "networking.gke.io/l4-regional-external"
      type: LoadBalancer
      selector:
        app: mixed-app
      ports:
      - name: tcp-port
        protocol: TCP
        port: 8080
      - name: udp-port
        protocol: UDP
        port: 8080
    

    内部ロードバランサを作成するには、spec.loadBalancerClass フィールドの値を networking.gke.io/l4-regional-internal に設定します。

    上記の Service には、TCP 用と UDP 用の 2 つのポートがあり、どちらもポート 8080 にあります。

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

    kubectl apply --server-side -f mixed-protocol-lb.yaml
    

混合プロトコル ロードバランサを確認する

Service を作成したら、GKE がロードバランサを正常に作成したことを確認します。

  1. サービスの検査:

    kubectl describe service SERVICE_NAME
    

    SERVICE_NAME は、Service の名前に置き換えます(mixed-protocol-lb など)。

    出力には、ロードバランサの IP アドレスと転送ルールが表示されます。出力で次の詳細を確認します。

    • status.loadBalancer.ingress.ip フィールドが入力されます。
    • バージョン 1.34.1-gke.2190000 から 1.36.2-gke.1498000 のクラスタでは、外部ロードバランサに次のアノテーションが存在することを確認します。
      • service.kubernetes.io/tcp-forwarding-rule
      • service.kubernetes.io/udp-forwarding-rule
    • 1.36.2-gke.1498000 以降のバージョンで作成されたクラスタの場合は、構成に応じて、ロードバランサに次のアノテーションが存在することを確認します。
      • IPv4 の場合: service.kubernetes.io/l3-forwarding-rule
      • IPv6 の場合: service.kubernetes.io/l3-forwarding-rule-ipv6
      • デュアルスタックの場合: 両方のアノテーション。
    • Events セクションにエラー メッセージが含まれていない。

混合プロトコル ロードバランサを更新する

Service マニフェストを編集することで、混合プロトコル ロードバランサのポートを更新できます。Service を編集するには、次のコマンドを実行します。

kubectl edit service SERVICE_NAME

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

ポートを更新する

混合プロトコル ロードバランサのポートを更新するには、Service マニフェストの ports セクションを変更します。ポートの追加、削除、変更が可能です。

次の例では、ストリーミング用の UDP ポートとゲームサーバー メタデータ用の TCP ポートを追加します。

apiVersion: v1
kind: Service
metadata:
  name: mixed-protocol-lb
spec:
  loadBalancerClass: "networking.gke.io/l4-regional-external"  # for internal LB, use: "networking.gke.io/l4-regional-internal"
  type: LoadBalancer
  selector:
    app: mixed-app
  ports:
  - name: tcp-port
    protocol: TCP
    port: 8080
  - name: streaming
    protocol: UDP
    port: 10100
  - name: gameserver-metadata
    protocol: TCP
    port: 10400
  - name: https
    protocol: TCP
    port: 443

単一プロトコル ロードバランサを混合プロトコルに更新する

単一プロトコル ロードバランサを混合プロトコル ロードバランサに変更するには、TCP プロトコルと UDP プロトコルの両方のポートを含むように Service を編集します。

次の例では、DNS の UDP ポートを既存の TCP 専用ロードバランサに追加します。

apiVersion: v1
kind: Service
metadata:
  name: already-existing-single-protocol-lb
spec:
  loadBalancerClass: "networking.gke.io/l4-regional-external" # for internal LB, use: "networking.gke.io/l4-regional-internal"
  type: LoadBalancer
  selector:
    app: mixed-app
  ports:
  - name: http
    protocol: TCP
    port: 80
  - name: https
    protocol: TCP
    port: 443
  - name: dns
    protocol: UDP
    port: 53

混合プロトコル ロードバランサを単一プロトコルに更新する

混合プロトコル ロードバランサを単一プロトコル ロードバランサに変更するには、いずれかのプロトコルのすべてのポートを削除します。

次の例では、DNS の UDP ポートを削除し、ロードバランサを TCP 専用に変換します。

apiVersion: v1
kind: Service
metadata:
  name: already-existing-mixed-protocol-lb
spec:
  loadBalancerClass: "networking.gke.io/l4-regional-external" # for internal LB, use: "networking.gke.io/l4-regional-internal"
  type: LoadBalancer
  selector:
    app: mixed-app
  ports:
  - name: http
    protocol: TCP
    port: 80
  - name: https
    protocol: TCP
    port: 443

混合プロトコル LoadBalancer を削除する

混合プロトコル LoadBalancer Service を削除するには、次のコマンドを実行します。

kubectl delete service SERVICE_NAME

SERVICE_NAME は、Service の名前に置き換えます(mixed-protocol-external-lb など)。

GKE は、Service 用に作成されたすべてのロードバランサ リソースを自動的に削除します。

トラブルシューティング

このセクションでは、混合プロトコル LoadBalancer Service に関する一般的な問題を解決する方法について説明します。

エラーイベントを確認する

トラブルシューティングの最初の手順は、サービスに関連付けられているイベントを確認することです。

  1. Service の詳細を取得します。

    kubectl describe service SERVICE_NAME
    

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

  2. 出力の最後にある Events セクションでエラー メッセージを確認します。

エラー: LoadBalancer で混合プロトコルはサポートされていません

cloud.google.com/l4-rbs: "enabled" アノテーションを使用して Service を作成した場合、混合プロトコル ロードバランサの作成後に、元のサービス コントローラから mixed-protocol is not supported for LoadBalancer という警告イベントが表示されることがあります。

新しいコントローラは混合プロトコルをサポートし、ロードバランサを正しくプロビジョニングするため、このメッセージは無視してかまいません。

更新後にポート定義が欠落している

症状:

TCP と UDP の両方に同じポート(ポート 8080 など)を使用する Service を更新すると、更新された Service からポート定義の 1 つが欠落します。

原因:

これは Kubernetes の既知の問題です。同じポートで複数のプロトコルを使用して Service を更新すると、クライアントサイドのパッチ計算でポートリストが誤って統合され、ポート定義の 1 つが削除されることがあります。この問題は、kubectl apply やマージ パッチを含む Go クライアントなど、クライアントサイド パッチ適用を使用するクライアントに影響します。

ソリューション:

この問題の回避策は、クライアントによって異なります。

  • kubectl の場合: kubectl apply で --server-side フラグを使用します。

    kubectl apply --server-side -f YOUR_SERVICE_MANIFEST.yaml
    

    YOUR_SERVICE_MANIFEST は、Service マニフェストの名前に置き換えます。

  • go-client の場合: マージ パッチを使用しないでください。代わりに、更新呼び出しを使用して Service を置き換えます。これには、Service オブジェクトの仕様全体を含む HTTP PUT リクエストが必要です。

次のステップ