手当たり次第に書くんだ

飽きっぽいのは本能

Kubernetes の externalIPs 非推奨化を Calico BGP + eBPF 環境でどう考えるか

Kubernetes 1.36 で、Service の spec.externalIPs が非推奨になりました。Kubernetes 公式ドキュメントでも、externalIPs から移行を始めるべきことが示されています。

Calico の BGP 機能を使って Service VIP を外部ネットワークへ広告している環境では、これを単純に「外部ロードバランサー製品を導入する話」と見てしまうと、論点を誤ります。変更が必要なのは、BGP で VIP を広告する設計そのものではなく、Kubernetes 上で VIP をどの API フィールドに持たせ、どの仕組みで割り当てるかという部分です。

この記事では、Calico BGP と Calico eBPF データプレーンを使う環境を前提に、Service.spec.externalIPs 非推奨化の影響と、LoadBalancer Service + Calico LoadBalancer IPAM への移行を整理します。

前提とする構成

ここでは、次のような構成を前提例として扱います。特定の製品ロードバランサーを外部に置くのではなく、Calico が Service VIP の経路広告と Service 転送に関与する構成です。

項目前提例
Kubernetes1.35 から 1.36 以降への移行を見据える
Calico3.31 系を想定
Service VIP 広告Calico BGP
Service 転送Calico eBPF データプレーン
Service 公開用 VIP10.253.0.0/24

この構成では、現在の Service VIP をできるだけ維持しながら、VIP の指定方法を externalIPs から LoadBalancer Service へ移すことが移行の中心になります。

現在の externalIPs + Calico BGP 構成

現在の構成では、Calico の BGPConfiguration に Service External IP として広告する CIDR を指定します。

apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  serviceExternalIPs:
    - cidr: 10.253.0.0/24

Service 側では、公開したい VIP を spec.externalIPs に指定します。

apiVersion: v1
kind: Service
metadata:
  name: example-service
spec:
  selector:
    app: example
  ports:
    - port: 80
      targetPort: 8080
  externalIPs:
    - 10.253.0.10

Kubernetes 自身は、externalIPs に指定された IP アドレスをノードへ割り当てたり、その IP アドレスへの経路を外部ネットワークへ作成したりしません。外部からその VIP 宛ての通信が Kubernetes ノードへ到達するようにする責任は、利用者側にあります。

この前提例では、その到達性を Calico BGP によって実現しています。Service の externalIPsserviceExternalIPs の CIDR に含まれる場合、Calico が VIP への経路を BGP で外部へ広告します。その後、ノードへ到着した Service 宛て通信は Calico eBPF によってバックエンド Pod へ転送されます。

BGP 広告と Service 転送は別の機能である

この構成では、Calico が二つの異なる役割を担当しています。どちらも Calico が関係するため一体に見えますが、設計上は分けて考える必要があります。

処理担当役割
VIP への経路を外部へ知らせるCalico BGP外部ルーターから Kubernetes ノードへ到達させる
ノードへ到着した VIP 宛て通信を Pod へ転送するCalico eBPFkube-proxy の代わりに Service 処理を行う
現在の VIP 指定Kubernetes spec.externalIPsService が受け付ける外部 IP を表す

BGP は、外部ネットワークから Service VIP までの経路を作ります。一方、eBPF データプレーンは、Kubernetes ノードへ到着したパケットを Service の Endpoint である Pod へ転送します。Calico eBPF モードでは、Kubernetes Service 処理を kube-proxy ではなく Calico が直接実装します。

Kubernetes 1.36 で非推奨になったもの

Kubernetes 1.36 で非推奨になったのは、Service API の spec.externalIPs フィールドです。

spec:
  externalIPs:
    - 10.253.0.10

externalIPs は、Service を操作できる利用者が任意の IP アドレスを指定できる構造を持ちます。この性質は、割り当てられていない IP アドレスの横取りや意図しない通信誘導につながる可能性があり、Kubernetes の CVE-2020-8554 とも関係します。

ここで重要なのは、「External IP」という用語全体が非推奨になったわけではないことです。今回の対象は、あくまで Service.spec.externalIPs です。

対象今回の非推奨化との関係
Service.spec.externalIPsKubernetes 1.36 で非推奨
Node の status.addresses にある ExternalIP別の概念
kubectl get serviceEXTERNAL-IP表示上の列名であり、externalIPs だけを意味しない
LoadBalancer Service に割り当てる VIP移行先として利用できる
Calico による Service IP の BGP 広告非推奨化の直接対象ではない
Calico eBPF による Service 転送非推奨化の直接対象ではない

Calico の serviceExternalIPs は入力元に依存している

Calico の BGPConfiguration には、Service External IP を BGP 広告するための serviceExternalIPs があります。Calico 側でこのフィールド自体が非推奨になったという話ではありません。

ただし、serviceExternalIPs が広告する対象は、Kubernetes の Service.spec.externalIPs に設定されたアドレスです。つまり、Calico の設定が残っていても、その入力元となる Kubernetes API フィールドが非推奨になっています。

構成要素現在の位置づけ
Kubernetes Service.spec.externalIPsKubernetes 1.36 で非推奨
Calico serviceExternalIPsCalico の BGP 広告設定として存在する
Calico BGP継続して利用可能
Calico eBPF継続して利用可能
BGP で Service VIP を公開する設計継続して利用可能

変更対象は、Calico BGP や eBPF そのものではありません。変更する必要があるのは、VIP を Kubernetes 上でどのように表現し、どの仕組みで管理するかです。

eBPF 環境では kube-proxy の廃止時期と分けて考える

Kubernetes の文脈では、将来 kube-proxy から externalIPs の処理が削除される可能性も論点になります。ただし、Calico eBPF 環境では、Service 処理を kube-proxy ではなく Calico eBPF が担当します。

そのため、kube-proxy から externalIPs 処理が削除されることと、Calico eBPF 環境が同じ時点で直ちに動作しなくなることは同じではありません。実際の動作可否は、その時点の Kubernetes API と Calico 側の実装にも依存します。

一方で、Kubernetes API として externalIPs が非推奨になった以上、Calico eBPF が独自に処理できる可能性を前提に設計を維持するのは適切ではありません。eBPF を使っていることは移行を不要にする理由ではなく、影響が現れる箇所と時期を kube-proxy 環境と分けて評価する理由です。

移行先は LoadBalancer Service と Calico LoadBalancer IPAM

Calico による BGP 広告と eBPF Service 処理を維持する場合、移行先は LoadBalancer Service と Calico LoadBalancer IPAM の組み合わせになります。

現在移行後
Service.spec.externalIPsService type: LoadBalancer
Calico serviceExternalIPsCalico serviceLoadBalancerIPs
利用者が VIP を直接指定Calico LoadBalancer IPAM が VIP を管理
VIP は spec.externalIPs に存在VIP は status.loadBalancer.ingress に記録
Calico BGP で経路広告Calico BGP で経路広告
Calico eBPF で Service 転送Calico eBPF で Service 転送

Service を LoadBalancer 型に変更しても、専用のロードバランサー製品や仮想アプライアンスを追加するとは限りません。この構成では、Kubernetes API 上は LoadBalancer Service として表現し、VIP の割り当てと BGP 広告を Calico が担当します。

Calico LoadBalancer IPAM の IPPool を作成する

Calico LoadBalancer IPAM を使うには、LoadBalancer 用の IPPool を明示的に作成します。Calico kube-controllers には LoadBalancer IPAM 機能がありますが、LoadBalancer Service 用の IPPool は自動作成されません。

apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: loadbalancer-ip-pool
spec:
  cidr: 10.253.0.0/24
  blockSize: 24
  disabled: false
  assignmentMode: Automatic
  allowedUses:
    - LoadBalancer

ここでは assignmentMode: Automatic を例にしています。この設定でも、Service 側のアノテーションによって特定の固定 VIP を要求できます。すべての VIP を明示的に管理したい場合は、自動割り当ての範囲や運用ルールを別途決める必要があります。

BGPConfiguration を serviceLoadBalancerIPs へ移す

現在 serviceExternalIPs で広告していた VIP レンジは、LoadBalancer Service へ移行後、serviceLoadBalancerIPs で広告します。

apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  serviceLoadBalancerIPs:
    - cidr: 10.253.0.0/24

両者の違いは、Calico が広告対象を取得する場所です。外部ルーターとの BGP ピアリングや、VIP 宛て経路を外部へ広告する設計自体は変わりません。

Calico 設定広告対象
serviceExternalIPsService.spec.externalIPs
serviceLoadBalancerIPsService.status.loadBalancer.ingress に登録された IP

固定 VIP を指定する

現在の externalIPs では、Service マニフェストに固定 VIP を直接記述します。Calico LoadBalancer IPAM でも、アノテーションを使って特定の IP アドレスを要求できます。

apiVersion: v1
kind: Service
metadata:
  name: example-service
  annotations:
    projectcalico.org/loadBalancerIPs: '["10.253.0.10"]'
spec:
  type: LoadBalancer
  loadBalancerClass: calico
  selector:
    app: example
  ports:
    - port: 80
      targetPort: 8080

projectcalico.org/loadBalancerIPs アノテーションを使用すると、Calico kube-controllers は指定された IP アドレスを Service へ割り当てます。割り当て後の Service には、次のようなステータスが設定されます。

status:
  loadBalancer:
    ingress:
      - ip: 10.253.0.10

指定した IP アドレスが利用できない場合、Calico はそのアドレスを割り当てません。固定 VIP として運用する場合、この動作は重要です。意図した VIP が使えないにもかかわらず、別の VIP で公開されることを避けられます。

Calico にだけ割り当てさせる

他の LoadBalancer Controller と競合する可能性がある環境では、Calico が明示的に要求された Service だけを扱うようにします。Calico kube-controllers の LoadBalancer Controller では、RequestedServicesOnly を使う設計が考えられます。

apiVersion: projectcalico.org/v3
kind: KubeControllersConfiguration
metadata:
  name: default
spec:
  controllers:
    loadBalancer:
      assignIPs: RequestedServicesOnly

この場合、Calico の IP 割り当てアノテーションや spec.loadBalancerClass: calico によって、Calico が扱う Service を明示できます。複数の Controller が存在する環境では、どの Controller がどの Service を管理するのかを曖昧にしないことが重要です。

externalTrafficPolicy と DSR は別の設計論点である

externalIPs から LoadBalancer Service への移行と、externalTrafficPolicy や DSR の選択は分けて考える必要があります。Calico の BGP Service 広告では、externalTrafficPolicy: ClusterLocal によって、広告するノード、ノード間転送、送信元 IP アドレスの扱いが変わります。

ただし、Calico eBPF データプレーンは kube-proxy とは異なる Service 実装を持ちます。また、Calico eBPF の外部 Service 転送には Tunnel と DSR のモードがあり、DSR はデフォルトでは無効です。使用するには Felix の bpfExternalServiceModeDSR に設定します。

そのため、「Cluster では必ず送信元 IP が失われる」「Local でなければ送信元 IP を維持できない」「LoadBalancer Service にすれば DSR になる」といった単純化は避けるべきです。実際の動作は、externalTrafficPolicy、Calico BGP の広告動作、Endpoint の配置、Calico eBPF の外部 Service 転送モード、上位ルーターの ECMP、ノード間転送経路の組み合わせで決まります。

移行時に確認する項目

実際の移行では、マニフェストを書き換えるだけでなく、VIP の割り当て、BGP 広告、実通信、障害時の収束まで確認します。

確認項目確認内容
LoadBalancer 用 IPPool10.253.0.0/24 が LoadBalancer 用途として登録されているか
LoadBalancer ControllerCalico kube-controllers が想定どおり Service を扱うか
Service の VIP 割り当てstatus.loadBalancer.ingress に意図した VIP が入るか
BGPConfigurationserviceLoadBalancerIPs に VIP レンジが設定されているか
上位ルーターの経路Service VIP への経路が Calico ノードから広告されているか
実通信外部ネットワークから VIP へ接続し、Pod まで到達できるか
障害時の動作Pod、ノード、BGP 経路変化時に期待どおり収束するか

あわせて、送信元 IP アドレス、応答経路、Endpoint のないノードへ着信した場合の動作、Calico NetworkPolicy の適用位置も確認します。VIP の持ち方を変えるだけに見えても、外部公開経路としてはルーティング、Service 転送、ポリシー、障害時挙動がつながっています。

まとめ

Kubernetes 1.36 で非推奨になったのは、Service の spec.externalIPs です。Calico BGP、Calico eBPF、BGP による Service VIP 公開設計そのものが非推奨になったわけではありません。

現在の構成が Service.spec.externalIPs、Calico serviceExternalIPs、Calico BGP、Calico eBPF の組み合わせであれば、移行後は LoadBalancer Service、Calico LoadBalancer IPAM、Calico serviceLoadBalancerIPs、Calico BGP、Calico eBPF の組み合わせに置き換えます。

変わるのは、VIP の指定方法と管理元です。Calico LoadBalancer IPAM では固定 VIP を指定できるため、現在使用している VIP レンジや個別 VIP を維持したまま移行できる可能性があります。この移行は外部公開方式を根本的に作り直す話ではなく、非推奨になる Kubernetes API フィールドを、LoadBalancer Service と Calico の IPAM / BGP 広告へ移す設計です。

参考書籍

参考
書籍
参考書籍

Kubernetes 完全ガイド 第 2 版

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

Amazon で見る

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

参考資料

関連する記事

Kubernetes Service と BGP の関連記事
Kubernetes の externalIPs 非推奨化を Calico BGP + eBPF 環境でどう考えるか

コメントを残す

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

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

トップへ戻る