目次(もくじ)
1. Kubernetesネットワーキングモデルの基本原則(きほんげんそく)
Kubernetesネットワーキングは三つの基本原則の上に構築されています。
1.1 コア要件(ようけん)
- すべてのPodは固有(こゆう)のIPアドレスを持つ - NATなしで互いに通信可能
- すべてのPodは他のすべてのPodに到達(とうたつ)できる - 同じノードでも異なるノードでも
- Podが見る自分のIPと他のPodが見るIPが同一 - NATなし
┌────────────────────────────────────────────────────┐
│ Kubernetesネットワーキング基本原則 │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Node 1 │ │ Node 2 │ │
│ │ │ │ │ │
│ │ ┌──────┐ │ NATなし! │ ┌──────┐ │ │
│ │ │Pod A │◄├───────────►┤│Pod C │ │ │
│ │ │10.1.1│ │ │ │10.1.2│ │ │
│ │ └──────┘ │ │ └──────┘ │ │
│ │ ┌──────┐ │ │ ┌──────┐ │ │
│ │ │Pod B │ │ │ │Pod D │ │ │
│ │ │10.1.1│ │ │ │10.1.2│ │ │
│ │ └──────┘ │ │ └──────┘ │ │
│ └──────────┘ └──────────┘ │
│ │
│ Pod A(10.1.1.2) → Pod C(10.1.2.3): 直接通信 │
│ NAT、ポートマッピングなし。各Podは固有IP所有 │
└────────────────────────────────────────────────────┘
1.2 ネットワーキング階層構造(かいそうこうぞう)
┌──────────────────────────────────────────┐
│ Kubernetesネットワーキング階層 │
├──────────────────────────────────────────┤
│ L7: Ingress / Gateway API │
│ (HTTPルーティング、TLS終端) │
├──────────────────────────────────────────┤
│ L4: Service │
│ (ClusterIP, NodePort, LoadBalancer) │
├──────────────────────────────────────────┤
│ L3: Podネットワーキング (CNI) │
│ (Pod-to-Pod、オーバーレイ/アンダーレイ)│
├──────────────────────────────────────────┤
│ L2-L3: ノードネットワーキング │
│ (物理/仮想ネットワーク) │
└──────────────────────────────────────────┘
2. Pod-to-Podネットワーキング:内部動作原理
2.1 同一ノード内のPod通信
┌────────────────────────────────────────────┐
│ Node │
│ │
│ ┌──────┐ veth pair ┌──────────┐ │
│ │Pod A │◄──────────────►│ │ │
│ │eth0 │ │ cbr0 │ │
│ │ │ │ (bridge) │ │
│ └──────┘ │ │ │
│ │ │ │
│ ┌──────┐ veth pair │ │ │
│ │Pod B │◄──────────────►│ │ │
│ │eth0 │ └──────────┘ │
│ └──────┘ │
│ │
│ 1. Pod AがPod Bにパケット送信 │
│ 2. veth pair経由でブリッジ(cbr0)に転送 │
│ 3. ブリッジがMAC宛先のvethを検索 │
│ 4. Pod Bのveth pair経由でPod Bに転送 │
└────────────────────────────────────────────┘
veth pair:一端はPodネームスペースのeth0、もう一端はノードのブリッジに接続された仮想イーサネットペアです。
2.2 異(こと)なるノードのPod通信(オーバーレイ)
┌──────────┐ ┌──────────┐
│ Node 1 │ │ Node 2 │
│ │ │ │
│ ┌──────┐ │ VXLAN/IPinIP │ ┌──────┐ │
│ │Pod A │ │ ┌───────────┐ │ │Pod C │ │
│ │10.1.1│ │───►│トンネリング│────►│ │10.1.2│ │
│ └──────┘ │ │ │ │ └──────┘ │
│ │ │元パケットを │ │ │
│ cbr0 │ │外部パケット│ │ cbr0 │
│ 10.1.1.0 │ │にカプセル化│ │ 10.1.2.0 │
│ │ └───────────┘ │ │
│ eth0 │ │ eth0 │
│192.168.1│ │192.168.2│
└──────────┘ └──────────┘
VXLANカプセル化:
┌─────────────────────────────────────────┐
│外部IP │ UDP │ VXLAN │内部IP │ Payload │
│ Hdr │ Hdr │ Hdr │ Hdr │ │
│192→192│ │ │10→10 │ Data │
└─────────────────────────────────────────┘
2.3 オーバーレイ vs アンダーレイ ネットワーキング
| 特性 | オーバーレイ (VXLAN/IPinIP) | アンダーレイ (BGP/Direct) |
|---|---|---|
| 設定難易度 | 簡単 | 困難 |
| ネットワーク要件 | L3接続のみ必要 | BGPサポート必要 |
| 性能オーバーヘッド | あり(カプセル化) | なし |
| MTU影響 | 減少(50-54バイト) | なし |
| デバッグ | 困難 | 容易 |
| 使用場面 | クラウド、マルチテナント | ベアメタル、高性能 |
3. CNIプラグイン詳細比較
3.1 CNIとは何(なに)か
CNI(Container Network Interface)はコンテナランタイムがネットワークプラグインと相互作用する標準インターフェースです。
Pod生成時のCNI動作フロー:
1. kubeletがCRI経由でコンテナ生成をリクエスト
2. コンテナランタイムがネットワークネームスペースを生成
3. kubeletがCNIプラグインを呼び出し(ADDコマンド)
4. CNIプラグインが:
a. veth pairを生成
b. PodにIPアドレスを割り当て(IPAM)
c. ルーティングルールを設定
d. 必要に応じてオーバーレイトンネルを設定
5. Podがネットワーク準備完了
3.2 主要CNIプラグイン比較
| 機能 | Calico | Cilium | Flannel | Weave Net |
|---|---|---|---|---|
| 開発元 | Tigera | Isovalent (Cisco) | CoreOS | Weaveworks |
| データプレーン | iptables/eBPF | eBPF | VXLAN | VXLAN/スリーブ |
| ネットワークモード | BGP/VXLAN/IPinIP | VXLAN/Native | VXLAN | VXLAN |
| Network Policy | 豊富(ほうふ) | 非常に豊富(L7) | なし | 基本的 |
| 暗号化(あんごうか) | WireGuard | WireGuard/IPsec | なし | IPsec |
| kube-proxy代替 | eBPFモード | ネイティブeBPF | 不可 | 不可 |
| 観測性 | 基本的 | Hubble(強力) | なし | Scope |
| サービスメッシュ | なし | 内蔵(オプション) | なし | なし |
| マルチクラスタ | サポート | ClusterMesh | 未サポート | サポート |
| 性能 | 高い(BGP) | 非常に高い(eBPF) | 中程度 | 低い |
| 複雑度(ふくざつど) | 中間 | 高い | 低い | 低い |
| 本番推奨 | 強く推奨 | 強く推奨 | 小規模のみ | 非推奨 |
3.3 Calico深堀り
# Calico BGPモード設定(IPPool)
apiVersion: crd.projectcalico.org/v1
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 10.244.0.0/16
encapsulation: None # BGP使用時はカプセル化なし
natOutgoing: true
nodeSelector: all()
blockSize: 26 # /26 = ノード当たり64 IP
---
# Calico BGP Peering設定
apiVersion: crd.projectcalico.org/v1
kind: BGPPeer
metadata:
name: rack-tor-switch
spec:
peerIP: 192.168.1.1
asNumber: 64512
nodeSelector: rack == "rack-1"
# Calico VXLANモード(クラウド環境)
apiVersion: crd.projectcalico.org/v1
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 10.244.0.0/16
encapsulation: VXLAN # VXLANカプセル化
natOutgoing: true
vxlanMode: Always
3.4 Cilium深堀り
# Cilium Helmインストール(kube-proxy代替モード)
# helm install cilium cilium/cilium --namespace kube-system \
# --set kubeProxyReplacement=true \
# --set k8sServiceHost=API_SERVER_IP \
# --set k8sServicePort=6443 \
# --set hubble.enabled=true \
# --set hubble.relay.enabled=true \
# --set hubble.ui.enabled=true \
# --set encryption.enabled=true \
# --set encryption.type=wireguard
# Ciliumステータス確認
# cilium status
# cilium connectivity test
# Cilium L7 Network Policy(HTTPベースポリシー)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l7-rule
namespace: default
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/.*"
- method: "POST"
path: "/api/v1/orders"
4. Service深堀り:ClusterIPからLoadBalancerまで
4.1 Serviceの動作原理
┌──────────────────────────────────────────────────┐
│ Serviceトラフィックフロー │
│ │
│ Client Pod ──► Service VIP ──► kube-proxy │
│ (10.96.0.10) /iptables/IPVS │
│ │ │
│ ┌────────┼────────┐ │
│ ▼ ▼ ▼ │
│ Pod A Pod B Pod C │
│ 10.1.1.2 10.1.1.3 10.1.2.4│
│ │
│ Service VIPは実際のインターフェースにバインドされない│
│ iptables/IPVSルールがDNATでPod IPに変換 │
└──────────────────────────────────────────────────┘
4.2 Serviceタイプ別詳細
# 1. ClusterIP(デフォルト)- クラスタ内部アクセスのみ
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ClusterIP
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
# クラスタIP: 自動割り当て(例: 10.96.0.10)
# クラスタ内部でのみ10.96.0.10:80でアクセス可能
# 2. NodePort - すべてのノードの固定ポートで外部アクセス
apiVersion: v1
kind: Service
metadata:
name: my-nodeport-service
spec:
type: NodePort
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
nodePort: 30080 # 30000-32767の範囲
# すべてのノードの30080ポートでアクセス可能
# NodeIP:30080 → ClusterIP:80 → Pod:8080
# 3. LoadBalancer - クラウドロードバランサ自動プロビジョニング
apiVersion: v1
kind: Service
metadata:
name: my-lb-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- port: 443
targetPort: 8443
# 外部LB IP → NodePort → ClusterIP → Pod
# 4. ExternalName - 外部DNSをクラスタ内サービスにマッピング
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: mydb.example.com
# external-db.default.svc.cluster.local → mydb.example.com
# 5. Headless Service - ClusterIPなしでPod IPを直接返却
apiVersion: v1
kind: Service
metadata:
name: my-headless-service
spec:
clusterIP: None # Headless宣言
selector:
app: my-stateful-app
ports:
- port: 5432
# DNSクエリ時にService IPではなく個別Pod IPを返却
# StatefulSetと共に使用: pod-0.my-headless-service.default.svc
5. kube-proxyモード:iptables vs IPVS vs eBPF
5.1 iptablesモード(デフォルト)
iptablesルールチェーン(Service当たり):
PREROUTING → KUBE-SERVICES → KUBE-SVC-XXXX → KUBE-SEP-YYYY
(確率的分配)
Serviceに3つのPodがある場合:
KUBE-SVC-XXXX:
-p tcp -d 10.96.0.10 --dport 80
→ 33%確率でKUBE-SEP-1 (DNAT → 10.1.1.2:8080)
→ 33%確率でKUBE-SEP-2 (DNAT → 10.1.1.3:8080)
→ 34%確率でKUBE-SEP-3 (DNAT → 10.1.2.4:8080)
問題点:
- Service/Pod数に比例してルール数増加 (O(n))
- ルール更新時に全チェーン再作成
- 10,000+のServiceで深刻な性能低下
5.2 IPVSモード
IPVS (IP Virtual Server):
┌───────────────────────────────────────────┐
│ IPVS Virtual Server: 10.96.0.10:80 │
│ │
│ Real Server 1: 10.1.1.2:8080 (weight 1)│
│ Real Server 2: 10.1.1.3:8080 (weight 1)│
│ Real Server 3: 10.1.2.4:8080 (weight 1)│
│ │
│ Algorithm: rr (Round Robin) │
│ 他のオプション: lc, dh, sh, sed, nq │
└───────────────────────────────────────────┘
利点:
- ハッシュテーブルベースO(1)検索
- 多様なロードバランシングアルゴリズム
- 大規模クラスタで安定した性能
- リアルタイム統計と接続追跡
5.3 eBPFモード (Cilium)
eBPF kube-proxy代替:
┌────────────────────────────────────────────┐
│ 従来: Pod → iptables/IPVS → Pod │
│ eBPF: Pod → BPFプログラム → Pod(直接!) │
│ │
│ ┌──────┐ BPF map ┌──────┐ │
│ │Pod A │──(Service ──│Pod B │ │
│ │ │ lookup) │ │ │
│ └──────┘ └──────┘ │
│ │
│ iptablesチェーン巡回なし! │
│ カーネル空間で直接パケットリダイレクト │
└────────────────────────────────────────────┘
| 比較項目 | iptables | IPVS | eBPF (Cilium) |
|---|---|---|---|
| 検索複雑度 | O(n) | O(1) | O(1) |
| ルール更新 | 全体再作成 | 増分更新 | 増分更新 |
| 負荷分散 | 確率的 | 多様なアルゴリズム | Maglevハッシュ |
| 接続追跡 | conntrack | conntrack | BPF conntrack |
| 性能 | 中程度 | 高い | 非常に高い |
| L7ポリシー | 不可 | 不可 | 可能 |
| 観測性 | 限定的 | 基本的 | Hubble(強力) |
| 10Kサービス | 非常に遅い | 高速 | 非常に高速 |
6. DNS:CoreDNSとサービスディスカバリ
6.1 CoreDNSアーキテクチャ
┌──────────────────────────────────────────────────┐
│ CoreDNS動作 │
│ │
│ Pod ──DNSクエリ──► CoreDNS Pod │
│ (nameserver (kube-system) │
│ 10.96.0.10) │
│ │ │
│ ┌──────────┼──────────┐ │
│ ▼ ▼ ▼ │
│ K8s API Corefile Upstream │
│ (サービス/Pod (プラグイン DNS │
│ レコード) 設定) (外部DNS) │
└──────────────────────────────────────────────────┘
6.2 DNSレコード形式
Service DNS:
my-service.my-namespace.svc.cluster.local
└ サービス名 ┘ └ネームスペース┘
Pod DNS:
10-1-1-2.my-namespace.pod.cluster.local
└IP(ドット→ダッシュ)┘
Headless ServiceのPod DNS (StatefulSet):
pod-0.my-headless.my-namespace.svc.cluster.local
└Pod名┘ └サービス名┘
SRVレコード:
_http._tcp.my-service.my-namespace.svc.cluster.local
→ ポート番号とホスト名を返却
6.3 ndots:5の問題と解決策
# ndots:5デフォルト設定の問題:
# "api.example.com"を検索する場合(ドットが5個未満):
# 1. api.example.com.default.svc.cluster.local(失敗)
# 2. api.example.com.svc.cluster.local(失敗)
# 3. api.example.com.cluster.local(失敗)
# 4. api.example.com(成功)
# → 外部DNS検索に不要な3回のクエリが発生!
# 解決方法1: Pod DNS設定のカスタマイズ
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
dnsConfig:
options:
- name: ndots
value: "2" # ndotsを2に削減
containers:
- name: app
image: my-app
# 解決方法2: FQDNで直接アクセス(末尾にドット)
# api.example.com. ← 末尾のドットがFQDNを意味
7. Ingress:HTTP/HTTPSルーティング
7.1 Ingressリソース例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls-secret
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
7.2 Ingressコントローラ比較
| 機能 | nginx-ingress | Traefik | HAProxy | Contour |
|---|---|---|---|---|
| 開発元 | Kubernetes/F5 | Traefik Labs | HAProxy Tech | VMware |
| プロトコル | HTTP/HTTPS/gRPC | HTTP/HTTPS/gRPC/TCP | HTTP/HTTPS/TCP | HTTP/HTTPS/gRPC |
| 設定リロード | 再起動必要 | ホットリロード | ホットリロード | ホットリロード |
| レート制限 | アノテーション | ミドルウェア | 内蔵 | 未サポート |
| 認証 | Basic/OAuth | Forward Auth | 内蔵 | 限定的 |
| 性能 | 高い | 中程度 | 非常に高い | 高い |
| Gateway API | サポート | サポート | 部分サポート | 完全サポート |
8. Gateway API:Ingressの進化(しんか)
8.1 なぜGateway APIなのか
Ingressの限界:
- アノテーションに依存した非標準設定
- L7 HTTPのみサポート(TCP/UDP/gRPC未サポート)
- 単一リソースで役割分離が困難
- トラフィック分割、ヘッダマッチングなどの高度な機能が欠如
8.2 Gateway APIリソース階層
┌──────────────────────────────────────────────────┐
│ Gateway APIリソース階層 │
│ │
│ インフラ管理者: │
│ ┌─────────────┐ │
│ │GatewayClass │ 使用するコントローラを指定 │
│ └──────┬──────┘ │
│ │ │
│ クラスタ運用者: │
│ ┌──────▼──────┐ │
│ │ Gateway │ リスナー(ポート、プロトコル、TLS)│
│ └──────┬──────┘ │
│ │ │
│ アプリケーション開発者: │
│ ┌──────▼──────┐ │
│ │ HTTPRoute │ ルーティングルール(ホスト、パス) │
│ │ TCPRoute │ │
│ │ GRPCRoute │ │
│ └─────────────┘ │
└──────────────────────────────────────────────────┘
8.3 Gateway API実践例
# 1. GatewayClass - インフラ管理者が定義
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: cilium
spec:
controllerName: io.cilium/gateway-controller
---
# 2. Gateway - クラスタ運用者が定義
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: gateway-infra
spec:
gatewayClassName: cilium
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: wildcard-tls
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
shared-gateway: "true"
---
# 3. HTTPRoute - 開発者が定義
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-routes
namespace: my-app
spec:
parentRefs:
- name: my-gateway
namespace: gateway-infra
hostnames:
- "app.example.com"
rules:
# ヘッダベースルーティング
- matches:
- headers:
- name: "X-Canary"
value: "true"
backendRefs:
- name: app-canary
port: 80
weight: 100
# トラフィック分割(カナリアデプロイ)
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: app-stable
port: 80
weight: 90
- name: app-canary
port: 80
weight: 10
# デフォルトルーティング
- backendRefs:
- name: app-stable
port: 80
8.4 Ingress vs Gateway API比較
| 機能 | Ingress | Gateway API |
|---|---|---|
| 役割分離 | 単一リソース | GatewayClass/Gateway/Route |
| プロトコル | HTTP/HTTPSのみ | HTTP/HTTPS/TCP/UDP/gRPC |
| トラフィック分割 | アノテーション(非標準) | ネイティブweight対応 |
| ヘッダマッチング | アノテーション(非標準) | 標準スペック |
| TLS設定 | 基本的 | きめ細かい制御 |
| クロスネームスペース | 困難 | ネイティブサポート |
| 拡張性 | アノテーションのみ | Policy API拡張 |
| ステータス | GA(安定) | GA(v1.0+、2023) |
9. Network Policy:マイクロセグメンテーション
9.1 基本概念
Network PolicyはPodレベルのファイアウォールです。選択されたPodに対するトラフィックを許可/遮断します。
重要:Network Policyがなければすべてのトラフィックが許可されます。Network Policyを1つでも適用すると、そのPodに対して明示的に許可されたトラフィックのみ通過します。
9.2 Default Denyポリシー
# ネームスペースのすべてのIngress遮断(デフォルト拒否)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {} # すべてのPodに適用
policyTypes:
- Ingress # Ingressのみ遮断(Egressは許可)
---
# ネームスペースのすべてのEgressも遮断
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
9.3 実践Network Policy例
# バックエンドPod: フロントエンドからのみアクセス許可
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
# 同じネームスペースのfrontend Podのみ許可
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress:
# DBアクセス許可
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
# DNS許可(必須!)
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
10. eBPFネットワーキング:iptablesを超(こ)えて
10.1 eBPFとは何か
eBPF(extended Berkeley Packet Filter)はカーネルを修正せずにカーネル空間でプログラムを実行できる技術です。
┌──────────────────────────────────────────────────┐
│ eBPFアーキテクチャ │
│ │
│ ユーザー空間 │
│ ┌──────────────────────────────────────────┐ │
│ │ Cilium Agent / hubble │ │
│ │ (eBPFプログラム管理、ポリシー適用) │ │
│ └──────────────┬───────────────────────────┘ │
│ │ BPF Syscall │
│ ───────────────┼────────────────────────────── │
│ カーネル空間 │ │
│ ┌──────────────▼───────────────────────────┐ │
│ │ BPFプログラム(検証後JITコンパイル) │ │
│ │ │ │
│ │ フックポイント: │ │
│ │ ┌─────┐ ┌──────┐ ┌────────┐ ┌──────┐ │ │
│ │ │ XDP │ │tc/cls│ │ socket │ │kprobe│ │ │
│ │ └─────┘ └──────┘ └────────┘ └──────┘ │ │
│ │ │ │
│ │ BPF Maps(プログラム間データ共有) │ │
│ │ ┌──────────────────────────────────┐ │ │
│ │ │ Service Map │ Endpoint Map │ CT │ │ │
│ │ └──────────────────────────────────┘ │ │
│ └──────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
10.2 eBPFがiptablesを置き換える理由
| 比較項目 | iptables | eBPF |
|---|---|---|
| 実行場所 | カーネルnetfilter | カーネル各種フックポイント |
| ルールマッチング | 線形探索 O(n) | ハッシュマップ O(1) |
| 更新 | 全チェーン再作成 | マップエントリのみ更新 |
| 観測性 | 限定的(カウンタのみ) | 豊富なメトリクス、イベント |
| L7処理 | 不可能 | 可能(HTTP、DNSなど) |
| 接続追跡 | conntrack(共有) | BPF自体のCT(効率的) |
| CPU使用量 | 高い(大規模時) | 低い |
| スケーラビリティ | 10Kサービスで低下 | 100K+サービスでも安定 |
10.3 Cilium Hubble:eBPFベースの観測性
# Hubble CLIでトラフィック監視
hubble observe --namespace production
# 特定Podのトラフィック確認
hubble observe --pod production/frontend-abc123
# DNSクエリ監視
hubble observe --protocol DNS
# 遮断されたトラフィック確認(Network Policy)
hubble observe --verdict DROPPED
# HTTPリクエスト監視(L7)
hubble observe --protocol HTTP --http-method GET
11. ネットワークデバッグ実践ガイド
11.1 tcpdumpによるパケットキャプチャ
# エフェメラルコンテナでtcpdump実行 (K8s 1.25+)
kubectl debug -it pod/my-app-xxx \
--image=nicolaka/netshoot \
--target=my-app-container \
-- tcpdump -i eth0 -nn port 8080
# 特定ホストとの通信キャプチャ
kubectl debug -it pod/my-app-xxx \
--image=nicolaka/netshoot \
--target=my-app-container \
-- tcpdump -i eth0 -nn host 10.1.2.3
# DNSクエリキャプチャ
kubectl debug -it pod/my-app-xxx \
--image=nicolaka/netshoot \
--target=my-app-container \
-- tcpdump -i eth0 -nn port 53
11.2 ネットワーク接続テスト
# netshoot Podで総合テスト
kubectl run netshoot --image=nicolaka/netshoot --rm -it -- bash
# TCP接続テスト
curl -v telnet://my-service:8080
# DNS解決確認
dig my-service.default.svc.cluster.local
dig +trace my-service.default.svc.cluster.local
# MTU確認
ping -M do -s 1472 target-pod-ip # 1472 + 28 = 1500
# ルーティングテーブル確認
ip route show
# ARPテーブル確認
ip neigh show
11.3 Network Policyトラブルシューティング
# 1. 現在適用されているNetwork Policy確認
kubectl get networkpolicy -A
# 2. 特定Podに適用されるポリシー確認
kubectl describe networkpolicy -n production
# 3. Ciliumの場合: エンドポイントポリシー状態
cilium endpoint list
cilium policy get
# 4. 接続テスト
kubectl exec -it frontend-pod -- curl -v http://backend-service:8080
# 5. DNS許可確認(Egress Policy時に必須)
kubectl exec -it my-pod -- nslookup kubernetes.default
# よくある間違い:
# - Egress PolicyでDNS(UDP/TCP 53)許可の漏れ
# - namespaceSelectorなしでpodSelectorのみ使用
# (他のネームスペースのPodにマッチしない)
# - policyTypesにEgressの記載漏れ(Egressルールがあっても無視される)
12. 性能チューニング
12.1 MTU最適化
MTUチェーン:
Pod (MTU) → オーバーレイ (VXLAN -50, IPinIP -20) → 物理NIC (MTU)
推奨設定:
- 物理NIC: ジャンボフレーム9000(可能な場合)
- VXLANオーバーレイ: 物理MTU - 50 = 8950
- IPinIPオーバーレイ: 物理MTU - 20 = 8980
- WireGuard暗号化: 物理MTU - 60 = 8940
デフォルト1500 NIC:
- VXLAN: 1500 - 50 = 1450
- IPinIP: 1500 - 20 = 1480
12.2 NodeLocal DNSCache
DNSクエリをノードローカルでキャッシュしてCoreDNSの負荷を削減します。
NodeLocal DNSCache動作:
Pod → 169.254.20.10 (NodeLocal) → CoreDNS(キャッシュミス時)
↓
ローカルキャッシュヒット時に即座に応答
効果:
- DNSレイテンシ50%以上削減
- CoreDNS負荷70-80%削減
- conntrack競合解消
- UDP DNSパケット損失防止
12.3 TCPチューニング
# ノードレベルのカーネルパラメータチューニング
# 接続追跡テーブルサイズ
net.netfilter.nf_conntrack_max = 1048576
# TCPバッファサイズ
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# TCP接続再利用
net.ipv4.tcp_tw_reuse = 1
# SYNバックログ
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# キープアライブ
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 10
13. マルチクラスタネットワーキング
13.1 Cilium ClusterMesh
┌──────────────┐ ┌──────────────┐
│ Cluster A │ │ Cluster B │
│ (us-east-1) │ │ (eu-west-1) │
│ │ │ │
│ ┌────────┐ │トンネル │ ┌────────┐ │
│ │Cilium │◄─┼─────────┼─►│Cilium │ │
│ │Agent │ │ │ │Agent │ │
│ └────────┘ │ │ └────────┘ │
│ │ │ │
│ Pod CIDR: │ │ Pod CIDR: │
│ 10.1.0.0/16 │ │ 10.2.0.0/16 │
│ │ │ │
│ Service: │ │ Service: │
│ shared-db │ Global │ shared-db │
│ (annotated) │Service │ (annotated) │
└──────────────┘ └──────────────┘
# Global Service設定(両方のクラスタで)
apiVersion: v1
kind: Service
metadata:
name: shared-database
annotations:
service.cilium.io/global: "true"
service.cilium.io/shared: "true"
spec:
selector:
app: postgres
ports:
- port: 5432
14. クイズ
Q1. Kubernetesですべてのポッドが固有IPを持ちNATなしで通信する理由は?
正解:Kubernetesネットワーキングモデルの三つの基本原則のためです:
- すべてのPodは固有のIPアドレスを持つ
- すべてのPodは他のすべてのPodにNATなしで到達できる
- Podが見る自分のIPと他のPodが見るIPが同一
このモデルはポートマッピングやNATの複雑さを排除し、サービスディスカバリとネットワークポリシーを単純化します。CNIプラグインがこの要件を実装します。
Q2. eBPFがiptablesよりKubernetesネットワーキングに適している理由は?
正解:iptablesはルールを線形に探索(O(n))し、ルール変更時に全チェーンを再作成する必要があります。10,000以上のServiceで深刻な性能低下が発生します。
eBPFは:
- ハッシュマップベースO(1)検索でService数に関係なく一定の性能
- マップエントリのみ更新でルール変更が高速
- L7ポリシー(HTTPメソッド/パス)をカーネルで直接処理
- Hubbleで豊富な観測性を提供
CiliumがeBPFを使用してkube-proxyを完全に代替します。
Q3. Gateway APIがIngressを代替するようになった核心的な理由は?
正解:Ingressの核心的な限界:
- 非標準アノテーションに依存しコントローラごとに設定が異なる
- HTTP/HTTPSのみサポートでTCP/UDP/gRPC不可
- 単一リソースでインフラ管理者、運用者、開発者間の役割分離が困難
- トラフィック分割、ヘッダマッチングなどの高度な機能が標準にない
Gateway APIはGatewayClass/Gateway/Routeの階層的リソースで役割を分離し、トラフィック分割、ヘッダマッチング、マルチプロトコルを標準スペックでサポートします。
Q4. Network PolicyでEgressルール設定時の最もよくある間違いは?
正解:DNS(UDP/TCPポート53)許可の漏れです。
Egress Policyを設定するとすべてのアウトバウンドトラフィックが遮断されます。DNSクエリも遮断されるためService名の解決が失敗します。必ずkube-dns(CoreDNS)PodへのUDP/TCP 53ポートEgressを許可する必要があります。
他のよくある間違い:
- policyTypesにEgress明示の漏れ
- namespaceSelectorなしで他のネームスペースのPodをマッチしようとする試み
- CIDRベースルールでPod CIDR範囲のエラー
Q5. ndots:5設定が外部DNS検索の性能を低下させる理由と解決策は?
正解:Kubernetesデフォルトのndots:5設定で「api.example.com」のようにドットが5個未満のドメインを検索すると、searchドメインを順番に追加して先に試行します:
- api.example.com.default.svc.cluster.local(失敗)
- api.example.com.svc.cluster.local(失敗)
- api.example.com.cluster.local(失敗)
- api.example.com(成功)
外部DNS1つを検索するのに不要な3回のクエリが発生します。
解決策:
- Pod dnsConfigでndotsを2に削減
- FQDN使用(末尾にドット追加:api.example.com.)
- NodeLocal DNSCacheでキャッシュ活用
- CoreDNS autopathプラグイン使用
15. 参考資料(さんこうしりょう)
- Kubernetes Networking Model - 公式ドキュメント
- Cilium Documentation - eBPFベースネットワーキング
- Calico Documentation - Project Calico
- Gateway API - 公式仕様
- CoreDNS - サービスディスカバリ用DNS
- Network Policies - Kubernetesドキュメント
- eBPF.io - eBPF入門
- Hubble - Kubernetes向けネットワーク観測性
- IPVSベースkube-proxy - Kubernetesブログ
- CNI Specification - Container Network Interface
- NodeLocal DNSCache - Kubernetesドキュメント
- Cilium ClusterMesh - マルチクラスタネットワーキング
- Life of a Packet in Kubernetes - カンファレンストーク
현재 단락 (1/717)
Kubernetesネットワーキングは三つの基本原則の上に構築されています。