手当たり次第に書くんだ

飽きっぽいのは本能

Kubernetes で送信元アドレスが変わる問題 – externalTrafficPolicy、hostNetwork、BGP 経路広告で考える

Kubernetes では、Service やロードバランサーを経由した通信で送信元アドレスが変わることがあります。これは Kubernetes の抽象化としては自然な挙動ですが、ログ、アクセス制御、監査、ミドルウェア側の制御を送信元 IP に依存している場合は問題になります。

この記事では、送信元アドレスが変わる問題を、externalTrafficPolicy: LocalhostNetwork、Calico / MetalLB の BGP 経路広告という観点で整理します。ポイントは、Kubernetes の柔軟性と、ネットワークとしての素直さをどこで折り合いを付けるかです。

送信元アドレスが問題になる場面

  • アプリケーションログで実クライアント IP を見たい
  • Web サーバーや WAF で送信元 IP による制御をしたい
  • LDAP、DNS、プロキシなどで接続元に応じた制御をしている
  • 監査ログで通信元を追跡したい
  • ネットワーク側の ACL と Kubernetes 側の抽象化がずれる

Kubernetes は Pod をどのノードに配置しても Service 経由で到達できるようにします。その便利さの裏側で、ノード間転送や SNAT が入り、アプリケーションから見える送信元が実クライアントではなくなることがあります。

externalTrafficPolicy: Local

externalTrafficPolicy: Local は、LoadBalancer や NodePort で外部通信を受けるときに、送信元アドレスを保持したい場合の代表的な設定です。

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

ただし、Local は万能ではありません。トラフィックを受けたノード上に対象 Pod が存在しない場合、そのノードでは転送できません。そのため、ロードバランサーや MetalLB 側のノード選択、Pod 配置、ヘルスチェックの設計が重要になります。

hostNetwork を使う考え方

hostNetwork を使うと、Pod はノードのネットワーク名前空間を使います。CNI を経由しないため、送信元アドレスや通信経路はかなり素直になります。

  • CNI を経由しないため通信経路が単純になる
  • ノード IP とポートで公開する形になる
  • 外部ロードバランサーとの相性が良い
  • Kubernetes の Service 抽象化からは少し外れる
  • ポート競合やノード配置の制約が出る

これは Kubernetes らしさを一部捨てる代わりに、ネットワークとしての分かりやすさを取る設計です。性能やトラブルシュートの観点では魅力がありますが、柔軟性は下がります。

BGP で Pod / Service 経路を広告する

Calico や MetalLB の BGP を使うと、Kubernetes 内の Pod や Service への経路を外部ネットワークへ広告する設計ができます。これは Kubernetes を既存ネットワークにより自然に接続する方法です。

BGP を使う場合、Kubernetes は閉じた内部ネットワークではなく、外部ルーティングと接続されたネットワークになります。これは強力ですが、Pod CIDR、Service CIDR、経路集約、重複しないアドレス設計が重要になります。

kubectl get svc -A
kubectl get endpoints -A
kubectl get nodes -o wide

IPv4 と IPv6 で難しさが違う

IPv4 ではアドレス空間が狭いため、Pod CIDR を外部へ出す設計は悩ましくなりがちです。既存ネットワークとの重複、経路集約、アドレス消費を考える必要があります。

一方で IPv6 では、十分なアドレス空間を前提に設計しやすくなります。Pod や Service を外部ルーティングとどう接続するかという意味では、IPv6 の方が Kubernetes と相性が良い面があります。

どの案を選ぶべきか

  • externalTrafficPolicy: Local: Kubernetes Service の枠内で送信元を保持したい場合
  • hostNetwork: ネットワークを単純にし、外部 LB に分散を任せたい場合
  • BGP 経路広告: Kubernetes ネットワークを外部ルーティングへ統合したい場合
  • SNAT を許容する: アプリケーション側で送信元 IP を重要視しない場合

どれが正解というより、何を守りたいかで選択が変わります。送信元 IP を保持するほど、Kubernetes の柔軟な抽象化は一部制約されます。一方、抽象化を優先するほど、ネットワークとしての見通しは悪くなることがあります。

確認するポイント

kubectl get svc -A -o wide
kubectl get endpoints -A
kubectl get pods -A -o wide
kubectl get nodes -o wide

外部からアクセスしたときに、アプリケーションログ上で送信元がどう見えるかも確認します。Kubernetes のリソース状態だけではなく、実際にアプリケーションが見ている送信元 IP を確認することが重要です。

まとめ

Kubernetes の送信元アドレス問題は、単なる設定ミスではなく、Kubernetes の抽象化とネットワーク設計の衝突です。Service による柔軟な転送を取るのか、送信元 IP の保持を優先するのか、外部 LB や BGP と統合するのかを設計として決める必要があります。

externalTrafficPolicy: LocalhostNetwork、BGP 経路広告はいずれも有効な選択肢ですが、得るものと失うものが違います。ログ、アクセス制御、監査、アドレス設計を含めて、Kubernetes の外側にあるネットワークとどう接続するかを考えるべきです。

参考
書籍
参考書籍

Kubernetes完全ガイド 第2版

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

Amazon で見る

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

関連記事

Kubernetes で送信元アドレスが変わる問題 – externalTrafficPolicy、hostNetwork、BGP 経路広告で考える

コメントを残す

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

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

トップへ戻る