Skip to content
Published on

Kubernetesネットワーキング深掘りガイド2025:CNI、Service、Ingress、DNS、Network Policy

Authors

目次(もくじ)

1. Kubernetesネットワーキングモデルの基本原則(きほんげんそく)

Kubernetesネットワーキングは三つの基本原則の上に構築されています。

1.1 コア要件(ようけん)

  1. すべてのPodは固有(こゆう)のIPアドレスを持つ - NATなしで互いに通信可能
  2. すべてのPodは他のすべてのPodに到達(とうたつ)できる - 同じノードでも異なるノードでも
  3. 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カプセル化:
┌─────────────────────────────────────────┐
│外部IPUDPVXLAN │内部IPPayloadHdrHdrHdrHdr   │         │
192192│     │       │1010Data└─────────────────────────────────────────┘

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プラグイン比較

機能CalicoCiliumFlannelWeave Net
開発元TigeraIsovalent (Cisco)CoreOSWeaveworks
データプレーンiptables/eBPFeBPFVXLANVXLAN/スリーブ
ネットワークモードBGP/VXLAN/IPinIPVXLAN/NativeVXLANVXLAN
Network Policy豊富(ほうふ)非常に豊富(L7)なし基本的
暗号化(あんごうか)WireGuardWireGuard/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 C10.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当たり):

PREROUTINGKUBE-SERVICESKUBE-SVC-XXXXKUBE-SEP-YYYY
                                             (確率的分配)

Serviceに3つのPodがある場合:
KUBE-SVC-XXXX:
  -p tcp -d 10.96.0.10 --dport 80
33%確率でKUBE-SEP-1 (DNAT10.1.1.2:8080)
33%確率でKUBE-SEP-2 (DNAT10.1.1.3:8080)
34%確率でKUBE-SEP-3 (DNAT10.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/IPVSPod│  eBPF: PodBPFプログラム → Pod(直接!)   │
│                                            │
│  ┌──────┐   BPF map    ┌──────┐           │
│  │Pod A │──(Service    ──│Pod B │           │
│  │      │   lookup)     │      │           │
│  └──────┘               └──────┘           │
│                                            │
│  iptablesチェーン巡回なし!│  カーネル空間で直接パケットリダイレクト        │
└────────────────────────────────────────────┘
比較項目iptablesIPVSeBPF (Cilium)
検索複雑度O(n)O(1)O(1)
ルール更新全体再作成増分更新増分更新
負荷分散確率的多様なアルゴリズムMaglevハッシュ
接続追跡conntrackconntrackBPF 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-ingressTraefikHAProxyContour
開発元Kubernetes/F5Traefik LabsHAProxy TechVMware
プロトコルHTTP/HTTPS/gRPCHTTP/HTTPS/gRPC/TCPHTTP/HTTPS/TCPHTTP/HTTPS/gRPC
設定リロード再起動必要ホットリロードホットリロードホットリロード
レート制限アノテーションミドルウェア内蔵未サポート
認証Basic/OAuthForward 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比較

機能IngressGateway 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 MapEndpoint MapCT  │   │   │
│  │  └──────────────────────────────────┘   │   │
│  └──────────────────────────────────────────┘   │
└──────────────────────────────────────────────────┘

10.2 eBPFがiptablesを置き換える理由

比較項目iptableseBPF
実行場所カーネル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動作:

Pod169.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ネットワーキングモデルの三つの基本原則のためです:

  1. すべてのPodは固有のIPアドレスを持つ
  2. すべてのPodは他のすべてのPodにNATなしで到達できる
  3. 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ドメインを順番に追加して先に試行します:

  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(成功)

外部DNS1つを検索するのに不要な3回のクエリが発生します。

解決策:

  • Pod dnsConfigでndotsを2に削減
  • FQDN使用(末尾にドット追加:api.example.com.)
  • NodeLocal DNSCacheでキャッシュ活用
  • CoreDNS autopathプラグイン使用

15. 参考資料(さんこうしりょう)

  1. Kubernetes Networking Model - 公式ドキュメント
  2. Cilium Documentation - eBPFベースネットワーキング
  3. Calico Documentation - Project Calico
  4. Gateway API - 公式仕様
  5. CoreDNS - サービスディスカバリ用DNS
  6. Network Policies - Kubernetesドキュメント
  7. eBPF.io - eBPF入門
  8. Hubble - Kubernetes向けネットワーク観測性
  9. IPVSベースkube-proxy - Kubernetesブログ
  10. CNI Specification - Container Network Interface
  11. NodeLocal DNSCache - Kubernetesドキュメント
  12. Cilium ClusterMesh - マルチクラスタネットワーキング
  13. Life of a Packet in Kubernetes - カンファレンストーク