- Kubernetes に LoadBalancer はないのか – Service、MetalLB、CNI BGP を分けて考える
LoadBalancer Service、MetalLB、CNI、BGP の責務を分けて確認した記事です。 - Kubernetes MetalLB の導入 – LoadBalancer Service をオンプレ環境で成立させる
オンプレミス環境で LoadBalancer Service を成立させる実装面の記事です。 - Kubernetes Calico eBPF の設計メモ – kube-proxy 代替、DualStack、高可用性をどう見るか
CNI、Service 処理、eBPF データプレーンを確認した記事です。
Kubernetes では、Service やロードバランサーを経由した通信で、アプリケーションから見える送信元アドレスが変わることがあります。
これは単純な設定ミスとは限りません。Kubernetes は、Pod がどの Node にいても Service 経由で到達できるように抽象化します。その過程で、Node 間転送、SNAT、Service のデータプレーン処理が入り、アプリケーションから見える送信元 IP が実クライアントではなくなることがあります。
ログ、アクセス制御、監査、WAF、ミドルウェアの接続元制御を送信元 IP に依存している場合、この挙動は問題になります。
この記事では、Kubernetes で送信元アドレスが変わる問題を、externalTrafficPolicy、hostNetwork、BGP 経路広告、Service のデータプレーンに分けて確認します。
この記事は Kubernetes の外部公開設計を扱います。実際の挙動は kube-proxy、eBPF データプレーン、CNI、MetalLB、クラウドロードバランサー、Kubernetes バージョンによって変わるため、導入時点の公式ドキュメントと実環境で確認してください。
送信元アドレスが問題になる場面
送信元 IP が変わっても、単に Web ページを表示するだけなら問題にならないこともあります。しかし、システム運用では送信元 IP に意味を持たせている場面が少なくありません。
| アクセスログ | 実クライアント IP を記録したい。Node IP やロードバランサー IP だけでは追跡しにくい。 |
|---|---|
| アクセス制御 | 送信元 IP によって許可、拒否、制限を行っている。 |
| 監査 | 誰がどこからアクセスしたかを後から説明する必要がある。 |
| WAF / セキュリティ製品 | 送信元 IP をもとにレート制限、ブロック、検知を行う。 |
| ミドルウェア | LDAP、DNS、プロキシ、DB などで接続元に応じた制御をしている。 |
Kubernetes の Service は便利ですが、その便利さは通信経路を抽象化することで成立しています。抽象化によって、アプリケーションから見える通信元が、実際のクライアントではなく Node やロードバランサーに変わることがあります。
なぜ送信元アドレスが変わるのか
送信元アドレスが変わる理由を一つにまとめてしまうと、切り分けが難しくなります。実際には、いくつかの層でアドレスが変わる可能性があります。
| 外部ロードバランサー | ロードバランサーがプロキシとして動作し、送信元がロードバランサーの IP に見える場合がある。 |
|---|---|
| NodePort / LoadBalancer Service | 外部通信を Node で受け、Service 経由で Pod へ転送する過程で SNAT が入る場合がある。 |
| Node 間転送 | 通信を受けた Node と Pod がいる Node が違う場合、Node 間転送が発生する。 |
| kube-proxy / eBPF | Service のデータプレーン実装によって、転送や NAT の挙動が変わる。 |
| Ingress / API Gateway | Nginx、Kong、Ingress Controller などが HTTP ヘッダーで実クライアント IP を伝える設計になる場合がある。 |
つまり、送信元 IP の問題は「Kubernetes の設定」だけではありません。外部ロードバランサー、Service、Node、CNI、Ingress、アプリケーションがまたがる問題です。
どの層で送信元が変わっているのかを分ける
アプリケーションログだけを見るのではなく、ロードバランサー、Node、Service、Pod、Ingress のどこで送信元が変わるのかを確認する必要があります。
externalTrafficPolicy: Local で何が変わるのか
externalTrafficPolicy: Local は、LoadBalancer Service や NodePort Service で外部通信を受けるときに、送信元 IP を保持したい場合の代表的な設定です。
apiVersion: v1
kind: Service
metadata:
name: example
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app: example
ports:
- name: http
port: 80
targetPort: 80externalTrafficPolicy: Cluster の場合、Service はクラスタ内のどの Node にいる Pod へも転送できます。柔軟ですが、Node 間転送や SNAT によって送信元 IP が変わることがあります。
externalTrafficPolicy: Local の場合、外部通信を受けた Node 上に存在する Pod だけへ転送します。そのため、Node 間転送を避けやすく、送信元 IP を保持しやすくなります。
| Cluster | クラスタ全体の Pod へ転送できる。柔軟だが、SNAT により送信元 IP が変わることがある。 |
|---|---|
| Local | 通信を受けた Node 上の Pod にだけ転送する。送信元 IP を保持しやすいが、Pod 配置とヘルスチェックが重要になる。 |
ただし、Local は万能ではありません。トラフィックを受けた Node 上に対象 Pod が存在しない場合、その Node では転送できません。つまり、送信元 IP を保持する代わりに、Pod 配置、Node 選択、ロードバランサーのヘルスチェックが重要になります。
hostNetwork は Kubernetes の抽象を一部外す設計である
hostNetwork を使うと、Pod は Node のネットワーク名前空間を使います。
通常の Pod は CNI によって Pod 用のネットワークを持ちますが、hostNetwork の Pod は Node の IP とポートを直接使います。そのため、通信経路は分かりやすくなります。
| 利点 | CNI や Service の抽象を一部避けられるため、通信経路が単純になりやすい。 |
|---|---|
| 利点 | 外部ロードバランサーから Node IP とポートへ直接振り分ける設計にしやすい。 |
| 制約 | Node 上のポート競合を考える必要がある。 |
| 制約 | Pod の配置自由度が下がり、Kubernetes の Service 抽象から少し外れる。 |
| 制約 | NetworkPolicy や CNI 側の制御が期待どおり効くかを確認する必要がある。 |
hostNetwork は、Kubernetes らしさを一部捨てる代わりに、ネットワークとしての素直さを取る設計です。性能やトラブルシュートの観点では魅力がありますが、柔軟性は下がります。
そのため、単に送信元 IP を残したいから hostNetwork にする、というより、外部ロードバランサー、Node 配置、ポート管理、セキュリティ境界まで含めて判断する必要があります。
BGP 経路広告は到達性を作る手段である
Calico や MetalLB の BGP を使うと、Kubernetes 内の Pod や Service への経路を外部ネットワークへ広告できます。
これは、Kubernetes を既存ネットワークにより自然に接続するための設計です。ただし、BGP は送信元 IP を保持する魔法ではありません。
BGP が担当するのは、外部ネットワークに対して「この宛先にはこの Node 経由で到達できる」と知らせることです。実際に Pod へどう転送するか、SNAT が入るか、Service のデータプレーンがどう処理するかは、別の層で決まります。
| MetalLB BGP | LoadBalancer IP への経路を外部ルーターへ広告する。 |
|---|---|
| CNI BGP | Pod CIDR や Service 関連の経路を外部ネットワークへ広告する構成がある。 |
| 外部ルーター | 受け取った経路をもとに、どの Node へ転送するかを決める。 |
| Service データプレーン | Node に入った通信を、どの Pod へ転送するかを処理する。 |
BGP を使う場合、Kubernetes は閉じた内部ネットワークではなく、外部ルーティングと接続されたネットワークになります。これは強力ですが、Pod CIDR、Service CIDR、LoadBalancer IP、経路集約、経路フィルタ、障害時の withdraw まで含めて設計する必要があります。
IPv4 と IPv6 では設計のしやすさが違う
送信元 IP や経路広告の問題は、IPv4 と IPv6 でも見え方が変わります。
IPv4 ではアドレス空間が狭く、既存ネットワークとの重複や NAT の利用が問題になりやすいです。Pod CIDR や Service CIDR を外部へ出す設計は、アドレス計画と経路集約を慎重に考える必要があります。
一方で IPv6 では、十分なアドレス空間を前提に設計しやすくなります。Pod や Service を外部ルーティングとどう接続するかという意味では、IPv6 の方が Kubernetes と相性が良い面があります。
ただし、IPv6 だから自動的に簡単になるわけではありません。ルーター、Firewall、CNI、Service、アプリケーションが IPv6 を前提に正しく設計されている必要があります。
どの案を選ぶべきか
送信元アドレスをどう扱うかは、何を守りたいかで変わります。
| externalTrafficPolicy: Local | Kubernetes Service の枠内で送信元 IP を保持したい場合に使う。Pod 配置とヘルスチェックが重要。 |
|---|---|
| hostNetwork | ネットワークを単純にし、外部ロードバランサーや Node 単位の制御を重視する場合に使う。 |
| BGP 経路広告 | Kubernetes ネットワークを外部ルーティングへ統合したい場合に使う。 |
| SNAT を許容する | アプリケーション側で送信元 IP を重要視しない場合は、抽象化を優先できる。 |
| HTTP ヘッダーで渡す | Ingress や API Gateway が X-Forwarded-For などで実クライアント IP を伝える設計にする。 |
どれが常に正解という話ではありません。送信元 IP を保持するほど、Kubernetes の柔軟な抽象化は一部制約されます。一方で、抽象化を優先するほど、ネットワークとしての見通しや監査性が下がることがあります。
送信元 IP を保持する設計は、自由度と引き換えになる
実クライアント IP を残したいなら、Node 選択、Pod 配置、外部ロードバランサー、ヘルスチェック、経路広告を合わせて設計する必要があります。
確認するポイント
送信元アドレスの問題を確認するときは、Kubernetes リソースだけでなく、実際にアプリケーションが見ている送信元 IP まで確認します。
kubectl get svc -A -o wide
kubectl get endpoints -A
kubectl get pods -A -o wide
kubectl get nodes -o wide| Service | type、externalTrafficPolicy、外部 IP、NodePort を確認する。 |
|---|---|
| Endpoint | 対象 Pod がどの Node にいるかを確認する。 |
| Pod | Pod の Node 配置、hostNetwork の有無、アプリケーションログを確認する。 |
| Node | 外部通信を受けている Node と Pod がいる Node が一致しているかを見る。 |
| 外部 LB / ルーター | どの Node に転送しているか、ヘルスチェックや BGP 経路がどう見えているかを確認する。 |
最終的には、テスト用の HTTP サーバーやアプリケーションログで、実際に見えている送信元 IP を確認します。Kubernetes のリソース状態が正しそうに見えても、アプリケーションが見ている送信元が期待どおりとは限りません。
書籍
Kubernetes 完全ガイド 第 2 版
Kubernetes の Service、ネットワーク、CNI、運用観点を体系的に確認したい場合の参考書籍です。価格や在庫はリンク先で確認してください。
Amazon で見るこのリンクは Amazon アソシエイトリンクです。
まとめ
Kubernetes の送信元アドレス問題は、単なる設定ミスではなく、Kubernetes の抽象化とネットワーク設計の衝突です。
Service による柔軟な転送を取るのか、送信元 IP の保持を優先するのか、外部ロードバランサーや BGP と統合するのかを設計として決める必要があります。
externalTrafficPolicy: Local、hostNetwork、BGP 経路広告はいずれも有効な選択肢ですが、得るものと失うものが違います。
ログ、アクセス制御、監査、アドレス設計を含めて、Kubernetes の外側にあるネットワークとどう接続するかを考えるべきです。
参考情報
- Kubernetes Documentation – Using Source IP
- Kubernetes Documentation – Service Traffic Policy
- MetalLB Documentation – BGP mode
- Kubernetes に LoadBalancer はないのか – Service、MetalLB、CNI BGP を分けて考える
Service、MetalLB、CNI BGP の責務を分けて確認します。 - Kubernetes MetalLB の導入 – LoadBalancer Service をオンプレ環境で成立させる
LoadBalancer Service と MetalLB の基本を確認します。 - Kubernetes Calico eBPF の設計メモ – kube-proxy 代替、DualStack、高可用性をどう見るか
CNI、kube-proxy 代替、DualStack を設計目線で確認します。 - MicroK8s MetalLB speaker が socket permission denied を出す原因 – L2 / 権限 / ホストネットワークを切り分ける
MetalLB speaker がホストネットワーク側で何をしているのかを確認します。 - Kubernetes 運用設計ガイド
Kubernetes 系記事の全体導線に戻ります。

