Kubernetes

NetworkPolicy適用確認とCNI別デバッグガイド

ⓘ本ページはプロモーションが含まれています

お得なお知らせ

スポンサードリンク
1ヶ月で資格+現場入り

インフラエンジニアへの最短ルート

未経験でもAWS・Linux・ネットワーク資格を最短で取り、現場入りまでサポート。SREやクラウドエンジニアの入口。

CODE×CODEスピード転職|無料面談▶ SRE/クラウドのフリーランス案件▶

▶ AWS/GCP/Kubernetesの独学には Kindle Unlimited の技術書読み放題がコスパ最強。


Contents

スポンサードリンク

NetworkPolicyの基本概念と前提条件

NetworkPolicyの基本動作と検証時の前提をまとめます。podSelectorやnamespaceSelector、policyTypesの挙動とCNI依存性、hostNetwork/HostPortの注意点を実務視点で解説します。

基本概念(Pod/Namespaceセレクタ、ポート、プロトコル、ingress/egress)

NetworkPolicyはL3/L4でPod間通信を制御するリソースです。podSelectorは同一Namespaceで評価され、空にするとそのNamespace内の全Podを選択します。namespaceSelectorはPeerとして別Namespaceを指定する際に使います。portsはTCP/UDP/SCTPを指定でき、標準のNetworkPolicyはL7(HTTPパス等)やICMPを直接扱いません。

デフォルト挙動と前提条件(policyTypes、CNIサポート)

NetworkPolicyはAPI上の宣言であり、実際の遮断はCNIプラグインが実装します。Podがどれか一つでもPolicyに選択されると、policyTypesに含まれる方向で明示的に許可されていない通信は拒否されます。policyTypesは明示的に指定することを推奨します。hostNetwork/HostPortの挙動やDaemonSetのノードローカル性はCNI実装に左右されます。

API互換性とKubernetesバージョン

マニフェストで使うapiVersionはクラスタごとに差があります。まずはクラスタで networking.k8s.io/v1 が利用可能か確認してください。下記コマンドで確認できます。

多くの近年のクラスタは networking.k8s.io/v1 をサポートしますが、古いクラスタでは beta 系の API や別の group/version の可能性があります。古いクラスタで差異がある場合は manifest の apiVersion を合わせる、あるいはクラスタのリリースノートで deprecation 情報を確認してください。

検証準備:クラスタとCNIの状態確認

検証前にクラスタとCNIの状態を確実に把握します。ここで事前に問題を潰しておくと、後の切り分けが早くなります。

クラスタとCNIの状態確認コマンド例

まずは利用可能なAPIとCNIの存在を確認します。以下は堅牢に情報を取得するための例です。各コマンドの出力を保存して調査に使ってください。

  • Kubernetes バージョンとノード情報を取得するコマンド:
  • kubectl version --short
  • kubectl get nodes -o wide

  • networking.k8s.io API の有無を確認:

  • kubectl api-versions | grep networking.k8s.io

  • kube-system の DaemonSet / Pod を列挙して CNI を特定する例:

  • kubectl get ds,deploy,po -n kube-system -o wide
  • kubectl get daemonset -n kube-system -o custom-columns=NAME:.metadata.name,IMAGE:.spec.template.spec.containers[0].image

  • 特定のCNI Podをラベルで探す(環境依存なのでラベル名は要調整):

  • kubectl get pods -n kube-system -l k8s-app=calico-node -o wide
  • kubectl get pods -n kube-system -l k8s-app=cilium -o wide

  • CNI Podのログ確認:

  • kubectl logs -n kube-system -c

  • ノード上のCNI設定ファイル(ノードSSHが可能な場合):

  • sudo ls /etc/cni/net.d

CNI名やラベルは環境差が大きいので、単純な文字列マッチよりDaemonSetやPodのイメージ名、ownerReferencesで特定する方法が堅牢です。

権限・必須ツールと事前チェック

実行に必要な権限と検証用ツールを揃えてください。主な項目は次の通りです。

  • RBAC: NetworkPolicyやPodの作成、exec の権限(例: kubectl auth can-i create networkpolicy --namespace=
  • kubectl(kubeconfig が設定済み)
  • CNI固有ツール(必要に応じて): calicoctl、cilium CLI/hubble
  • デバッグ用イメージ: nicolaka/netshoot、curlimages/curl、infoblox/dnsutils、iperf3
  • ノードツール(読み取り専用推奨): iptables/nft、conntrack、bpftool、tcpdump(ノードSSH権限が必要)
  • クラウド環境固有の確認:GKE等はアドオンやCalicoの導入状況で機能が変わるため、クラウドのドキュメントとリリースノートを参照してください(例: https://cloud.google.com/kubernetes-engine/docs/how-to/network-policy)。

ノードやCNIに対する操作は影響範囲が大きいので、事前承認とバックアウト手順を用意してください。

検証マトリクスとテストPodによる接続確認

検証は再現性と判定の明確さが重要です。ここでは網羅的にケースを設計し、DNS周りやService経由とPodIP直叩きの差も検証します。

検証マトリクスの設計(Ingress/Egress/ポート/プロトコル/名前空間等)

検証マトリクスは期待結果を明確にするために作成します。DNS(UDP/TCP 53)やFQDNベースの検証はEgress制限で失敗することがある点に注意してください。

ケース 方向 送信元 宛先 ポート プロトコル 期待結果
1 Ingress 同一NamespaceのPod 試験Pod 80 TCP Allow
2 Ingress 別NamespaceのPod 試験Pod 80 TCP Allow/Denied(Policy次第)
3 Egress 試験Pod 外部IP 443 TCP Allow/Denied
4 Ingress Service ClusterIP経由 バックエンドPod 80 TCP PodレベルのPolicyが適用されるか確認
5 Egress 試験Pod クラスタDNS (UDP/TCP 53) 53 UDP/TCP DNSがブロックされるとFQDN検証は失敗
6 Egress 試験Pod バックエンド PodIP 80 TCP PodIP直叩きでパスが通るか確認

この表を基に自動化スクリプトを作成してください。

テストPodの作り方と接続確認の具体コマンド例

テストはephemeral Podや既存のデバッグPodで行うと便利です。FQDNベースのテストはDNSが通ることが前提です。EgressルールでDNSがブロックされると名前解決ができず失敗するため、DNS(UDP/TCP 53)の許可ルール例か、Pod IPによる検証を用意してください。

  • FQDNでのHTTPアクセス確認(ephemeral Podを使う例)
  • kubectl run --rm --image=curlimages/curl --restart=Never curl-test -n np-a -- sh -c 'curl -sS -m 5 http://backend.np-b.svc.cluster.local:80'
  • Pod IP での確認
  • PODIP=$(kubectl get pod -n np-b -l app=backend -o jsonpath='{.items[0].status.podIP}')
  • kubectl run --rm --image=curlimages/curl --restart=Never curl-test -n np-a -- sh -c "curl -sS -m 5 http://$PODIP:80"
  • DNS の確認(dig/nslookup が使える場合)
  • kubectl run --rm --image=nicolaka/netshoot --restart=Never -n np-a -- dig +short backend.np-b.svc.cluster.local
  • Pod/Namespace のラベル確認
  • kubectl get pods -n --show-labels
  • kubectl get ns --show-labels

DNSブロックでFQDNが解決できない時は、まず DNS (UDP/TCP 53) を許可するPolicyを追加するか、PodIP直接での検証を行ってください。

代表的NetworkPolicyマニフェスト例と適用→検証フロー

よく使う代表パターンを示します。例では namespaceSelector のラベル依存に注意し、必要なら Namespace にラベル付与を行う手順を含めます。

テスト用リソース(Namespace/Deployment/Service/Pod)

以下は検証用の最小構成です。Namespaceには明示的にラベルを付けています。実運用ではラベル名を組織ルールに合わせてください。

NamespaceSelectorでラベルを参照するPolicyを使う場合、対象Namespaceにラベルが付与されていることを確認してください。ラベルがない場合は次のように付与します。

deny-all(完全隔離)マニフェスト

対象Namespace内の全Podを両方向で遮断する例です。

名前空間間許可(np-a から np-b の backend への許可)

namespaceSelector を使う場合、Namespaceラベルに依存します。ラベル付与を忘れないでください。

クライアント側でDNSを許可する例(np-a)

Egress を制限する場合はDNS(UDP/TCP 53)も許可する必要があります。以下は np-a の Pod が kube-system の DNS に接続できるようにする例です。事前に kube-system にラベルを付けてください。

適用から検証、期待結果までのワークフロー

まずはリソースをデプロイしてからPolicyを適用し、マトリクスに従ってテストします。一般的な手順は次の通りです。

  1. テスト用NamespaceとPodを作成する。
  2. 必要なNamespaceラベルを付与する(namespaceSelector を使う場合)。
  3. マニフェストを適用する。
  4. Podの起動待ちを行い、FQDN と PodIP 両方で接続を確認する。
  5. 期待と異なる場合は CNI ログ、iptables/BPF、tcpdump の順で原因を切り分ける。
  6. 修正後に同一マトリクスで再確認する。

CNI別デバッグと低レイヤ診断(実務的な切り分け手順)

CNIごとに実装や可視化手段が異なります。標準NetworkPolicyはL3/L4のみのため、L7制御やFQDN制御が必要な場合はCNIの拡張機能を利用する必要があります。

CNI別のチェックポイントと専用ツール(Calico、Cilium、その他)

各CNIの主要ポイントと代表的コマンドを示します。

  • Calico
  • カーネルレベルのルールはFelixが管理します。ログは calico-node コンテナで確認してください。
  • calicoctl が使える環境ならポリシーや状態の照会が便利です。
  • Calico の FQDN ベースの拡張やエンタープライズ機能はバージョン依存です。ドキュメントで確認してください。

  • Cilium

  • cilium CLI と Hubble によるフロー可視化が強力です(cilium status, cilium endpoint list, cilium monitor, hubble observe)。
  • Cilium の拡張ポリシー(CiliumNetworkPolicy)は L7 制御をサポートします。BPF レベルでの可視化や sysdump が取得できます。

  • その他(Weave、Flannel、kube-router など)

  • 実装は多様で、NetworkPolicy 未対応または限定的な場合があります。daemon のログとドキュメントを確認してください。

標準 NetworkPolicy は L7 をサポートしません。L7/FQDN の制御が必要な場合は、Cilium や Calico の拡張を検討してください。各CNIで実装方法や制約が異なるため、必ずベンダーのドキュメントを参照してください。

低レイヤ診断(iptables/nftables、BPFマップ、conntrack、tc、tcpdump等)

低レイヤは「読み取り中心」で切り分けを行います。危険な変更は避けてください。ここでは安全に行える確認コマンドと禁止事項を示します。

  • 読み取り用コマンド例:
  • sudo iptables-save | grep -E 'cali|CILIUM|cilium|CALICO'
  • sudo iptables -L -n -v
  • sudo nft list ruleset
  • sudo conntrack -L | grep
  • sudo bpftool map show
  • sudo bpftool prog list
  • sudo tcpdump -n -i any host and port

  • ipvs / kube-proxy の確認:

  • sudo ipvsadm -Ln
  • kubectl -n kube-system get daemonset kube-proxy -o yaml

  • 禁止・注意事項(明確に守ること)

  • ノード全体に影響する破壊的操作を行わない(例: iptables -F, iptables -X, nft delete ruleset, conntrack -F)。
  • 影響範囲が限定される操作でも、事前に影響試算と承認を得ること。
  • 必要であれば特定フローだけを削除する(例: sudo conntrack -D -s )等の限定的操作を検討する。

低レイヤ診断はCNI固有の構造を理解してから行うと効率的です。ログとキャプチャを保存して解析に使ってください。

Service経由とPodIP直叩きの切り分け(kube-proxy iptables / ipvs の違い)

Service経由とPodIP直叩きでルーティング経路が異なることがあります。特に kube-proxy のモード(iptables / ipvs)で動作が変わります。

  • モード確認:
  • kubectl -n kube-system get ds kube-proxy -o yaml で起動オプションを確認
  • ノード上で sudo ipvsadm -Ln を実行し、IPVS テーブルが存在すれば ipvs モード

  • 典型的な差:

  • iptables モードでは ClusterIP へは DNAT がかかり、iptables チェーンにルールが現れます。
  • ipvs モードでは ipvs テーブルで仮想サービスが管理され、パケットの扱いが異なるため、Policy の適用箇所やログの出どころが変わることがあります。

切り分けは、ノードの tcpdump と Pod 内の tcpdump を比較し、DNAT の有無やパスの差を確認してください。

特殊ケース:hostNetwork / HostPort / ノードローカルDaemonSet の扱いと検証方法

hostNetwork を使う Pod はノードのネットワーク名前空間で動くため、NetworkPolicy の適用が期待どおりにならない場合があります。HostPort やノードローカルなDaemonSetも同様に挙動がCNI依存です。検証のポイントは次の通りです。

  • hostNetwork Pod のトラフィックがどの時点でフィルタされるかを、ノード上の tcpdump と Pod内の tcpdump で比較する。
  • HostPort はノードのポートを使うため、ノードのファイアウォールや kube-proxy の設定が影響する。
  • 回避策としては、アプリをCluster-IPやNodePort越しにアクセスさせる、あるいはクラスタ内プロキシを経由させる方法がある。

CI自動化・運用ベストプラクティス、よくある誤り

運用では自動化と明確な前提確認が重要です。ここでは優先的な切り分けフローとよくある誤りの実例を示します。

CI組込みと運用フロー(テストの自動化、監視、段階的導入)

検証をCIに組み込む際の高レベルな流れは次の通りです。

  1. テスト用クラスタ/Namespace を用意する(kind/k3d 等で短命環境)
  2. マニフェストをデプロイし、前提チェックを実行する(API・CNI・ラベル等)
  3. 検証スクリプトでマトリクス全ケースを実行し、明示的に成功/失敗を判定する
  4. 結果をアーティファクトとして保存し、問題発生時はログ・pcapを参照する
  5. 段階的に本番に導入し、監視(CNIのドロップメトリクス等)を設置する

よくある誤り・実例のトラブルシュート

代表的な誤りと対応例を示します。

  • ラベルミスでPolicyがマッチしない
  • 再現: NamespaceBのServiceにアクセス不可
  • 原因: podSelector/namespaceSelectorのラベル名がPodやNamespaceと一致していない
  • 対応: kubectl get pods -n ns-b --show-labels で確認し、ラベルまたはPolicyを修正する

  • Egress制限でFQDNが失敗する(DNSブロック)

  • 再現: FQDNでアクセスできないが PodIP 直叩きは通る
  • 原因: クライアント側のEgressで UDP/TCP 53 が許可されていないため名前解決が失敗している
  • 対応: DNS を許可するPolicyを追加するか、検証は PodIP で行う

  • testスクリプトで待ちの扱いが甘い

  • 再現: kubectl wait に '|| true' を付けているため準備不足でも先に進む
  • 対応: 待ち処理は明示的なタイムアウトとリトライで実装し、失敗時は明確に異常終了させる

付録:コピーして使えるテスト用マニフェストと堅牢な検証スクリプト例

ここでは前節のマニフェストと、DNSの落とし穴に対応した堅牢なスクリプト例を示します。実行前に内容を確認し、環境に合わせて調整してください。

マニフェスト一覧(主なもの)

  • test-resources.yaml(前出)
  • deny-all.yaml(np-b 全隔離、前出)
  • allow-from-ns-a.yaml(np-b の backend に対して np-a からの TCP:80 を許可、前出)
  • allow-dns.yaml(np-a から kube-system の DNS に対する UDP/TCP:53 を許可、前出)
  • client-restrict-egress.yaml(np-a から np-b:80 のみを許可する例)

このPolicyは np-a から np-b の TCP:80 のみを許可します。DNS が許可されていないため FQDN による検証は失敗します。この例で DNS の重要性を確認してください。

test-script.sh(堅牢版の例)

検証スクリプトは待ち・判定・エラーハンドリングを明確にします。以下は一例です。実行前に実行権限を付与してください(chmod +x test-script.sh)。

上記スクリプトは失敗時に明確な終了コードを返します。kubectl wait を単に '|| true' で逃すような実装は避けてください。

まとめ

  • NetworkPolicy は L3/L4 の制御であり、実効は CNI に依存します。CNI の実装差を把握してください。
  • Egress を制限する Policy を導入すると DNS(UDP/TCP 53)がブロックされ、FQDN ベースの検証は失敗することがあります。DNS 許可または PodIP 直接検証を併用してください。
  • networking.k8s.io/v1 の利用可否はクラスタによります。kubectl api-versions や kubectl explain で確認してください。
  • L7 制御や FQDN 制御は標準 NetworkPolicy では扱えません。Cilium や Calico の拡張機能を利用する場合はベンダードキュメントで機能と制約を確認してください。
  • 低レイヤ診断は読み取り中心で行い、破壊的な操作(iptables 全消去、conntrack 全削除など)は原則実施しないでください。
  • 検証は前提チェック(API/CNI/ラベル/RBAC)→マトリクス設計→堅牢なスクリプトで自動化→低レイヤ切り分けの順で行ってください。
スポンサードリンク

お得なお知らせ

スポンサードリンク
1ヶ月で資格+現場入り

インフラエンジニアへの最短ルート

未経験でもAWS・Linux・ネットワーク資格を最短で取り、現場入りまでサポート。SREやクラウドエンジニアの入口。

CODE×CODEスピード転職|無料面談▶ SRE/クラウドのフリーランス案件▶

▶ AWS/GCP/Kubernetesの独学には Kindle Unlimited の技術書読み放題がコスパ最強。


-Kubernetes