こんにちは!インフラやセキュリティの世界へようこそ。
新しいシステムの開発や運用に関わるようになると、「Kubernetes(K8s)」や「マイクロサービス」といった、なんだか難しそうな言葉を耳にする機会が一気に増えますよね。
今日は、そんなモダンな開発環境で絶対に避けて通れない「Kubernetes NetworkPolicy(ネットワークポリシー)」について、身近な防犯の例えを交えながら、優しく、そして実務で即座に役立つレベルまでしっかり紐解いていきたいと思います。
一歩ずつ対策を学んでいけば、決して難しくありません。それでは、さっそく見ていきましょう!
—
1. 家の鍵に例える「デフォルト拒否(Default Deny)」の重要性
まず、あなたが新しいマンションに引っ越してきたところを想像してください。
このマンション、実は少し変わっていて、「最初は何もしなくても、全室の玄関のドアが全開。誰でもどの部屋にも自由に出入りできる状態」になっています。
「えっ、そんなの泥棒に入り放題じゃないですか!」と思いましたよね?その通り、セキュリティ的には最悪の状態です。
Kubernetesの初期状態も、これとまったく同じなんです。
Kubernetesのクラスタ(サーバーの集合体)の中には、ショッピングサイトの画面を表示する「フロントエンド」や、注文データを処理する「バックエンド」、顧客情報を保存する「データベース」など、たくさんの小さなプログラム(マイクロサービス)が「名前空間(Namespace)」という部屋ごとに分かれて同居しています。
何も設定していないデフォルトの状態では、「どの部屋の住民も、他のすべての部屋に自由に行き来できる状態」になっています。もし、一番外側の「フロントエンド」の部屋が悪い人に破られてしまったら、中の金庫がある「データベース」の部屋まで一直線に侵入されてしまいますよね。これが「横移動(ラテラルムーブメント)」と呼ばれる、攻撃者常習の手口です。
最初の防犯対策:まずは全部の鍵を閉める
この危険な状態を解消する最初のステップが、「デフォルト拒否(Default Deny)」という考え方です。
防犯の基本は、「すべて施錠し、合鍵を持っている信頼できる人だけに通る許可を出す」ことですよね。KubernetesのNetworkPolicyを使えば、まさにこの「全室の施錠」を簡単に実現できるのです。
—
2. NetworkPolicyとは?名前空間とラベルを使ったアクセス制御
「じゃあ、全部の部屋の鍵を閉めちゃったら、お隣の部屋に書類を届けたい時どうするの?」という疑問が湧きますよね。
そこで使うのが、「NetworkPolicy(ネットワークポリシー)」という交通ルールの設定です。これは、マンションの管理人に「A号室の人がB号室に行くのは許可するけれど、C号室に行くのは禁止」と指示するようなものです。
Kubernetesでは、部屋(名前空間)や、部屋の中にいる人たち(Pod)に「ラベル(Label)」という名札をつけて管理します。
例えば、以下のような名札を貼るとイメージしやすいでしょう。
app=frontend(フロントエンドの役割を持つ人)app=database(データベースの役割を持つ人)environment=production(本番環境の部屋にいる人)
このラベルを目印にして、「app=frontend の名札をつけた人だけは、app=database の部屋に入っていいよ」という具体的なルール(交通規制)を作っていくのが、ラベルベースのアクセス制御の仕組みです。
—
3. 【実践】名前空間間の通信を最小限に絞る設定ファイル
百聞は一見にしかず。実際に、実務で使えるKubernetesのNetworkPolicyの設定ファイル(YAML形式)を見てみましょう。
今回は、「database という名前空間にあるデータベースに対し、frontend という名前空間にあるアプリからしか通信を許可しない(それ以外はすべて拒否)」という、鉄壁の防犯ルールを作ってみます。
以下のコードを、実務の現場でそのまま、あるいは微調整して適用してみてください。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-database # このポリシーの名前(わかりやすい名前をつけましょう)
namespace: database # ルールを適用する「データベースの部屋(名前空間)」を指定
spec:
podSelector:
matchLabels:
app: my-database # この部屋の中の「my-database」というラベルがついたPodを守ります
policyTypes:
- Ingress # 「外から中に入ってくる通信(Ingress)」を制御の対象にします
ingress:
- from:
# 1. まず、「frontend」という名前空間全体からの通信を許可の対象にします
- namespaceSelector:
matchLabels:
project: production-frontend
# 2. さらに、その名前空間の中でも「app=frontend」というラベルを持つPodだけに絞り込みます
podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 3306 # データベースの通信でよく使われるMySQLのポート番号を許可
この設定のポイント
namespaceSelectorとpodSelectorの組み合わせ: 単に「別の部屋(名前空間)全体からの出入りを許可する」だけでなく、「その部屋にいる、特定の名札(app: frontend)を持った特定のシステムだけ」に絞り込んでいる点が、セキュリティ上の重要なポイントです。これぞ「最小権限の原則(必要最小限のものだけ許可する)」ですね。policyTypes: [Ingress]: 「入ってくる通信(Ingress)」を拒否すると宣言しています。これに加えて「出ていく通信(Egress)」も絞る設定を入れると、さらに安全性が高まります。
—
4. 現場の落とし穴:CSI/CNIプラグインの確認を忘れずに!
ここで、新人の担当者がやりがちな「現場の落とし穴」を一つお伝えしておきます。
「よし、今の設定ファイルをサーバーに適用したぞ!これで完璧だ!」と意気込んで通信テストをしてみても、なぜか設定が無視されて今まで通り通信できてしまうことがあります。
原因は何だと思いますか?
実は、Kubernetes自体は「こういうルールにしてね」という指示(NetworkPolicyのオブジェクト)を受け取るだけで、実際の交通整理(ドアの開け閉めや警備)を行っているのは、「CNI(Container Network Interface)プラグイン」と呼ばれるネットワーク用の拡張機能です。
よく使われる Flannel というシンプルなネットワークプラグインなどは、デフォルトではこのNetworkPolicyの交通整理機能(ルール解釈)をサポートしていません。
現場でNetworkPolicyを動かすためには、以下のようなセキュリティ機能に対応したCNIプラグインがクラスタに導入されている必要があります。
- Calico (カニコではなくカリコ。定番の人気プラグインです)
- Cilium (最近大注目のeBPFベースの超高速プラグイン)
- Antrea など
「あれ、設定したのに効かないな?」と思ったら、まずはインフラの先輩に「このクラスタのCNIってNetworkPolicyに対応していましたっけ?」と確認してみるのが、トラブルシューティングの近道です。
—
まとめ
今回は、Kubernetes NetworkPolicyを使った名前空間間の通信制御について解説しました。
1. デフォルト拒否: 最初はすべてのドアを施錠し、不要な横移動をシャットアウトする。
2. ラベルベースの制御: 「どの部屋の、どのアプリ(名札)からなら通信してよいか」を細かく指定する。
3. CNIプラグインの確認: ルールを正しく解釈・実行できるネットワーク環境が土台として必要。
セキュリティの対策は、最初の一歩を踏み出すときは難しく感じられますが、「誰に、どこまでの権限を与えるか」という考え方は現実世界の防犯とまったく同じです。
ぜひ、ご自身のプロジェクトや検証環境でもNetworkPolicyを取り入れて、安全で堅牢なマイクロサービス環境を作ってみてくださいね。一歩ずつ、確実にスキルアップしていきましょう!
コメント