Kubernetesの「裸の王様」を卒業せよ:NetworkPolicyによるマイクロセグメンテーションの実践
「うちはクラウドのマネージドサービスを使っているから大丈夫」
インシデント対応の現場で、何度この言葉を聞いたことだろう。残念ながら、Kubernetes(K8s)におけるデフォルトのネットワーク設定は、「全Podが全Podと通信可能」という、セキュリティの観点では極めて無防備な状態だ。
これは、オフィスビルに入り込んだ侵入者が、受付を通らずに社長室から倉庫まで全ての部屋の鍵を勝手に開けられる状態と同じだ。今回は、この「放置された盲点」を塞ぐための、泥臭くも堅牢なマイクロセグメンテーションの実装を解説する。
—
なぜ「デフォルト全許可」が死を招くのか
攻撃者がPodの一つ(例えば、脆弱なWebアプリケーションのPod)に侵入したとしよう。彼らが最初に行うのは、内部ネットワークの偵察だ。
もしマイクロセグメンテーションが未実装なら、攻撃者はPod内部から直接データベース(DB)へ接続を試みたり、内部APIを叩いて機密情報を盗み出したりする。「境界防御(WAFやロードバランサ)」がどれほど強固でも、一度侵入を許せば内部はガラ空き。 これがKubernetesにおける最大の脆弱性だ。
—
実装戦略:ホワイトリスト形式での「ゼロトラスト」
Kubernetesの NetworkPolicy は、デフォルトの「全許可」を「全拒否」に覆す強力な武器だ。まずは、「何も通さない」というルールを定義し、必要な通信だけを穴開けする。
1. 全通信をブロックする「Deny-All」ポリシー
まずは、クラスタ内の全Podに対して、入出力の通信を遮断する。これを適用しない限り、ホワイトリストは機能しない。
# deny-all.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: default-deny-all
namespace: production # 適用したい名前空間を指定
spec:
podSelector: {} # セレクタを空にすることで全てのPodを対象にする
policyTypes:
- Ingress
- Egress
2. 特定の通信のみを許可する(最小権限の原則)
次に、必要な通信だけを許可する。例えば、「frontend」Podから「backend-api」Podへの通信のみを許可する設定は以下のようになる。
# allow-frontend-to-backend.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend-api # 宛先のPodラベル
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend # 許可元のPodラベル
ports:
- protocol: TCP
port: 8080 # バックエンドが待ち受けているポート
—
実務でハマる「落とし穴」と鉄則
現場のエンジニアがこの設定で必ずと言っていいほど躓くポイントがある。
DNS解決を忘れるな
Egress(出口)のポリシーを厳しくしすぎると、Podが内部DNS(CoreDNS)に問い合わせできなくなり、外部URLへの通信が軒並み失敗する。以下の設定を忘れないようにしてほしい。
# allow-dns-egress.yaml
egress:
- to:
- namespaceSelector: {} # kube-system名前空間等のDNSを参照できるようにする
ports:
- protocol: UDP
port: 53
ラベル管理は「神」である
NetworkPolicy は podSelector のラベルに依存する。開発環境と本番環境で同じラベルを使ったり、ラベル付けを自動化せず手動で行うと、意図しない通信遮断(DoS状態)を引き起こす。ラベル運用はCI/CDパイプラインで強制すべきだ。
—
セキュリティチーフからの「最後のアドバイス」
NetworkPolicyの実装は、パズルに似ている。最初は複雑に感じるだろう。だが、一度この「ホワイトリスト管理」という規律をチームに浸透させれば、万が一コンテナが乗っ取られたとしても、攻撃者の横方向への移動(ラテラルムーブメント)を確実に封じ込めることができる。
「とりあえず動く」を脱却し、「安全に動かす」をエンジニアの誇りにしよう。設定を反映する際は、必ず kubectl apply --dry-run=client で構成をチェックし、ステージング環境で入念な通信テストを行ってから本番へ適用すること。
セキュリティとは、派手なハッキングを防ぐことではなく、こうした「退屈で地味な設定」を誰よりも丁寧に積み重ねることの延長線上にある。健闘を祈る。
コメント