MetalLB を使用してバンドルされたロード バランシングを構成する

このページでは、GDCV for Bare Metal の MetalLB を使用してバンドルされたロード バランシングを構成する方法について説明します。MetalLB ロードバランサは、ワーカーノードの専用プールまたはコントロール プレーンと同じノードで実行されます。

GDCV for Bare Metal で使用可能なロード バランシング トポロジの例については、ロードバランサの概要をご覧ください。

要件

  • すべてのロードバランサ ノードは、同じレイヤ 2 サブネット内にある必要があります。
  • すべての VIP は、ロードバランサのノードのサブネット内に存在し、サブネットのゲートウェイからルーティング可能である必要があります。
  • ロードバランサのサブネットのゲートウェイは、Gratuitous ARP メッセージをリッスンし、ロードバランサ ノードに ARP パケットを転送するできる必要があります。

設定に関する項目

クラスタ構成ファイルの cluster.spec.loadBalancer セクションを編集して、バンドル型ロード バランシングを構成します。クラスタ構成ファイルと有効な構成の例に関する情報は、次のいずれかのページをご覧ください。

loadBalancer.mode

バンドル型ロード バランシングを有効にするには、この値を bundled にする必要があります。

loadBalancer.ports.controlPlaneLBPort

この値は、Kubernetes コントロール プレーン(Kubernetes API サーバー)に送信されるトラフィックに使用される宛先ポートを指定します。

loadBalancer.vips.controlPlaneVIP

この値は、Kubernetes コントロール プレーン(Kubernetes API サーバー)に送信されるトラフィックに使用する宛先 IP アドレスを指定します。この IP アドレスは、クラスタ内のノードと同じレイヤ 2 サブネットに存在する必要があります。構成ファイルの address pools セクションには、このアドレスを記述しないでください

loadBalancer.vips.ingressVIP

この値は、上り(内向き)トラフィック用ロードバランサの背後にある Service に使用する IP アドレスを指定します。管理クラスタ構成ファイルでは、このフィールドを使用できません。このアドレスは、構成のアドレスプール セクションに記述する必要があります。

loadBalancer.addressPools

構成のこのセクションには、1 つ以上のアドレスプールが含まれています。各アドレスプールには、IP アドレス範囲のリストを指定します。LoadBalancer 型の Service を作成すると、Service の外部 IP アドレスはそれらの範囲から選択されます。

アドレスプールは次の形式で指定されます。

- name: POOL_NAME
  avoidBuggyIPs: BOOLEAN
  manualAssign: BOOLEAN
  addresses:
  - IP_RANGE
  - IP_RANGE2
  • name: ご自身の組織としての目的に適したアドレスプールの名前(pool-name)。このフィールドは変更できません。
  • avoidBuggyIPs:(省略可)true または falsetrue の場合は、末尾が .0.255 のIP アドレスがプールから除外されます。一部のネットワーク ハードウェアは、これらの特別なアドレスへのトラフィックをドロップします。このフィールドは省略できます。デフォルト値は false です。このフィールドは変更可能です。
  • manualAssign:(省略可)true または falsetrue の場合、このプール内のアドレスは Kubernetes Services に自動的に割り当てられません。true の場合、このプール内の IP アドレスは、サービスによって明示的に指定された場合にのみ使用されます。このフィールドは省略できます。デフォルト値は false です。このフィールドは変更可能です。
  • addresses 重複しない 1 つ以上の IP アドレス範囲のリスト。ip-range は、CIDR 表記(198.51.100.0/24 など)または範囲表記(198.51.100.0-198.51.100.10 など。ダッシュの前後にスペースなし)で指定します。このフィールドは変更できません。

addresses リストの IP アドレス範囲は重複していてはならず、ロードバランサを実行しているノードと同じサブネット内に存在する必要があります。

loadBalancer.nodePoolSpec

構成のこのセクションでは、ロードバランサを実行するノードのリストを指定します。ロードバランサ ノードは、デフォルトで通常のワークロードを実行できます。これらのノードには特別な taint はありません。以下の例は、2 つのノードを持つノードプールを示しています。最初のノード 1.2.3.4 は、k8sIP フィールドを使用して、クラスタ内のノードの IP アドレスを指定します。1.2.3.4 アドレスは SSH アクセスにのみ使用されます。

nodePoolSpec:
  nodes:
  - address: 1.2.3.4
    k8sIP: 10.0.0.32
  - address: 10.0.0.33

ロードバランサ ノードプール内のすべてのノードは、構成ファイルの loadBalancer.addressPools セクションで構成されているロードバランサの VIP と同じレイヤ 2 サブネット内にある必要があります。ノードに k8sIP が構成されている場合は、他のロードバランサの VIP と同じレイヤ 2 サブネットになければならないアドレスはそのアドレスだけです。

nodePoolSpec が設定されない場合、バンドルされたロードバランサは、コントロール プレーン ノードで実行されます。可能であれば、ロードバランサは、別のノードプールで実行することをおすすめします。

コントロール プレーンのロード バランシング

コントロール プレーンのロードバランサは、コントロール プレーンの仮想 IP アドレス(VIP)を提供します。GDCV for Bare Metal は、ロードバランサ ノードで Kubernetes の静的 Pod として Keepalived と HAProxy を実行し、コントロール プレーン VIP に通知します。Keepalived は、高可用性を実現するためにロードバランサ ノードの Virtual Router Redundancy Protocol(VRRP)を使用します。

データプレーンのロード バランシング

データ プレーン ロードバランサは、LoadBalancer タイプのすべての Kubernetes Service を対象としています。GDCV for Bare Metal は、レイヤ 2 モードで実行される MetalLB を使用してデータプレーンのロード バランシングを行います。データプレーンのロード バランシングは、GDCV for Bare Metal を介してのみ構成できます。MetalLB ConfigMap を直接変更しないでください。サービス間での IP アドレス共有など、すべての MetalLB 機能を使用できます。機能の詳細については、MetalLB のドキュメントをご覧ください。

MetalLBL は、デーモンセットを使用して各ノードでスピーカー Pod を実行し、高可用性のために memberlist を使用します。クラスタごとにではなく、Kubernetes Service ごとに専用の MetalLB 専用のロードバランサ ノードがあります。この方法により、複数のサービスがある場合、トラフィックはロードバランサ ノード間で分散されます。

データ プレーン ロードバランサは、コントロール プレーン ノードまたはワーカー ノードのサブセットで実行できます。コントロール プレーン ノードでデータプレーン ロードバランサのバンドルを行うと、コントロール プレーン ノードの使用率が増えます。ただし、コントロール プレーン ノードでバンドルを行うと、コントロール プレーンの過負荷のリスクが高まり、SSH 認証鍵などのコントロール プレーン上の機密情報のリスク プロファイルが増加します。

クライアントの送信元 IP アドレスの保持

バンドルされたレイヤ 2 ロード バランシング ソリューションで作成された LoadBalancer Service は、外部トラフィック ポリシーのデフォルトの Cluster 設定を使用します。この設定 spec.externalTrafficPolicy: Cluster は、クラスタ全体のエンドポイントに外部トラフィックを転送しますが、クライアント送信元 IP アドレスは不明瞭になります。

以降のセクションでは、クライアントの送信元 IP アドレスを保持するようにクラスタを構成する方法について説明します。

サービス NodePort

Kubernetes は、NodePort Service に送信元ネットワーク アドレス変換(NAT)を行います。クライアントの送信元 IP アドレスを保持するには、service.spec.externalTrafficPolicyLocal に設定します。Kubernetes はソース NAT を実行しなくなりますが、選択したノード IP で実行中の Pod があることを確認する必要があります。

サービス LoadBalancer

LoadBalancer Service で externalTrafficPolicy: Local を使用するときは、ロードバランサ ノードで確実に実行されるようにアプリケーション Pod を設定します。この変更を行うには、次の nodeSelector をアプリケーション Pod に追加します。

apiVersion: v1
kind: Pod
...
spec:
  nodeSelector:
      baremetal.cluster.gke.io/lbnode: "true"
...

上り(内向き)

アプリケーションが HTTP サービスである場合は、Ingress コンポーネントを構成することで、クライアント IP の可視性を実現できます。

  1. istio-ingress Service を編集用に開きます。

    kubectl edit service -n gke-system istio-ingress
    
  2. externalTrafficPolicy: Localspec に追加し、エディタを保存して終了します。

    apiVersion: v1
    kind: Service
    ...
    spec:
    ...
      externalTrafficPolicy: Local
    
  3. istio-ingress Deployment を編集用に開きます。

    kubectl edit deployment -n gke-system istio-ingress
    
  4. 次の nodeSelector を Deployment に追加し、エディタを保存して終了します。

    apiVersion: apps/v1
    kind: Deployment
    ...
    spec:
      ...
      template:
        ...
        spec:
          ...
          nodeSelector:
              baremetal.cluster.gke.io/lbnode: "true"
    ...
    

次の例のように、Ingress の背後にあるすべてのサービスに、クライアント IP を含む X-Forwarded-For ヘッダーが表示されます。

X-Forwarded-For: 21.0.104.4