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

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

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

概要

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

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

GKE は、IPv4、IPv6、デュアルスタック構成の混合プロトコル Service をサポートしています。混合プロトコル 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 の場合は、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 で混合プロトコルを使用する場合は、上記の要件に従って Service を削除して再作成する必要があります。
  • Service のポートを更新すると、ロードバランサ経由でルーティングされるすべてのトラフィックが一時的に中断される可能性があります。
  • Private Service Connect を混合プロトコル Service に接続することはできません。

料金

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

タイプ トランスポート層 インターネット層 転送ルールの数 外部 IP アドレスの数
内部 単一または混合(TCP、UDP、またはその両方) IPv4 1 0
IPv6 1 0
IPv4 と IPv6(デュアルスタック) 2 0
外部 単一または混合(TCP、UDP、またはその両方) IPv4 1 1
IPv6 1 1
IPv4 と IPv6(デュアルスタック) 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[section] にエラー メッセージが表示されない。

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

混合プロトコル ロードバランサのポートは、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 の一般的な問題を解決する方法について説明します。

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

トラブルシューティングの最初のステップは、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 の場合: --server-side フラグを kubectl apply で使用します。

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

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

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

次のステップ