Network Policy
Kubernetes で Pod 間のネットワーク通信を制御し、不要な通信を遮断するセキュリティ機能
Network Policy とは
Network Policy は、Kubernetes で Pod 間のネットワーク通信をホワイトリスト方式で制御するリソースである。デフォルトでは Kubernetes クラスター内の全 Pod が相互に通信可能だが、Network Policy を適用すると、明示的に許可された通信のみが可能になる。
これはクラスター内のファイアウォールルールに相当する。従来のネットワークセキュリティが「サーバー間」の通信制御だったのに対し、Network Policy は「Pod 間」という、より細かい粒度で制御できる点が特徴だ。
なぜ必要なのか
Kubernetes のデフォルト設定では、同一クラスター内の全 Pod がフラットなネットワークで接続されている。これは開発の利便性は高いが、セキュリティ上は危険だ。
たとえば、フロントエンド Pod が侵害された場合、攻撃者はそこからデータベース Pod に直接アクセスできてしまう。本来フロントエンドはバックエンド API を経由してのみデータベースにアクセスすべきだが、ネットワークレベルでの制限がなければ、アプリケーションレイヤーの制御を迂回できる。
Network Policy を適用すれば、「フロントエンド → バックエンド API → データベース」という正規の通信経路のみを許可し、「フロントエンド → データベース」の直接通信を遮断できる。
基本的な構文
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-policy
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes: ["Ingress", "Egress"]
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
- namespaceSelector:
matchLabels:
env: production
ports:
- port: 8080
protocol: TCP
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- port: 5432
protocol: TCP
- to: # DNS 解決を許可
- namespaceSelector: {}
ports:
- port: 53
protocol: UDP
この例では api Pod に対して以下を制御している。
- 受信 (Ingress):
frontendPod からの 8080/TCP のみ許可 - 送信 (Egress):
databasePod への 5432/TCP と DNS (53/UDP) のみ許可
よくある落とし穴
DNS の Egress 許可忘れ
Egress ルールを設定する際、DNS (UDP 53) の許可を忘れるケースが非常に多い。Egress を制限した瞬間に Pod が名前解決できなくなり、全ての外部通信が失敗する。Network Policy を初めて導入するチームがほぼ確実にハマるポイントだ。
podSelector と namespaceSelector の AND/OR
from 配列内の要素は OR 条件だが、1 つの要素内に podSelector と namespaceSelector を並べると AND 条件になる。この挙動は直感に反するため、意図しない許可や拒否が発生しやすい。
# OR: frontend Pod または production namespace の全 Pod
- from:
- podSelector:
matchLabels:
app: frontend
- namespaceSelector:
matchLabels:
env: production
# AND: production namespace 内の frontend Pod のみ
- from:
- podSelector:
matchLabels:
app: frontend
namespaceSelector:
matchLabels:
env: production
デフォルト拒否ポリシーの未設定
Network Policy は「追加」で動作する。Pod に Network Policy が 1 つも適用されていなければ、全通信が許可される。まず全拒否のデフォルトポリシーを適用し、その上で必要な通信を個別に許可する設計が安全だ。
# 全拒否のデフォルトポリシー
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {} # namespace 内の全 Pod に適用
policyTypes: ["Ingress", "Egress"]
CNI プラグインの対応状況
Network Policy は Kubernetes の標準 API だが、実際の通信制御は CNI (Container Network Interface) プラグインが担う。CNI プラグインが Network Policy をサポートしていなければ、リソースを作成しても何も起きない。エラーも出ないため、「設定したのに通信が制限されない」という事態になる。
| CNI プラグイン | Network Policy サポート | 特徴 |
|---|---|---|
| Calico | ✅ 完全対応 | L3/L4 制御、GlobalNetworkPolicy で全 namespace 横断 |
| Cilium | ✅ 完全対応 + 拡張 | L7 (HTTP, gRPC) レベルの制御も可能 |
| AWS VPC CNI | ⚠️ v1.14+ で対応 | EKS のデフォルト。以前は非対応で Calico の追加が必要だった |
| Flannel | ❌ 非対応 | Network Policy を使うなら Calico に移行が必要 |
段階的な導入戦略
本番クラスターに Network Policy を一気に導入すると、想定外の通信が遮断されてサービス障害を引き起こすリスクがある。以下の段階で導入する。
- 監査モード: Cilium の Policy Audit Mode や Calico のログモードで、現在の通信パターンを可視化する
- 非本番環境で検証: staging 環境で Network Policy を適用し、アプリケーションの動作を確認する
- namespace 単位で段階適用: 影響範囲の小さい namespace から順に本番適用する
- 全拒否デフォルトの適用: 全 namespace にデフォルト拒否ポリシーを適用し、ホワイトリスト方式に移行する
基礎から学ぶなら関連書籍が手がかりになる。