このページでは、Google Distributed Cloud の MetalLB を使用してバンドル型ロード バランシングを構成する方法について説明します。MetalLB ロードバランサは、ワーカーノードの専用プールまたはコントロール プレーンと同じノード上で動作します。
Google Distributed Cloud で使用可能なロード バランシング トポロジの例については、ロードバランサの概要をご覧ください。
要件
- すべてのロードバランサ ノードは、同じレイヤ 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
またはfalse
。true
の場合は、末尾が.0
と.255
の IP アドレスがプールから除外されます。一部のネットワーク ハードウェアは、これらの特別なアドレスへのトラフィックをドロップします。このフィールドは省略できます。デフォルト値はfalse
です。このフィールドは変更可能です。manualAssign
: (省略可)true
またはfalse
。true
の場合、このプール内のアドレスは Kubernetes Service に自動的に割り当てられません。true
の場合、このプール内の IP アドレスは、Service によって明示的に指定された場合にのみ使用されます。このフィールドは省略できます。デフォルト値は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 はありません。ロードバランサ ノードプール内のノードはワークロードを実行できますが、ワーカー ノードプール内のノードとは分離されています。特定のクラスタノードを複数のノードプールに含めることはできません。ノードプール間でノード IP アドレスが重複すると、クラスタの作成などのクラスタ オペレーションがブロックされます。
ロードバランサ ノードプール内のノードでワークロードが実行されないようにするには、次の taint をノードに追加します。
node-role.kubernetes.io/load-balancer:NoSchedule
Google Distributed Cloud は、ロード バランシングに必要な Pod にこの taint の toleration を追加します。
次の例は、2 つのノードを含むロード バランシング ノードプールを示しています。最初のノードには、標準 IP アドレス nodePoolSpec.nodes.address
(「1.2.3.4」)と Kubernetes IP アドレス nodePoolSpec.nodes.k8sIP
(10.0.0.32
)が設定されています。ノードにオプションの k8sIP
アドレスを指定すると、Kubernetes API、kubelet、ワークロードのリクエストやレスポンスなど、ノードのデータ トラフィックの処理専用になります。この場合、管理クラスタ オペレーションでのノードへの SSH 接続には、標準 IP アドレス nodePoolSpec.nodes.address
が使用されます。k8sIP
アドレスを指定しない場合、ノードの標準 IP アドレスでノードのすべてのトラフィックが処理されます。
nodePoolSpec:
nodes:
- address: 1.2.3.4
k8sIP: 10.0.0.32
- address: 10.0.0.33
デフォルトでは、ロードバランサ ノードプール内のすべてのノードは、構成ファイルの loadBalancer.addressPools
セクションで構成されているロードバランサの VIP と同じレイヤ 2 サブネット内にある必要があります。ただし、ノードに Kubernetes IP アドレス k8sIP
を指定する場合は、そのアドレスのみが他のロードバランサの VIP と同じレイヤ 2 サブネットに存在する必要があります。
nodePoolSpec
を設定しない場合、バンドルされたロードバランサは、コントロール プレーン ノードで実行されます。可能であれば、ロードバランサは、別のノードプールで実行することをおすすめします。
コントロール プレーンのロード バランシング
コントロール プレーンのロードバランサは、コントロール プレーンの仮想 IP アドレス(VIP)を提供します。Google Distributed Cloud は、ロードバランサ ノード上の Kubernetes 静的 Pod として Keepalived と HAProxy を実行し、コントロール プレーン VIP に通知します。Keepalived は、高可用性を実現するためにロードバランサ ノードの Virtual Router Redundancy Protocol(VRRP)を使用します。
データプレーンのロード バランシング
データ プレーン ロードバランサは、LoadBalancer
タイプのすべての Kubernetes Service を対象としています。Google Distributed Cloud は、レイヤ 2 モードで実行される MetalLB を使用してデータプレーンのロード バランシングを行います。データプレーンのロード バランシングは、Google Distributed Cloud を介してのみ構成できます。MetalLB ConfigMap を直接変更しないでください。サービス間での IP アドレス共有など、すべての MetalLB 機能を使用できます。機能の詳細については、MetalLB のドキュメントをご覧ください。
MetalLBL は、デーモンセットを使用して各ノードでスピーカー Pod を実行し、高可用性のために memberlist を使用します。クラスタごとにではなく、Kubernetes Service ごとに専用の MetalLB 専用のロードバランサ ノードがあります。この方法により、複数のサービスがある場合、トラフィックはロードバランサ ノード間で分散されます。
データ プレーン ロードバランサは、コントロール プレーン ノードで、またはワーカーノードのサブセットで実行できます。コントロール プレーン ノードでデータプレーン ロードバランサのバンドルを行うと、コントロール プレーン ノードの使用率が増えます。ただし、コントロール プレーン ノードでバンドルを行うと、コントロール プレーンが過負荷になるリスクが高まり、SSH 認証鍵など、コントロール プレーン上の機密情報のリスク プロファイルが増大します。
クライアントの送信元 IP アドレスの保持
バンドルされたレイヤ 2 ロード バランシング ソリューションで作成された LoadBalancer
Service は、外部トラフィック ポリシーのデフォルトの Cluster
設定を使用します。この設定 spec.externalTrafficPolicy: Cluster
は、クラスタ全体のエンドポイントに外部トラフィックを転送しますが、クライアント送信元 IP アドレスは不明瞭になります。
以降のセクションでは、クライアントの送信元 IP アドレスを保持するようにクラスタを構成する方法について説明します。
NodePort
Service
Kubernetes は、NodePort
Service に送信元ネットワーク アドレス変換(SNAT)を行います。クライアントの送信元 IP アドレスを保持するには、service.spec.externalTrafficPolicy
を Local
に設定します。Kubernetes は SNAT を実行しなくなりますが、選択したノード IP で実行中の Pod があることを確認する必要があります。
LoadBalancer
Service
LoadBalancer
Service で externalTrafficPolicy: Local
を使用するときは、ロードバランサ ノードで確実に実行されるようにアプリケーション Pod を設定します。この変更を行うには、次の nodeSelector
をアプリケーション Pod に追加します。
apiVersion: v1
kind: Pod
...
spec:
nodeSelector:
baremetal.cluster.gke.io/lbnode: "true"
...
Ingress
アプリケーションが HTTP サービスである場合は、Ingress コンポーネントを構成することで、クライアント IP の可視性を実現できます。
istio-ingress
Service を編集用に開きます。kubectl edit service -n gke-system istio-ingress
externalTrafficPolicy: Local
をspec
に追加し、エディタを保存して終了します。apiVersion: v1 kind: Service ... spec: ... externalTrafficPolicy: Local
istio-ingress
Deployment を編集用に開きます。kubectl edit deployment -n gke-system istio-ingress
次の
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