Contents
Overview
MetalLB は、Kubernetes クラスターにロードバランシング機能を提供するソフトウェアです。Kubernetes は、クラウドネイティブな環境で設計されており、クラウドプロバイダーによって提供されるロードバランサーに依存することが一般的です。しかし、オンプレミス環境やクラウドプロバイダーが提供するロードバランサを使用できない場合、MetalLB は非常に役立ちます。
MetalLB は、Layer 2 モードと BGP モードの 2 つの動作モードをサポートしています。Layer 2 モードでは、同じサブネット内で IP アドレスをアナウンスすることでロードバランシングを行い、BGP モードでは、BGP (Border Gateway Protocol) を使用してルーティング情報をアナウンスします。個人的には、特別な条件が無ければ BGP モードを推奨します。
前提条件
- MetalLB のバージョンは v0.13.12 を使用しています。
- 最新の MetalLB は以下の選択肢があります。本稿では metallb-frr を採用していますが、将来的には、高機能な metallb-frr-k8s を採用した方が良いと思います。
- metallb-native: MetalLB の基本モードであり、標準的な Layer 2 と BGP の設定を使用できます。
- metallb-frr: FRR をバックエンドに使用し、BGP の高度な機能(BFD、IPv6、マルチプロトコル BGP)をサポートします。
- metallb-frr-k8s: FRR-K8s を使用し、MetalLB のスピーカーと連携しつつ、MetalLB の範囲を超えた FRR 機能を提供します。
インストール
MetalLB (metallb-frr) をインストールします。MetalLB のインストールには、Kustomize や Helm を使用できますが、本稿ではマニフェストベースのインストールとなります。
myadmin@ubuntu-22-04:~$ kubectl create -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-frr.yaml
Layer 2 モード
Layer 2 モードの概要
概要
- 動作: 1 つのノードがサービスの IP をローカルネットワークにアナウンスする責任を持ちます。MetalLB は IPv4 の場合は ARP リクエスト、IPv6 の場合は NDP リクエストに応答します。
- 利点: 特別なハードウェアを必要とせず、どの Ethernet ネットワークでも動作します。
ロードバランシングの挙動
- トラフィックの流れ: サービス IP への全トラフィックは 1 つのノードに集まり、そこから kube-proxy がトラフィックを各ポッドに分散します。
- フェイルオーバー: リーダーノードが障害を起こすと、自動で他のノードが IP アドレスを引き継ぎます。
制限事項
- シングルノードのボトルネック:
- サービスの帯域幅が 1 つのノードの帯域幅に制限されます。
- フェイルオーバーの遅延:
- フェイルオーバーがクライアントの協力に依存し、一部のシステムは Gratuitous ARP パケットを正しく処理しないため、キャッシュの更新が遅れることがあります。
L2 リーダー選出の仕組み
- 選出方法:
- 各スピーカーが「node+VIP」要素のハッシュを使ってリストを計算し、最初のアイテムがサービスをアナウンスします。
- スピーカー間で状態を保持する必要がありません。
ノードの追加・削除
- ノードの削除: 現在のリーダースピーカーが変更されません。
- ノードの追加: 新しいノードがリストの最初のアイテムになると、リーダースピーカーが変更されます。
MetalLB の Layer 2 モードは、フェイルオーバーとロードバランシングのためのシンプルかつ汎用的なソリューションを提供します。クラスター内での高可用性を実現しつつ、複雑なネットワークインフラとの相互運用性は必要としない設計となっています。
Layer 2 モードの設定
まず、公式サイトによると「IPVS モードで kube-proxy を使用している場合、Kubernetes v1.14.2 以降では strictARP
を有効にする必要があります。」と記載されています。この設定は Layer 2 モードでのみ必要です。具体的な設定内容は「Kubernetes クラスター構築」に含めていますので、そちらを参照して下さい。
次に、以下のように IPAddressPool
, L2Advertisement
の設定をします。この設定により、MetalLB は 10.1.0.192/27
および fd00::a01:c0/123
の範囲内の IP アドレスを Kubernetes サービスに割り当て、これらの IP アドレスを Layer 2 モードでネットワーク上にアナウンスします。
myadmin@ubuntu-22-04:~$ cat <<EOF | kubectl create -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- 10.1.0.192/27
- fd00::a01:c0/123
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2advertisement
namespace: metallb-system
spec:
ipAddressPools:
- default
EOF
- IPAddressPool: IPAddressPool リソースは、MetalLB がサービスに割り当てる IP アドレスの範囲を定義します。この設定では、IPv4 と IPv6 の両方のアドレス範囲を指定しています。
- apiVersion: metallb.io/v1beta1: MetalLB リソースのバージョンを指定します。
- kind: IPAddressPool: リソースの種類を示します。この場合、IP アドレスプールの定義です。
- metadata:
- name: default: この IP アドレスプールの名前を指定します。この名前は他のリソースから参照するために使用されます。
- namespace: metallb-system: このリソースが属する Kubernetes のネームスペースを指定します。MetalLB は通常、
metallb-system
ネームスペースにデプロイされます。
- spec:
- addresses: MetalLB が使用する IP アドレスの範囲を指定します。
- 10.1.0.192/27: IPv4 のアドレス範囲を指定しています。
- fd00::a01:c0/123: IPv6 のアドレス範囲を指定しています。
- addresses: MetalLB が使用する IP アドレスの範囲を指定します。
- L2Advertisement: L2Advertisement リソースは、MetalLB が Layer 2 モードで IP アドレスをどのようにアナウンスするかを定義します。この設定では、前述の IPAddressPool リソースを使用して IP アドレスをアナウンスします。
- apiVersion: metallb.io/v1beta1: MetalLBリソースのバージョンを指定します。
- kind: L2Advertisement: リソースの種類を示します。この場合、Layer 2 アドバタイズメントの定義です。
- metadata:
- name: l2advertisement: この L2 アドバタイズメントの名前を指定します。
- namespace: metallb-system: このリソースが属する Kubernetes のネームスペースを指定します。
- spec:
- ipAddressPools: このアドバタイズメントに関連付ける IP アドレスプールの名前を指定します。この設定では、前述の
IPAddressPool
リソース(名前はdefault
)を指定しています。
- ipAddressPools: このアドバタイズメントに関連付ける IP アドレスプールの名前を指定します。この設定では、前述の
BGP モード
BGP モードの概要
概要
- BGP ピアリングの確立:
- クラスター内の各ノードがネットワークルーターと BGP ピアリングセッションを確立し、そのセッションを通じて外部クラスターサービスの IP アドレスをアナウンスします。
- ロードバランシングの仕組み:
- ルーターがマルチパス (multipath) をサポートしている場合、MetalLB が公開するルートは互いに等価であり、異なるネクストホップを持つだけです。これにより、ルーターはすべてのネクストホップを使用してトラフィックをロードバランスします。
- パケットがノードに到着した後、kube-proxy が最終的なトラフィックルーティングを行い、パケットをサービス内の特定のポッドに送ります。
ロードバランシングの挙動
- 接続単位のバランシング:
- 具体的な挙動はルーターのモデルや設定に依存しますが、一般的にはパケットハッシュに基づいて接続単位でバランシングを行います。
- 単一の TCP または UDP セッションのすべてのパケットがクラスター内の単一のマシンに送信されます。異なる接続間でのみトラフィックが分散されます。
- 単一接続のスプレッドが悪影響を及ぼす理由:
- 複数のパスに単一接続を分散すると、パケットの順序が乱れ、エンドホストのパフォーマンスが大幅に低下します。
- Kubernetes 内のノード間のトラフィックルーティングが一貫していないため、異なるノードが同じ接続のパケットを異なるポッドにルーティングする可能性があり、接続が失敗します。
- パケットハッシュ:
- 高性能ルーターはステートレスで接続を分散するためにパケットハッシュを使用します。パケットからいくつかのフィールドを抽出し、それを「シード」として使用して、可能なバックエンドのうちの 1 つを決定します。
- 3-tuple(プロトコル、送信元 IP、宛先 IP)や 5-tuple(送信元および宛先ポートを追加)ハッシュが一般的です。
制限事項
- BGP ベースのロードバランシングの反応性:
- BGP ベースのロードバランシングは、バックエンドセットの変更に対してうまく反応しません。クラスターのノードがダウンすると、すべてのアクティブな接続が切断される可能性があります。
- ハッシュの安定性:
- ルーターのハッシュは通常安定していないため、バックエンドセットが変更されると、既存の接続が再ハッシュされ、ほとんどの接続が異なるバックエンドに突然転送されることになります。
- 対策:
- より安定した ECMP ハッシュアルゴリズムを使用する。
- サービスデプロイメントを特定のノードに固定する。
- トラフィックが少ない時間帯に変更をスケジュールする。
- 論理的なサービスを 2 つの Kubernetes サービスに分割し、DNS を使用してトラフィックを移行する。
- クライアント側で透過的なリトライロジックを追加する。
- イングレスコントローラーの背後にサービスを配置する。
- 断続的な接続リセットを許容する。
FRR モード
- 追加機能:
- BFD サポート付きの BGP セッション。
- BGP と BFD の IPv6 サポート。
- マルチプロトコル BGP。
- 制限事項:
- 同一ホスト内でのピアリングが不可能。
- BGPAdvertisement の RouterID および myAsn フィールドがオーバーライドされる場合、すべてのアドバタイズメントで同一である必要がある。
- eBGP ピアが複数ホップ離れている場合、ebgp-multihop フラグを true に設定する必要がある。
FRR-K8s モード
- 概要:
- FRR-K8s は Kubernetes のラッパーであり、MetalLB が FRR-K8s の設定を生成します。
- ユーザーは追加の FRR-K8s 設定インスタンスを提供でき、MetalLB が提供するサービスのアドバタイズメント以外の目的で FRR を利用できます。
- 特徴と制限:
- FRR モードと同じ特徴と制限が適用されます。
このように、MetalLB の BGP モードは高いスケーラビリティと柔軟性を提供しますが、いくつかの制限事項もあります。特にノードの変更やバックエンドセットの変更時に接続が切断される可能性があるため、適切な対策を講じることが重要です。
BGP モードの設定
BGP モードでは Layer 2 モードのように strictARP
の設定は必要ありません。
以下のように、IPAddressPool
, BGPAdvertisement
, BGPPeer
の設定をします。この設定は、MetalLB が IPv4 および IPv6 のアドレス範囲を使用してサービスIPをアドバタイズし、特定の BGP ピアとセッションを確立するためのものです。IPAddressPool
で定義された IP アドレスが、BGPAdvertisement
によってアドバタイズされ、BGPPeer
で定義されたピアと BGP セッションを確立します。本稿では、ローカルとリモートの AS に同じ番号を使用しており、iBGP での構成となっています。
myadmin@ubuntu-22-04:~$ cat <<EOF | kubectl create -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- 172.17.64.0/24
- fd00::ac11:4000/120
---
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default
---
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
name: default-ipv4
namespace: metallb-system
spec:
myASN: 64512
peerASN: 64512
peerAddress: 10.65.224.3
---
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
name: default-ipv6
namespace: metallb-system
spec:
myASN: 64512
peerASN: 64512
peerAddress: fd00::a41:e003
EOF
- IPAddressPool:
IPAddressPool
リソースは、MetalLB がサービスに割り当てる IP アドレスの範囲を定義します。この設定では、IPv4 と IPv6 の両方のアドレス範囲を指定しています。- apiVersion: metallb.io/v1beta1: MetalLB リソースのバージョンを指定します。
- kind: IPAddressPool: リソースの種類を示します。この場合、IP アドレスプールの定義です。
- metadata:
- name: default: この IP アドレスプールの名前を指定します。この名前は他のリソースから参照するために使用されます。
- namespace: metallb-system: このリソースが属する Kubernetes のネームスペースを指定します。MetalLB は通常、metallb-system ネームスペースにデプロイされます。
- spec:
- addresses: MetalLB が使用する IP アドレスの範囲を指定します。
- 172.17.64.0/24: IPv4 のアドレス範囲を指定しています。
- fd00::ac11:4000/120: IPv6 のアドレス範囲を指定しています。
- addresses: MetalLB が使用する IP アドレスの範囲を指定します。
- BGPAdvertisement: BGPAdvertisement リソースは、MetalLB が BGP モードで IP アドレスをどのようにアナウンスするかを定義します。この設定では、前述の
IPAddressPool
リソースを使用して IP アドレスをアナウンスします。- apiVersion: metallb.io/v1beta1: MetalLB リソースのバージョンを指定します。
- kind: BGPAdvertisement: リソースの種類を示します。この場合、BGP アドバタイズメントの定義です。
- metadata:
- name: default: この BGP アドバタイズメントの名前を指定します。
- namespace: metallb-system: このリソースが属する Kubernetes のネームスペースを指定します。
- spec:
- ipAddressPools: このアドバタイズメントに関連付ける IP アドレスプールの名前を指定します。この設定では、前述の
IPAddressPool
リソース(名前はdefault
)を指定しています。
- ipAddressPools: このアドバタイズメントに関連付ける IP アドレスプールの名前を指定します。この設定では、前述の
- BGPPeer (IPv4):
BGPPeer
リソースは、MetalLB が BGP ピアとセッションを確立するための設定を定義します。この設定では、IPv4 アドレスを使用して BGP ピアリングを行います。- apiVersion: metallb.io/v1beta2: MetalLB リソースのバージョンを指定します。
- kind: BGPPeer: リソースの種類を示します。この場合、BGP ピアの定義です。
- metadata:
- name: default-ipv4: この BGP ピアの名前を指定します。
- namespace: metallb-system: このリソースが属する Kubernetes のネームスペースを指定します。
- spec:
- myASN: 64512: 自身の ASN (Autonomous System Number) を指定します。
- peerASN: 64512: ピアの ASN を指定します。
- peerAddress: 10.65.224.3: ピアの IPv4 アドレスを指定します。
- BGPPeer (IPv6): 上記の設定の IPv6 バージョンです。この設定では、IPv6 アドレスを使用して BGP ピアリングを行います。
- apiVersion: metallb.io/v1beta2: MetalLB リソースのバージョンを指定します。
- kind: BGPPeer: リソースの種類を示します。この場合、BGP ピアの定義です。
- metadata:
- name: default-ipv6: この BGP ピアの名前を指定します。
- namespace: metallb-system: このリソースが属する Kubernetes のネームスペースを指定します。
- spec:
- myASN: 64512: 自身の ASN (Autonomous System Number) を指定します。
- peerASN: 64512: ピアの ASN を指定します。
- peerAddress: fd00::a41:e003: ピアの IPv6 アドレスを指定します。