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 転送に関与する構成です。
| 項目 | 前提例 |
|---|---|
| Kubernetes | 1.35 から 1.36 以降への移行を見据える |
| Calico | 3.31 系を想定 |
| Service VIP 広告 | Calico BGP |
| Service 転送 | Calico eBPF データプレーン |
| Service 公開用 VIP | 10.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/24Service 側では、公開したい VIP を spec.externalIPs に指定します。
apiVersion: v1
kind: Service
metadata:
name: example-service
spec:
selector:
app: example
ports:
- port: 80
targetPort: 8080
externalIPs:
- 10.253.0.10Kubernetes 自身は、externalIPs に指定された IP アドレスをノードへ割り当てたり、その IP アドレスへの経路を外部ネットワークへ作成したりしません。外部からその VIP 宛ての通信が Kubernetes ノードへ到達するようにする責任は、利用者側にあります。
この前提例では、その到達性を Calico BGP によって実現しています。Service の externalIPs が serviceExternalIPs の CIDR に含まれる場合、Calico が VIP への経路を BGP で外部へ広告します。その後、ノードへ到着した Service 宛て通信は Calico eBPF によってバックエンド Pod へ転送されます。
BGP 広告と Service 転送は別の機能である
この構成では、Calico が二つの異なる役割を担当しています。どちらも Calico が関係するため一体に見えますが、設計上は分けて考える必要があります。
| 処理 | 担当 | 役割 |
|---|---|---|
| VIP への経路を外部へ知らせる | Calico BGP | 外部ルーターから Kubernetes ノードへ到達させる |
| ノードへ到着した VIP 宛て通信を Pod へ転送する | Calico eBPF | kube-proxy の代わりに Service 処理を行う |
| 現在の VIP 指定 | Kubernetes spec.externalIPs | Service が受け付ける外部 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.10externalIPs は、Service を操作できる利用者が任意の IP アドレスを指定できる構造を持ちます。この性質は、割り当てられていない IP アドレスの横取りや意図しない通信誘導につながる可能性があり、Kubernetes の CVE-2020-8554 とも関係します。
ここで重要なのは、「External IP」という用語全体が非推奨になったわけではないことです。今回の対象は、あくまで Service.spec.externalIPs です。
| 対象 | 今回の非推奨化との関係 |
|---|---|
Service.spec.externalIPs | Kubernetes 1.36 で非推奨 |
Node の status.addresses にある ExternalIP | 別の概念 |
kubectl get service の EXTERNAL-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.externalIPs | Kubernetes 1.36 で非推奨 |
Calico serviceExternalIPs | Calico の 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.externalIPs | Service type: LoadBalancer |
Calico serviceExternalIPs | Calico 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 設定 | 広告対象 |
|---|---|
serviceExternalIPs | Service.spec.externalIPs |
serviceLoadBalancerIPs | Service.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: 8080projectcalico.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: Cluster と Local によって、広告するノード、ノード間転送、送信元 IP アドレスの扱いが変わります。
ただし、Calico eBPF データプレーンは kube-proxy とは異なる Service 実装を持ちます。また、Calico eBPF の外部 Service 転送には Tunnel と DSR のモードがあり、DSR はデフォルトでは無効です。使用するには Felix の bpfExternalServiceMode を DSR に設定します。
そのため、「Cluster では必ず送信元 IP が失われる」「Local でなければ送信元 IP を維持できない」「LoadBalancer Service にすれば DSR になる」といった単純化は避けるべきです。実際の動作は、externalTrafficPolicy、Calico BGP の広告動作、Endpoint の配置、Calico eBPF の外部 Service 転送モード、上位ルーターの ECMP、ノード間転送経路の組み合わせで決まります。
移行時に確認する項目
実際の移行では、マニフェストを書き換えるだけでなく、VIP の割り当て、BGP 広告、実通信、障害時の収束まで確認します。
| 確認項目 | 確認内容 |
|---|---|
| LoadBalancer 用 IPPool | 10.253.0.0/24 が LoadBalancer 用途として登録されているか |
| LoadBalancer Controller | Calico kube-controllers が想定どおり Service を扱うか |
| Service の VIP 割り当て | status.loadBalancer.ingress に意図した VIP が入るか |
| BGPConfiguration | serviceLoadBalancerIPs に 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 Documentation: Service
- Calico documentation: Advertise Kubernetes service IP addresses
- Calico documentation: LoadBalancer IP address management
- Calico documentation: Enable the eBPF dataplane


