Skip to content
Published on

コンテナ & Kubernetes ネットワークデバッグ完全ガイド

Authors
  • Name
    Twitter

1. Docker ネットワーキングモデル

コンテナネットワークデバッグの基礎は、Dockerが提供するネットワーキングモデルを正確に理解することから始まります。

1.1 Bridge ネットワーク

Dockerのデフォルトのネットワークドライバです。各コンテナは docker0 ブリッジに接続された仮想イーサネット(veth)インターフェースを割り当てられます。

# ブリッジネットワークの詳細確認
docker network inspect bridge

# コンテナのIPアドレス確認
docker inspect --format '{{.NetworkSettings.IPAddress}}' <container_id>

# vethペア確認
ip link show type veth

# docker0に接続されたインターフェース確認
brctl show docker0

ブリッジネットワークでよく発生する問題は以下の通りです。

  • コンテナ間通信不可: 同じブリッジネットワークに接続されているか確認
  • 外部通信不可: iptables NAT ルールと IP フォワーディング設定を確認
  • ポート競合: ホストポートバインディングの重複を確認
# iptables NATルール確認
sudo iptables -t nat -L -n -v

# IPフォワーディング状態確認
cat /proc/sys/net/ipv4/ip_forward

# ポートバインディング確認
docker port <container_id>

1.2 Host ネットワーク

コンテナがホストのネットワークスタックを直接使用します。ネットワーク分離がないためパフォーマンスは向上しますが、ポート競合のリスクがあります。

# hostモードでコンテナを実行
docker run --network host nginx

# コンテナ内部でネットワークインターフェース確認
docker exec <container_id> ip addr show

# ホストと同じネットワークスタックを使用していることを確認
docker exec <container_id> ss -tlnp

1.3 Overlay ネットワーク

複数のDockerホストにまたがるコンテナ間通信を可能にします。Docker Swarm や外部キーバリューストアが必要です。

# overlayネットワーク作成
docker network create --driver overlay my-overlay

# VXLANトンネル状態確認
ip -d link show type vxlan

# overlayネットワークのピア情報確認
docker network inspect my-overlay --format '{{json .Peers}}'

overlay ネットワークのデバッグ時に注意すべき点は以下の通りです。

  • VXLANポート(UDP 4789)がファイアウォールで許可されているか確認
  • MTU設定がVXLANオーバーヘッド(50バイト)を考慮しているか確認
  • ノード間の時刻同期状態を確認

2. Kubernetes ネットワーキングモデルと CNI

2.1 Kubernetes ネットワーキングの基本原則

Kubernetes ネットワーキングモデルは3つの基本原則に従います。

  1. すべてのPodはNATなしで他のすべてのPodと通信できなければならない
  2. すべてのノードはNATなしですべてのPodと通信できなければならない
  3. PodがI自身のIPとして認識するアドレスが、他のPodから見えるアドレスと同じでなければならない
# クラスタネットワークCIDR確認
kubectl cluster-info dump | grep -m 1 cluster-cidr

# ノードのPod CIDR確認
kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}'

# 使用中のCNIプラグイン確認
ls /etc/cni/net.d/
cat /etc/cni/net.d/*.conflist

2.2 CNI プラグインの理解

CNI(Container Network Interface)はコンテナのネットワークインターフェースを構成する標準です。

# CNIバイナリの場所確認
ls /opt/cni/bin/

# CNI設定ファイル確認
cat /etc/cni/net.d/10-calico.conflist

# kubeletのCNI関連ログ確認
journalctl -u kubelet | grep -i cni

主要なCNIプラグインの比較は以下の通りです。

CNI プラグインデータプレーンNetwork Policy特徴
Calicoiptables/eBPF対応BGPベースのルーティング
CiliumeBPF対応L7ポリシー、Hubble観測
FlannelVXLAN/host-gw非対応シンプルな設定
WeaveVXLAN対応自動メッシュネットワーク

3. Pod間通信のデバッグ

3.1 同一ノード内のPod間通信

# Pod IP確認
kubectl get pods -o wide

# PodからPodへのping テスト
kubectl exec -it <pod-a> -- ping <pod-b-ip>

# 同一ノードのPod間のルート確認
kubectl exec -it <pod-a> -- traceroute <pod-b-ip>

# ノードのvethインターフェース確認
kubectl debug node/<node-name> -it --image=nicolaka/netshoot -- ip link show

3.2 異なるノードのPod間通信

# ノードのルーティングテーブル確認
kubectl debug node/<node-name> -it --image=nicolaka/netshoot -- route -n

# VXLANまたはIPIPトンネル状態確認
kubectl debug node/<node-name> -it --image=nicolaka/netshoot -- ip tunnel show

# tcpdumpでパケットキャプチャ
kubectl debug node/<node-name> -it --image=nicolaka/netshoot -- \
  tcpdump -i any -nn host <target-pod-ip>

# MTU問題確認(Path MTU Discovery)
kubectl exec -it <pod> -- ping -M do -s 1400 <target-pod-ip>

ノード間通信の問題の主な原因は以下の通りです。

  • クラウドセキュリティグループでPod CIDRトラフィックがブロックされている
  • MTU不一致によるパケットフラグメンテーション
  • ノード間のルーティングテーブル不整合
  • IPIP/VXLANトンネルインターフェースのダウン

4. Pod-to-Service 通信のデバッグ

4.1 Service の基本動作確認

# ServiceのClusterIPとEndpoints確認
kubectl get svc <service-name> -o wide
kubectl get endpoints <service-name>

# Endpointsの詳細確認
kubectl get endpoints <service-name> -o yaml

# Serviceへの接続テスト
kubectl exec -it <test-pod> -- curl -v http://<service-name>:<port>

# Service selectorにマッチするPod確認
kubectl get pods -l <label-selector>

4.2 kube-proxy と iptables/IPVS ルール

kube-proxy はServiceの仮想IPを実際のPod IPに変換する役割を持ちます。

# kube-proxyモード確認
kubectl get configmap kube-proxy -n kube-system -o yaml | grep mode

# iptablesモード: Service関連iptablesルール確認
sudo iptables -t nat -L KUBE-SERVICES -n
sudo iptables -t nat -L KUBE-SVC-<hash> -n
sudo iptables -t nat -L KUBE-SEP-<hash> -n

# IPVSモード: 仮想サーバ一覧確認
sudo ipvsadm -Ln
sudo ipvsadm -Ln -t <cluster-ip>:<port>

# kube-proxyログ確認
kubectl logs -n kube-system -l k8s-app=kube-proxy --tail=100

iptablesルールの分析ではチェインの流れを理解する必要があります。

PREROUTING -> KUBE-SERVICES -> KUBE-SVC-xxx -> KUBE-SEP-xxx (DNAT)
# 特定Serviceの完全なiptablesチェイン追跡
SERVICE_IP=$(kubectl get svc <service-name> -o jsonpath='{.spec.clusterIP}')
sudo iptables -t nat -L KUBE-SERVICES -n | grep $SERVICE_IP

# conntrackテーブルでService接続追跡
sudo conntrack -L -d $SERVICE_IP

5. Service DNS 解決の問題

5.1 CoreDNS の動作確認

Kubernetesクラスタ内部のDNSはCoreDNSが担当します。

# CoreDNS Pod状態確認
kubectl get pods -n kube-system -l k8s-app=kube-dns

# CoreDNS設定確認
kubectl get configmap coredns -n kube-system -o yaml

# DNS解決テスト
kubectl exec -it <test-pod> -- nslookup <service-name>
kubectl exec -it <test-pod> -- nslookup <service-name>.<namespace>.svc.cluster.local

# DNS応答時間計測
kubectl exec -it <test-pod> -- dig <service-name>.default.svc.cluster.local +stats

5.2 DNS 問題の診断

# PodのDNS設定確認
kubectl exec -it <pod> -- cat /etc/resolv.conf

# CoreDNSログでエラー確認
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=200

# DNSデバッグ用Pod配置
kubectl run dnsutils --image=gcr.io/kubernetes-e2e-test-images/dnsutils:1.3 \
  --restart=Never -- sleep 3600

# 外部ドメイン解決テスト
kubectl exec -it dnsutils -- nslookup google.com
kubectl exec -it dnsutils -- nslookup kubernetes.default

よく発生するDNS問題と解決策は以下の通りです。

  • ndots設定: resolv.conf の ndots:5 設定により、短い名前に対して複数回DNSクエリが発生します。FQDN(末尾に . を含む)を使用すれば解決します。
  • CoreDNS CrashLoopBackOff: ログを確認し、アップストリームDNSサーバの接続状態を点検します。
  • DNSキャッシュ問題: CoreDNS の cache プラグイン設定を確認します。
# ndots問題の確認: クエリ回数比較
kubectl exec -it <pod> -- dig myservice.default.svc.cluster.local +search +showsearch
kubectl exec -it <pod> -- dig myservice.default.svc.cluster.local. +search +showsearch

6. 外部通信のデバッグ

6.1 Ingress / LoadBalancer の問題

# Ingressリソース状態確認
kubectl get ingress -A
kubectl describe ingress <ingress-name>

# Ingress Controllerログ確認
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100

# LoadBalancer ServiceのExternal IP確認
kubectl get svc -l type=LoadBalancer

# NodePortを通じた外部アクセステスト
curl -v http://<node-ip>:<node-port>

6.2 Egress トラフィックのデバッグ

# Podから外部へのトラフィック確認
kubectl exec -it <pod> -- curl -v https://httpbin.org/ip

# NATゲートウェイとルーティング確認
kubectl exec -it <pod> -- traceroute 8.8.8.8

# SNATルール確認
sudo iptables -t nat -L POSTROUTING -n -v

7. Network Policy のデバッグ

7.1 Network Policy の基本診断

# 適用されたNetwork Policy確認
kubectl get networkpolicy -A
kubectl describe networkpolicy <policy-name> -n <namespace>

# 特定Podに適用されるNetwork Policy確認
kubectl get networkpolicy -n <namespace> -o json | \
  jq '.items[] | select(.spec.podSelector.matchLabels | to_entries[] |
  .key == "app" and .value == "myapp")'

# Network Policy適用前後の接続テスト
kubectl exec -it <source-pod> -- nc -zv <target-pod-ip> <port>

7.2 Network Policy トラブルシューティングパターン

# すべてのトラフィックを遮断するデフォルトポリシー
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
# ポリシー適用後の通信テスト
kubectl exec -it <pod> -- wget -qO- --timeout=2 http://<target-service>

# CNI別Network Policyログ確認
# Calico
kubectl logs -n calico-system -l k8s-app=calico-node --tail=100

# Cilium
kubectl exec -n kube-system <cilium-pod> -- cilium policy get
kubectl exec -n kube-system <cilium-pod> -- cilium endpoint list

8. Calico トラブルシューティング

8.1 Calico 状態確認

# Calicoノードの健全性確認
kubectl get pods -n calico-system
calicoctl node status

# BGPピア状態確認
calicoctl get bgpPeer
calicoctl node status | grep -A 5 "BGP"

# IPプール確認
calicoctl get ippool -o wide

# Calico固有のネットワークポリシー確認
calicoctl get networkpolicy -A
calicoctl get globalnetworkpolicy

8.2 Calico デバッグ

# Felixのログレベル変更(デバッグ時)
calicoctl patch felixconfiguration default \
  --patch '{"spec":{"logSeverityScreen":"Debug"}}'

# BIRDルーティングデーモン状態確認
kubectl exec -n calico-system <calico-node-pod> -- birdcl show route

# IP-in-IPトンネル状態確認
kubectl exec -n calico-system <calico-node-pod> -- ip tunnel show

# Calicoがプログラムしたiptablesルール確認
sudo iptables -L -n | grep cali

9. Cilium トラブルシューティング

9.1 Cilium 状態確認

# Ciliumエージェントの詳細状態確認
kubectl exec -n kube-system <cilium-pod> -- cilium status --verbose

# Ciliumエンドポイント一覧
kubectl exec -n kube-system <cilium-pod> -- cilium endpoint list

# BPFマップ状態確認
kubectl exec -n kube-system <cilium-pod> -- cilium bpf lb list
kubectl exec -n kube-system <cilium-pod> -- cilium bpf ct list global

# Hubbleでネットワークフロー観察
hubble observe --namespace <namespace>
hubble observe --pod <pod-name> --protocol TCP

9.2 Cilium デバッグ

# Cilium接続性テスト
kubectl exec -n kube-system <cilium-pod> -- cilium connectivity test

# eBPFプログラム状態確認
kubectl exec -n kube-system <cilium-pod> -- cilium bpf prog list

# ポリシートレーシング
kubectl exec -n kube-system <cilium-pod> -- cilium policy trace \
  --src-k8s-pod <namespace>:<src-pod> \
  --dst-k8s-pod <namespace>:<dst-pod> \
  --dport <port>

# リアルタイムイベントモニタリング
kubectl exec -n kube-system <cilium-pod> -- cilium monitor --type drop
kubectl exec -n kube-system <cilium-pod> -- cilium monitor --type policy-verdict

10. Debug コンテナとエフェメラルコンテナ

10.1 kubectl debug の活用

# 実行中のPodにデバッグコンテナをアタッチ
kubectl debug -it <pod-name> --image=nicolaka/netshoot --target=<container-name>

# ノードレベルのデバッグ
kubectl debug node/<node-name> -it --image=ubuntu

# Podのコピーを作成してデバッグ(原本に影響なし)
kubectl debug <pod-name> -it --copy-to=debug-pod --image=nicolaka/netshoot

# プロセス名前空間を共有するデバッグコンテナ
kubectl debug -it <pod-name> --image=busybox --share-processes

10.2 netshoot を使ったネットワークデバッグ

# netshootコンテナの配置
kubectl run netshoot --image=nicolaka/netshoot --restart=Never -- sleep 3600

# コンテナに入って総合的なネットワーク診断
kubectl exec -it netshoot -- bash

# 内部で実行するコマンド:
# TCP接続テスト
nc -zv <service-ip> <port>

# HTTPリクエストテスト
curl -v http://<service-name>.<namespace>.svc.cluster.local:<port>/health

# DNS検索
dig +short <service-name>.<namespace>.svc.cluster.local

# パケットキャプチャ
tcpdump -i eth0 -nn port 80

# ネットワーク経路追跡
mtr <target-ip>

# SSL/TLS接続確認
openssl s_client -connect <service-ip>:443

11. 実践デバッグシナリオ

シナリオ 1: Pod が Service にアクセスできない場合

# ステップ1: ServiceとEndpoints確認
kubectl get svc <service-name> -o yaml
kubectl get endpoints <service-name>

# ステップ2: Endpointsが空の場合 -> selector確認
kubectl get pods -l <label-selector> --show-labels

# ステップ3: PodがReady状態か確認
kubectl get pods -l <label-selector> -o wide
kubectl describe pod <target-pod> | grep -A 5 "Conditions"

# ステップ4: kube-proxyルール確認
sudo iptables -t nat -L KUBE-SERVICES -n | grep <cluster-ip>

# ステップ5: Pod IPへ直接アクセステスト
kubectl exec -it <source-pod> -- curl -v http://<pod-ip>:<target-port>

シナリオ 2: 間欠的なタイムアウトの発生

# ステップ1: conntrackテーブル飽和確認
sudo sysctl net.netfilter.nf_conntrack_count
sudo sysctl net.netfilter.nf_conntrack_max

# ステップ2: パケットドロップ確認
kubectl debug node/<node-name> -it --image=nicolaka/netshoot -- \
  netstat -s | grep -i drop

# ステップ3: ネットワークインターフェースエラー確認
kubectl debug node/<node-name> -it --image=nicolaka/netshoot -- \
  ip -s link show

# ステップ4: TCP再送確認
kubectl debug node/<node-name> -it --image=nicolaka/netshoot -- \
  netstat -s | grep -i retrans

シナリオ 3: DNS 解決が遅い場合

# ステップ1: DNS応答時間計測
kubectl exec -it <pod> -- dig <service-name>.default.svc.cluster.local +stats | grep "Query time"

# ステップ2: CoreDNS Podリソース使用量確認
kubectl top pods -n kube-system -l k8s-app=kube-dns

# ステップ3: ndots最適化適用
# Pod specに以下を追加:
# dnsConfig:
#   options:
#   - name: ndots
#     value: "2"

# ステップ4: CoreDNSキャッシュヒット率確認
kubectl exec -n kube-system <coredns-pod> -- \
  wget -qO- http://localhost:9153/metrics | grep coredns_cache

12. デバッグチェックリスト

ネットワーク問題を体系的にアプローチするためのチェックリストです。

[ ] Pod状態確認(Running、Ready)
[ ] Service Endpoints確認(空でないこと)
[ ] DNS解決確認(nslookup/dig)
[ ] Pod IPへの直接接続テスト
[ ] kube-proxyルール確認(iptables/IPVS[ ] Network Policy確認(Ingress/Egressルール)
[ ] CNIプラグイン健全性確認
[ ] ノード間ネットワーク接続確認
[ ] MTU設定確認
[ ] ファイアウォール/セキュリティグループルール確認
[ ] conntrackテーブル状態確認
[ ] CoreDNS状態とログ確認

ネットワークデバッグはレイヤーごとにアプローチするのが最も効果的です。L2(イーサネット)-> L3(IP/ルーティング)-> L4(TCP/UDP)-> L7(HTTP/DNS)の順序で各レイヤーに問題がないか確認すれば、複雑なネットワーク問題も体系的に解決できます。