0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

オンプレK8sでLoadBalancer Serviceを使うためにMetalLB(BGPモード)を入れた話

0
Posted at

この記事は2024年後半頃の構築作業をもとにしています。当時のバージョンは Calico v3.28.1 / MetalLB v0.14.8。手順や推奨構成はその後変わっている部分があるので、最新の公式ドキュメントと併せて読んでください。

経緯

オンプレの物理サーバ(Hyper-V上のVM)でK8sクラスタを組んだ。クラウドのマネージドK8sなら type: LoadBalancer のServiceを作れば、クラウド側の連携コンポーネントが勝手に外部IP(AWSの場合はELBのDNS名)を払い出してくれる。しかしオンプレだと当然そんなものはなく、EXTERNAL-IPが <pending> のまま永遠に待ちぼうけになる。

要件は次の2つ。

  • NetworkPolicyでアクセス制御をしたい
  • LoadBalancerタイプのServiceを使いたい(クラスタ外からのアクセスを各ノードに分散したい)

この2つを満たす構成として、CNIにCalico、LoadBalancer実装としてMetalLBをBGPモードで採用した。

構成の全体像

  • Calico (CNI。クラスタ内のL3ネットワーク + NetworkPolicy担当)
  • MetalLB (BGPモードで、LoadBalancer ServiceのIPを外部のBGPルータ2台に経路広報する)
  • 外部のBGPルータがLBのVIP宛のトラフィックを受け、各ノードに振り分ける

なお当時使ったのはMetalLBの「native mode」(組み込みのBGP実装)だが、現在の公式ドキュメントではFRR-K8sモードが推奨になっている。これから入れるならそちらを検討した方がよさそう。

ハマりどころ・気づき

1. Calicoは最初からBGPを喋っている

当初は「MetalLBがBGPなんだからCalicoもBGPモードにするんでしょ」と思ってCalicoのBGP化を進めていた。ところが kubectl calico node status を叩いてみると、BGP設定を何もデプロイしていない時点で、全ノード間のBGPネイバー(node-to-node mesh)がEstablishedになっていた

IPv4 BGP status
+--------------+-------------------+-------+------------+-------------+
| PEER ADDRESS |     PEER TYPE     | STATE |   SINCE    |    INFO     |
+--------------+-------------------+-------+------------+-------------+
| 10.x.x.x     | node-to-node mesh | up    | 2024-08-01 | Established |
| ...          | node-to-node mesh | up    | ...        | Established |
+--------------+-------------------+-------+------------+-------------+

Calicoはデフォルトでノード間フルメッシュのBGPを組み、Podへの経路を交換している(今回の構成ではPod間トラフィック自体はIPIPでカプセル化される設定 CALICO_IPV4POOL_IPIP: Always のまま)。「BGPモードにする」という作業の実態は、外部ルータとのピアリングや経路広報などのBGPConfigurationを追加することであって、BGP自体は最初から動いている。

2. BGPConfigurationは kubectl apply できない

Calicoの projectcalico.org/v3 APIグループのリソース(BGPConfigurationなど)は、素の kubectl apply だとデプロイに失敗する。calicoctl(kubectlプラグインとして kubectl calico で使える)が必要。calicoctlがこのAPIグループのバリデーションとデフォルト値補完を担っているため。

# kubectl calico apply -f bgpconfig.yaml
Successfully applied 1 'BGPConfiguration' resource(s)

kubectlだけで完結させたいならCalico APIサーバーを別途導入する必要がある。地味に引っかかるポイント。

現在のCalicoにはnative v3 CRDsという仕組みがあり、APIサーバーやcalicoctlなしで kubectl から直接 projectcalico.org/v3 リソースを管理できる選択肢が増えている。当時はcalicoctl一択だった。

3. で、CalicoのBGP設定は結局解除した

BGPConfigurationを作り、外部ルータとのピアリング設定を検討していたところで、「そもそもCalico側で外部ルータとBGPを喋る必要はないのでは?」と気づいた。外部にLBのIPを広報するのはMetalLBのspeakerの仕事で、Pod間の通信はCalicoのデフォルト構成のままで既に動いている。結局、追加したBGPConfigurationは削除し、Calicoはデフォルト設定のままとした。

役割分担を整理するとこうなる。

  • Calico: クラスタ内(Pod間)の経路。ノード間のBGPメッシュはデフォルトのまま
  • MetalLB: クラスタ外向け。LoadBalancer ServiceのIPを外部BGPルータに広報

なお、CalicoとMetalLBを併用する場合の制約(同じルータに両方がBGPピアを張ると衝突する問題)がMetalLBのドキュメントに書かれている。今回はCalico側で外部ピアを張らない構成にしたので、この制約自体を考慮不要にできた、という面もある。ちなみにASはCalicoのメッシュ(デフォルトの64512)とMetalLB(プライベートASを別途採番)で別になっている。

4. kube-proxyのstrictARP

MetalLB導入の前提として、kube-proxyをIPVSモードで使っている場合は strictARP: true にする必要がある(Kubernetes v1.14.2以降。公式のInstallation > Preparationに記載)。

kubectl edit configmap -n kube-system kube-proxy
ipvs:
  strictARP: true

MetalLBの設定

マニフェスト(metallb-native.yaml)でcontrollerとspeakerを入れたあと、設定系リソースをデプロイする。実際に使ったのは次の3種類。

IPAddressPool: LBとして払い出すIPアドレス範囲。

ipaddress-pool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: lb-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.x.x.1-10.x.x.254

BGPPeer: 外部BGPルータとのピア設定。ルータ2台分作って冗長化。

bgppeer1.yaml
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: router1
  namespace: metallb-system
spec:
  myASN: 65xxx
  peerASN: 65xxx
  peerAddress: 10.x.x.x

BGPAdvertisement: プールのIPをピアに広報する設定。specを書かなければ全プールがデフォルト設定で広報される。

advertisement.yaml
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
  name: advertisement1
  namespace: metallb-system

これで type: LoadBalancer のServiceを作るとプールからIPが払い出され、外部ルータ経由でクラスタ外から届くようになった。

まとめ

  • オンプレでLoadBalancer Serviceを使うならMetalLB。ルータと連携できる環境ならBGPモードが素直
  • 「MetalLBがBGPだからCNIもBGPモードに」は早合点だった。外部への経路広報はMetalLBの仕事で、Calicoはデフォルトのnode-to-node meshのままでよい
  • Calicoの projectcalico.org/v3 リソースは(当時は)calicoctl必須
  • kube-proxyがIPVSモードならstrictARPを忘れずに

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?