- Published on
Kubernetes Network Policy 完全ガイド: CiliumとCalicoで実現するゼロトラストネットワークセキュリティ
- Authors
- Name
- はじめに
- Kubernetes NetworkPolicy アーキテクチャ
- Cilium CiliumNetworkPolicy 深層分析
- Calico GlobalNetworkPolicy 深層分析
- Cilium vs Calico vs 標準NetworkPolicy 比較表
- 実装ガイド
- モニタリングとトラブルシューティング
- 障害事例と復旧手順
- プロダクションデプロイチェックリスト
- 高度なパターン: マルチクラスターネットワークポリシー
- まとめ
- 参考資料

はじめに
Kubernetesクラスターにおいて、Podはデフォルトで他のすべてのPodと自由に通信できる。これは開発初期には便利だが、プロダクション環境では深刻なセキュリティ脅威となる。1つのPodが侵害されると、クラスター内のすべてのサービスへのラテラルムーブメントが可能になるためだ。実際、2024年のCNCF Security Auditで調査されたKubernetesセキュリティインシデントの67%が、内部ネットワーク分離の不備に起因するものだった。
ゼロトラストネットワーク(Zero Trust Network) アーキテクチャは、この問題に対する解答として、ネットワーク内部のすべてのトラフィックも信頼せず、明示的に許可された通信のみを許可する原則である。Kubernetesでこれを実現するための核心ツールがNetworkPolicyである。
しかし、標準のKubernetes NetworkPolicyはL3/L4(IP、ポート)レベルの制御のみをサポートし、DNSベースのポリシーやHTTPパスベースのフィルタリングなどの高度な機能は提供しない。この制限を克服するために、CiliumやCalicoなどのCNIプラグインが登場した。CiliumはeBPFベースでL7までの精密なポリシーを提供し、CalicoはBGPルーティングとGlobalNetworkPolicyを通じてエンタープライズグレードのネットワークセキュリティを実現する。
本記事では、Kubernetes NetworkPolicyの基本概念から始め、CiliumとCalicoの高度なポリシー実装、比較分析、モニタリングとトラブルシューティング、実際の障害事例と復旧手順、そしてプロダクションデプロイチェックリストまで総合的に解説する。
Kubernetes NetworkPolicy アーキテクチャ
NetworkPolicyの基本構造
Kubernetes NetworkPolicyは、Podレベルでネットワークトラフィックを制御するネームスペーススコープのリソースである。CNIプラグインが実際のポリシーを適用し、NetworkPolicyをサポートしないCNI(例:Flannel)ではリソースを作成しても効果がない。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-server-policy
namespace: production
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
environment: production
podSelector:
matchLabels:
role: frontend
- ipBlock:
cidr: 10.0.0.0/8
except:
- 10.0.1.0/24
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
このポリシーは以下のように動作する。
- 対象Pod選択:
podSelectorでapp: api-serverラベルを持つPodに適用 - Ingressルール: productionネームスペースのfrontend Podと10.0.0.0/8帯域(10.0.1.0/24を除く)からTCP 8080ポートへのアクセスのみ許可
- Egressルール: database PodへのTCP 5432アクセスとDNS(UDP 53)トラフィックのみ許可
Default Deny戦略
ゼロトラストの基本はすべてのトラフィックを遮断した後、必要なものだけを明示的に許可することである。Default Denyポリシーは、ネームスペース内のすべてのPodのIngressとEgressを遮断する。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
空のpodSelectorはネームスペース内のすべてのPodを選択する。IngressとEgressの両方がpolicyTypesに指定されているが、許可ルールがないためすべてのトラフィックが遮断される。サービスディスカバリが正常に動作するようにDNSを別途許可する必要がある。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
ネームスペース分離パターン
大規模クラスターでは、ネームスペース間の分離が必須である。以下は同一ネームスペース内通信のみを許可するパターンである。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: namespace-isolation
namespace: team-alpha
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
podSelector: {}にnamespaceSelectorがない場合、現在のネームスペースのすべてのPodのみがマッチされる。これにより、ネームスペース間の分離を簡潔に実装できる。
Cilium CiliumNetworkPolicy 深層分析
Ciliumアーキテクチャ とeBPF
CiliumはLinuxカーネルのeBPF(extended Berkeley Packet Filter) 技術を活用して、ネットワークポリシーをカーネルレベルで適用する。従来のiptablesベースのアプローチとは異なり、eBPFはプログラマブルなデータプレーンを提供するため、ポリシー数が増加してもパフォーマンス低下がほとんどない。
Ciliumの主要コンポーネントは以下の通りである。
- Cilium Agent: 各ノードでDaemonSetとして実行され、eBPFプログラムをコンパイルしてカーネルにロードする
- Cilium Operator: クラスター全体のリソース管理を担当する
- Hubble: ネットワークフローをリアルタイムで観測するモニタリングツール
- Envoy Proxy: L7ポリシー適用時に透過プロキシとして動作する
L3-L7フィルタリング実装
CiliumのCiliumNetworkPolicyは、標準NetworkPolicyのすべての機能を含みつつ、L7(HTTP、gRPC、Kafka)レベルの精密な制御を追加でサポートする。
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l7-api-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: api-server
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: '8080'
protocol: TCP
rules:
http:
- method: GET
path: '/api/v1/products'
- method: POST
path: '/api/v1/orders'
headers:
- 'Content-Type: application/json'
- method: GET
path: '/healthz'
このポリシーは、frontend Podからapi-serverへのトラフィックのうち、GET /api/v1/products、POST /api/v1/orders(JSON Content-Typeヘッダー必須)、GET /healthzリクエストのみを許可する。PUTやDELETEなどの他のHTTPメソッドはブロックされる。
DNSベースポリシー
CiliumはFQDN(Fully Qualified Domain Name)ベースでEgressトラフィックを制御できる。外部APIコールを特定ドメインに制限する際に有用である。
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: dns-based-egress
namespace: production
spec:
endpointSelector:
matchLabels:
app: payment-service
egress:
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: '53'
protocol: ANY
rules:
dns:
- matchPattern: '*.stripe.com'
- matchPattern: '*.amazonaws.com'
- toFQDNs:
- matchPattern: '*.stripe.com'
toPorts:
- ports:
- port: '443'
protocol: TCP
- toFQDNs:
- matchPattern: '*.amazonaws.com'
toPorts:
- ports:
- port: '443'
protocol: TCP
このポリシーは、payment-serviceがstripe.comとamazonaws.comドメインとのみHTTPS通信できるように制限する。DNSクエリ自体もそれらのドメインに対してのみ許可される。
CiliumClusterwideNetworkPolicy
クラスター全体に適用されるポリシーにはCiliumClusterwideNetworkPolicyを使用する。
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: block-metadata-access
spec:
endpointSelector: {}
egressDeny:
- toCIDR:
- 169.254.169.254/32
toPorts:
- ports:
- port: '80'
protocol: TCP
このポリシーは、クラスター内のすべてのPodがクラウドメタデータサービス(169.254.169.254)にアクセスすることをブロックする。IMDSを通じた認証情報窃取攻撃を防ぐ重要なセキュリティ対策である。
Calico GlobalNetworkPolicy 深層分析
Calicoアーキテクチャ
CalicoはTigeraが開発したネットワーキングソリューションで、BGP(Border Gateway Protocol)ベースのL3ルーティングとポリシーエンジンを提供する。主要コンポーネントは以下の通りである。
- Felix: 各ノードで実行されるエージェントで、ルーティングテーブルとiptables/eBPFルールを管理する
- BIRD: BGPクライアントで、ノード間のルーティング情報を交換する
- Typha: FelixとKubernetes API Server間のプロキシで、API Serverの負荷を軽減する
- calicoctl: Calicoリソースを管理するCLIツール
GlobalNetworkPolicy実装
CalicoのGlobalNetworkPolicyは、ネームスペースに依存しないクラスター全体スコープのポリシーである。標準のKubernetes NetworkPolicyより優先して適用される。
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: deny-egress-to-internet
spec:
selector: environment == 'production'
types:
- Egress
egress:
- action: Allow
destination:
nets:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- action: Allow
protocol: UDP
destination:
ports:
- 53
- action: Deny
destination:
notNets:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
このポリシーは、production環境のすべてのPodがRFC 1918プライベートIP帯域とDNSトラフィックのみを許可し、インターネットへの直接通信をブロックする。
Calicoティアシステム
Calico Enterpriseでは、ポリシーティアを使用してポリシー適用順序を明確に管理できる。
apiVersion: projectcalico.org/v3
kind: Tier
metadata:
name: security
spec:
order: 100
---
apiVersion: projectcalico.org/v3
kind: Tier
metadata:
name: platform
spec:
order: 200
---
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: security.block-known-threats
spec:
tier: security
order: 10
selector: all()
types:
- Ingress
- Egress
ingress:
- action: Deny
source:
nets:
- 198.51.100.0/24
- action: Pass
egress:
- action: Deny
destination:
nets:
- 198.51.100.0/24
- action: Pass
セキュリティチームのポリシーがプラットフォームチームのポリシーより先に評価されるため、既知の脅威IPをプラットフォームポリシーに関係なくブロックできる。
Cilium vs Calico vs 標準NetworkPolicy 比較表
各ソリューションの主要機能と特性を比較した表である。
| 項目 | Kubernetes NetworkPolicy | Cilium | Calico |
|---|---|---|---|
| ポリシースコープ | ネームスペース | ネームスペース + クラスター | ネームスペース + クラスター |
| L3/L4サポート | O | O | O |
| L7サポート | X | O (HTTP, gRPC, Kafka, DNS) | 部分的 (Enterpriseのみ) |
| DNSベースポリシー | X | O (FQDNマッチング) | O (Calico Enterprise) |
| ポリシーエンジン | CNI依存 | eBPFネイティブ | iptables / eBPF選択 |
| パフォーマンス (1000+ポリシー) | iptablesベースの性能低下 | eBPFで安定した性能 | eBPFモード時良好 |
| モニタリング | 別途ツール必要 | Hubble内蔵 | calicoctl + Prometheus |
| FQDN Egress | X | O | O (Enterprise) |
| ポリシーティア | X | X | O (Enterprise) |
| ホストファイアウォール | X | O | O |
| 暗号化 | X | WireGuard/IPsec | WireGuard |
| マルチクラスター | X | Cluster Mesh | Calico Federation |
| CNCFステータス | 標準 | Graduated | - (Tigera商用) |
| GUI管理 | X | Hubble UI | Calico Enterprise UI |
実装ガイド
段階的Default Deny適用
プロダクション環境でDefault Denyを一度に適用すると、大規模障害が発生する可能性がある。以下は安全な段階的適用手順である。
ステップ1: 監査モードで開始(Cilium)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: audit-default-deny
namespace: staging
annotations:
policy.cilium.io/audit-mode: 'true'
spec:
endpointSelector: {}
ingress:
- fromEndpoints:
- matchLabels:
reserved:host: ''
egress:
- toEndpoints:
- matchLabels:
reserved:host: ''
監査モードでは、ポリシーが実際にトラフィックをブロックせず、ブロック対象となるトラフィックをHubbleを通じてログとして記録する。
ステップ2: Hubbleでトラフィック分析
# Hubble CLIでポリシーによって監査されたトラフィックを確認
hubble observe --namespace staging --verdict AUDIT --output json | \
jq '.flow | {src: .source.labels, dst: .destination.labels, port: .l4.TCP.destination_port}'
# ネームスペース内の通信パターンを把握
hubble observe --namespace staging --type trace:to-endpoint \
--output compact --last 1000
ステップ3: 許可ポリシー作成後、Default Denyを有効化
監査ログ分析結果に基づいて必要な許可ポリシーをすべて作成した後、監査モードのannotationを削除してポリシーを有効化する。
マイクロサービスポリシーパターン
実際のマイクロサービス環境でよく使用されるポリシーパターンである。
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: microservice-pattern
namespace: ecommerce
spec:
endpointSelector:
matchLabels:
app: order-service
ingress:
- fromEndpoints:
- matchLabels:
app: api-gateway
toPorts:
- ports:
- port: '8080'
protocol: TCP
rules:
http:
- method: POST
path: '/orders'
- method: GET
path: '/orders/[0-9]+'
egress:
- toEndpoints:
- matchLabels:
app: inventory-service
toPorts:
- ports:
- port: '8080'
protocol: TCP
- toEndpoints:
- matchLabels:
app: payment-service
toPorts:
- ports:
- port: '8080'
protocol: TCP
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: '53'
protocol: ANY
このポリシーは、order-serviceがapi-gatewayからのみ注文関連HTTPリクエストを受け付け、inventory-serviceとpayment-serviceとのみ通信できるように制限する。
モニタリングとトラブルシューティング
Hubbleを活用したCiliumモニタリング
HubbleはCiliumに内蔵されたネットワーク観測ツールで、eBPFベースですべてのネットワークフローをリアルタイムで収集する。
# Hubble有効化(Cilium Helmインストール時)
helm upgrade cilium cilium/cilium \
--namespace kube-system \
--set hubble.enabled=true \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true
# 特定ネームスペースでブロックされたトラフィックを確認
hubble observe --namespace production --verdict DROPPED \
--output json --last 100
# 特定Pod間の通信を追跡
hubble observe --from-pod production/api-server-7d9f8b6c5d-x2k4m \
--to-pod production/database-5f7b9c8d6e-m3n7p --output compact
# ポリシー適用状態を確認
cilium policy get --endpoint 12345
# Ciliumエンドポイントの状態を確認
cilium endpoint list -o json | \
jq '.[] | select(.status.policy.realized.denied > 0) | {id: .id, labels: .status.labels}'
calicoctlを活用したCalicoトラブルシューティング
# Calicoノード状態確認
calicoctl node status
# 適用されたポリシー一覧確認
calicoctl get networkpolicy --all-namespaces -o wide
calicoctl get globalnetworkpolicy -o wide
# 特定ワークロードのポリシー評価シミュレーション
calicoctl get workloadendpoint --all-namespaces -o yaml | \
grep -A 5 "api-server"
# Felixログでポリシー適用を確認
kubectl logs -n calico-system -l k8s-app=calico-node -c calico-node \
--tail=100 | grep -i "policy"
# BGPピア状態確認
calicoctl node status | grep -A 10 "BGP"
Prometheusメトリクス収集
CiliumとCalicoの両方がPrometheusメトリクスを公開している。
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: cilium-metrics
namespace: monitoring
spec:
selector:
matchLabels:
k8s-app: cilium
namespaceSelector:
matchNames:
- kube-system
endpoints:
- port: metrics
interval: 15s
path: /metrics
主要なモニタリングメトリクスは以下の通りである。
cilium_policy_verdict_total: ポリシー判定結果(FORWARDED、DROPPED、AUDIT)カウンターcilium_drop_count_total: ポリシーによってドロップされたパケット数cilium_policy_import_errors_total: ポリシーパースエラー数calico_felix_active_local_policies: Felixがアクティブに管理しているポリシー数calico_felix_iptables_save_errors: iptablesルール保存エラー数
障害事例と復旧手順
事例1: Default Deny一括適用による全サービスダウン
状況: 運用チームがプロダクションネームスペースにDefault Denyポリシーをテストなしで適用。DNS許可ポリシーを漏れたため、すべてのサービスのサービスディスカバリが失敗し、連鎖的にすべてのマイクロサービスが相互通信不能状態に陥った。
症状:
- すべてのPodのreadiness probe失敗
- サービス間HTTPリクエストタイムアウト
- DNSクエリ応答なし
復旧手順:
# 1. 緊急措置: 問題を起こしたDefault Denyポリシーを削除
kubectl delete networkpolicy default-deny-all -n production
# 2. 状態確認
kubectl get pods -n production -o wide
kubectl get endpoints -n production
# 3. DNS通信確認
kubectl exec -n production deploy/api-server -- nslookup kubernetes.default
# 4. 根本原因分析後、正しいポリシーセットを再適用
# - DNS許可ポリシーを最初に適用
kubectl apply -f allow-dns-egress.yaml
# - サービス間通信ポリシーを適用
kubectl apply -f service-communication-policies/
# - Default Denyを最後に適用
kubectl apply -f default-deny-all.yaml
教訓: Default Denyは必ず許可ポリシーを先に適用した後、最後に適用しなければならない。ステージング環境での事前検証は必須である。
事例2: Cilium DNSポリシーとCoreDNSキャッシュの不整合
状況: CiliumのFQDNベースEgressポリシーを適用したが、CoreDNSのキャッシュされたDNS応答がCiliumのDNSプロキシをバイパスし、ポリシーが適用されない問題が発生した。
症状:
- 特定のFQDNポリシーが断続的に動作しない
- HubbleでそのFQDNに対するDNSクエリが観測されない
- CoreDNSキャッシュTTLが期限切れになるとポリシーが正常動作
復旧手順:
# 1. CoreDNSキャッシュ確認
kubectl exec -n kube-system deploy/coredns -- \
curl -s http://localhost:9153/metrics | grep 'coredns_cache'
# 2. Cilium DNSプロキシログ確認
cilium monitor --type drop --related-to fqdn
# 3. DNSポリシー再適用とCilium Agent再起動
kubectl rollout restart daemonset/cilium -n kube-system
# 4. CoreDNS設定でCilium DNSプロキシ経由のフォワーディングを確認
kubectl get configmap coredns -n kube-system -o yaml
事例3: Calicoポリシー順序の競合
状況: 2つのチームが独立してGlobalNetworkPolicyを作成し、order値が同一のポリシーが生成された。意図しないAllowルールがDenyより先に評価され、セキュリティポリシーが無効化された。
症状:
- ブロックすべきトラフィックが許可されている
- calicoctlでポリシー順序の競合を発見
復旧手順:
# 1. すべてのGlobalNetworkPolicyのorderを確認
calicoctl get globalnetworkpolicy -o yaml | grep -E "name:|order:"
# 2. 競合ポリシーのorderを修正
calicoctl apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: security-block-external
spec:
order: 50
selector: all()
types:
- Egress
egress:
- action: Deny
destination:
notNets:
- 10.0.0.0/8
EOF
# 3. ポリシー適用順序を検証
calicoctl get globalnetworkpolicy -o wide | sort -k3 -n
プロダクションデプロイチェックリスト
事前準備
- CNIプラグイン(Cilium/Calico)がインストールされ正常に動作しているか確認
- すべてのネームスペースに適切なラベルが設定されているか確認
- すべてのワークロードにapp、roleなどの選択用ラベルがあるか確認
- kube-systemネームスペースの重要サービス(CoreDNS、metrics-server)に対する許可ポリシーを準備
ポリシー適用順序
- ステップ1: DNS許可ポリシーをすべてのネームスペースに適用
- ステップ2: kube-systemネームスペースとの必須通信を許可
- ステップ3: サービス間通信許可ポリシーを適用
- ステップ4: 外部通信許可ポリシーを適用
- ステップ5: Default Denyポリシーをステージングで先にテスト
- ステップ6: プロダクションにDefault Denyを適用(トラフィックモニタリング併行)
モニタリング必須項目
- Hubbleまたはcalicoctlでドロップされたトラフィックのリアルタイムモニタリングを構成
- Prometheus + Grafanaダッシュボードにポリシー関連メトリクスを追加
- ポリシー違反時のPagerDuty/Slackアラートを設定
- 定期的なポリシー監査(Policy Audit)の自動化を構成
運用上の注意事項
- ポリシー変更時は必ず
--dry-run=clientオプションで事前検証 - CIDRベースポリシーはIP変更に脆弱なため、ラベルベースポリシーを優先使用
- Headless Serviceの場合、Pod IPが直接使用されるため別途ポリシーを検討
- NodePort、LoadBalancerサービスのIngressトラフィック経路を確認
- Cilium Host Policy使用時、ノード間通信(kubelet、etcd)遮断に注意
- ポリシーバックアップとGitリポジトリ管理(GitOps連携推奨)
ロールバック計画
- 緊急時にDefault Denyポリシーを即座に削除できるスクリプトを準備
- ポリシー変更前後のHubble/calicoctlスナップショット比較プロセスを整備
- ロールバック対象ポリシーの以前バージョンをGitから即座に復元できるパイプラインを構成
高度なパターン: マルチクラスターネットワークポリシー
Cilium Cluster Mesh
Cilium Cluster Meshを使用すると、複数のクラスターにまたがってネットワークポリシーを適用できる。
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: cross-cluster-policy
namespace: shared-services
spec:
endpointSelector:
matchLabels:
app: shared-database
ingress:
- fromEndpoints:
- matchLabels:
app: backend
io.cilium.k8s.policy.cluster: cluster-east
toPorts:
- ports:
- port: '5432'
protocol: TCP
- fromEndpoints:
- matchLabels:
app: backend
io.cilium.k8s.policy.cluster: cluster-west
toPorts:
- ports:
- port: '5432'
protocol: TCP
Calico Federation
CalicoではFederationを通じて、リモートクラスターのサービスに対するネットワークポリシーを構成できる。
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: federated-service-access
spec:
selector: app == 'frontend'
types:
- Egress
egress:
- action: Allow
destination:
selector: app == 'api-gateway'
namespaceSelector: global()
protocol: TCP
まとめ
Kubernetesネットワークポリシーは、クラスターセキュリティの中核的なコンポーネントである。標準のNetworkPolicyだけでもL3/L4レベルの分離を実装できるが、実際のプロダクション環境ではCiliumやCalicoのようなCNIプラグインの高度な機能が不可欠である。
Ciliumは、eBPFベースの高性能データプレーン、L7ポリシー、DNSベースのEgress制御、Hubbleオブザーバビリティを強みとする。Calicoは、BGPルーティング統合、GlobalNetworkPolicy、ポリシーティアシステムでエンタープライズ環境に適している。
どのソリューションを選択しても、Default Deny戦略に基づくゼロトラストアプローチを採用し、ポリシー適用前に必ず監査モードとステージング環境で十分な検証を行うべきである。ネットワークポリシーは一度適用して終わりではなく、サービスの進化に合わせて継続的に管理・更新すべき生きたセキュリティ要素であることを忘れてはならない。