手当たり次第に書くんだ

飽きっぽいのは本能

Kubernetes に LoadBalancer はないのか – Service、MetalLB、CNI BGP を分けて考える

Kubernetes と入口設計の関連記事

Kubernetes のネットワーク設計では、「Kubernetes には LoadBalancer がないので MetalLB を入れる」という説明が出てくることがあります。

言いたいことは分かります。クラウド環境では type: LoadBalancer の Service を作ると、クラウドロードバランサーが自動的に作られることがあります。一方で、オンプレミス Kubernetes では、同じ Service を作っても外部 IP が割り当たらず、外部から到達できないことがあります。

ただし、そこで「Kubernetes には LoadBalancer がない」と言い切ると、少し雑になります。

Kubernetes には、Service の公開方式として type: LoadBalancer があります。ないのは、Kubernetes 単体で物理ネットワーク上の外部ロードバランサーや経路広告まで自動的に用意する仕組みです。

この記事では、Kubernetes の LoadBalancer Service、MetalLB、CNI、BGP を、オンプレミス環境の外部公開設計として確認します。実際の設定値や対応機能は Kubernetes、MetalLB、CNI のバージョンによって変わるため、導入時点の公式ドキュメントで確認してください。

Kubernetes にあるのは Service の抽象である

Kubernetes の Service は、Pod 群に対して安定した名前、IP、ポートを提供するためのリソースです。

Pod は作り直されるたびに IP が変わります。ReplicaSet や Deployment によって Pod が増減することもあります。そのため、Pod の IP を直接参照してアプリケーション同士を接続すると、構成がすぐに不安定になります。

Service は、その不安定な Pod 群の前に、安定した到達点を置くための抽象です。

ClusterIPクラスタ内部から Service へ到達するための仮想 IP を提供する。
NodePort各 Node の特定ポートで Service を公開する。
LoadBalancer外部ロードバランサーを前提に Service を公開する。
ExternalNameService 名を外部 DNS 名へ対応づける。

このうち type: LoadBalancer は、Kubernetes に「この Service を外部ロードバランサー経由で公開したい」と宣言するものです。公式ドキュメントでも、クラウドプロバイダーのロードバランサーを使って Service を外部へ公開する方式として説明されています。

apiVersion: v1
kind: Service
metadata:
  name: example
spec:
  type: LoadBalancer
  selector:
    app: example
  ports:
    - name: http
      port: 80
      targetPort: 8080

この YAML は、LoadBalancer Service の宣言です。しかし、この宣言だけで物理ネットワークにロードバランサーが突然生まれるわけではありません。

クラウド環境では、クラウドコントローラーがこの要求を受け取り、AWS、Azure、Google Cloud などのロードバランサーを作成します。オンプレミス環境では、その役割を担う実装を別途用意する必要があります。

LoadBalancer Service は要求であって、物理装置そのものではない

Kubernetes は Service の抽象を持っています。ただし、その抽象を外部ネットワークへ接続する実装は環境側に必要です。

MetalLB はオンプレで LoadBalancer Service を成立させる実装である

MetalLB は、オンプレミス Kubernetes で LoadBalancer Service を成立させるための実装です。

MetalLB は、Service に外部 IP を割り当て、その IP へ外部ネットワークから到達できるようにします。つまり、Kubernetes の Service 抽象と、実際のネットワーク到達性の間をつなぐ部品です。

L2 モード特定の Node が外部 IP を受け持つように振る舞い、ARP / NDP に応答して到達性を作る。
BGP モード外部ルーターと BGP ピアを張り、LoadBalancer IP への経路を広告する。
IP アドレスプールService に割り当てる外部 IP の範囲を定義する。
SpeakerNode 側で外部ネットワークへの広告や応答を担うコンポーネント。

MetalLB を「Kubernetes に LoadBalancer を追加するもの」と言うこともできますが、それだけでは少し粗いです。より正確には、MetalLB は LoadBalancer Service の要求に対して、オンプレミス環境で外部 IP と到達性を与える実装です。

この違いは重要です。MetalLB は Kubernetes の Service を置き換えるものではありません。Service の抽象を、オンプレミスの L2 / L3 ネットワークに接続するための実装です。

CNI は Pod ネットワークの土台である

CNI は、Pod にネットワークを与えるための仕組みです。

Calico、Cilium、Flannel、Kube-OVN などは、それぞれ異なる方法で Pod ネットワーク、ノード間通信、NetworkPolicy、データプレーンを実装します。

ここで混乱しやすいのは、CNI と LoadBalancer Service の関係です。CNI は Pod ネットワークの土台であり、Service の外部公開だけを担当するものではありません。

ただし、Calico や Cilium のように BGP 機能を持つ CNI もあります。この場合、Pod CIDR、Service IP、LoadBalancer IP の経路広告まで CNI 側で扱える構成があります。

すると、MetalLB の BGP と CNI の BGP をどう分けるのか、という設計判断が必要になります。

Pod ネットワークPod 間通信や Node 間通信をどう成立させるか。
NetworkPolicyPod 間の通信制御をどのレイヤーで実現するか。
Service 処理kube-proxy、eBPF、CNI 機能のどこで Service 転送を扱うか。
BGP 広告Pod CIDR、Service IP、LoadBalancer IP のどれを外部へ広告するか。

この切り分けをしないまま「CNI が BGP を持っているから MetalLB は不要」と言うと、何の経路を誰が広告するのかが曖昧になります。逆に、MetalLB を入れれば CNI の経路設計を考えなくてよい、という話でもありません。

BGP はロードバランサーではなく経路広告である

BGP はロードバランサーではありません。

BGP は、どの IP プレフィックスにどの経路で到達できるかを、外部ネットワークへ伝えるための経路制御プロトコルです。

MetalLB の BGP モードや CNI の BGP 機能は、外部ルーターに対して「この LoadBalancer IP や Pod ネットワークには、この Node 経由で到達できる」と知らせるために使われます。

そのため、BGP を使ったからといって、それだけでアプリケーションレベルの負荷分散が完成するわけではありません。

BGP が担当すること外部ネットワークへ経路を伝え、LoadBalancer IP や Pod ネットワークへの到達性を作る。
Service が担当することService IP やポートを入口として、背後の Endpoint / Pod へ接続する抽象を提供する。
kube-proxy / eBPF が担当することService への通信を実際の Pod へ転送するデータプレーン処理を担う。
アプリケーションが担当することHTTP、セッション、認証、業務ロジック、障害時の振る舞いを扱う。

BGP は到達性を作ります。どの Pod に流すか、送信元アドレスを維持するか、Node 障害時に経路をどう引っ込めるか、通信がどの Node を経由するかは、Service、MetalLB、CNI、kube-proxy 代替、外部ルーターの組み合わせで決まります。

Service、MetalLB、CNI BGP を分ける

ServicePod 群に対する安定した到達点を作る Kubernetes の抽象。
type: LoadBalancer外部向けロードバランサーを要求する Service の公開方式。
MetalLBオンプレミス環境で LoadBalancer Service に外部 IP と到達性を与える実装。
CNIPod ネットワーク、NetworkPolicy、Service 処理、経路制御の土台。
BGP外部ネットワークへ経路を伝えるためのプロトコル。
外部ルーターMetalLB や CNI から受け取った経路を、実ネットワークへ反映する側。

このように分けると、「Kubernetes に LoadBalancer はない」という表現がどこでずれているかが見えます。

Kubernetes には LoadBalancer Service という抽象があります。ないのは、オンプレミス環境でその抽象を実ネットワークへ接続する外部ロードバランサー実装です。

MetalLB はその実装の一つです。CNI BGP は、Pod ネットワークや Service 到達性を外部ネットワークへ広告する別の設計要素です。BGP は、そのための経路制御の手段です。

オンプレ Kubernetes で設計すべきこと

オンプレミス Kubernetes では、クラウドのように外部ロードバランサーが自動的に用意されるとは限りません。そのため、外部公開の設計を自分たちで決める必要があります。

外部 IP の払い出しLoadBalancer Service に割り当てる IP アドレス帯を誰が管理するのか。
到達性の作り方L2 で ARP / NDP に応答するのか、BGP で経路広告するのか。
BGP の責務MetalLB が広告するのか、CNI が広告するのか、両方を使うのか。
外部ルーターどの Node と BGP ピアを張り、どのプレフィックスを受け取るのか。
送信元アドレスexternalTrafficPolicy、Node 経由、Pod への転送経路で送信元 IP がどう見えるか。
障害時の収束Node 障害、Pod 障害、経路 withdraw、ARP / NDP の切り替わりをどう扱うか。

ここを曖昧にしたまま MetalLB や CNI を入れると、平常時は動いているように見えても、障害時や経路変更時に説明できない構成になります。

特に BGP を使う場合は、Kubernetes 内部だけで完結しません。外部ルーター側のポリシー、経路集約、フィルタ、ECMP、障害時の収束時間まで含めて設計する必要があります。

オンプレ Kubernetes の LoadBalancer はネットワーク設計である

Service の YAML だけでなく、外部 IP、ルーター、BGP、CNI、Node 障害時の経路収束まで含めて考える必要があります。

参考
書籍
参考書籍

Kubernetes 完全ガイド 第 2 版

Kubernetes の Service、ネットワーク、リソース設計を体系的に確認したい場合の参考書籍です。価格や在庫はリンク先で確認してください。

Amazon で見る

このリンクは Amazon アソシエイトリンクです。

まとめ

Kubernetes に LoadBalancer がない、という言い方は正確ではありません。Kubernetes には Service の公開方式として type: LoadBalancer があります。

ただし、Kubernetes が単体で外部ロードバランサーや物理ネットワーク上の到達性を作ってくれるわけではありません。クラウド環境ではクラウド側のロードバランサーがその役割を担い、オンプレミス環境では MetalLB や CNI の BGP 機能などを組み合わせて設計します。

Service は Kubernetes の抽象、MetalLB はオンプレミスで LoadBalancer Service を成立させる実装、CNI は Pod ネットワークの土台、BGP は経路広告の手段です。

この 4 つを分けて考えると、Kubernetes の外部公開設計はかなり見通しがよくなります。逆に、ここを混ぜると、動いている時はよくても、障害時にどこを見ればよいのか分からなくなります。

参考情報

関連する記事
Kubernetes に LoadBalancer はないのか – Service、MetalLB、CNI BGP を分けて考える

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る