- フラットネットワークの問題
- ネットワークポリシーの登場:Kubernetesのゼロトラスト
- エンタープライズがこれを無視できない理由
- 代替手段:属性ベースファイアウォールとサービスメッシュ
- 比較:ネットワークポリシー vs サービスメッシュ vs ABACファイアウォール
- 実世界での実装
- 始め方
- 結論
Kubernetesの世界には、多くのエンタープライズが見落としている危険なデフォルト設定があります。それは、すべてのPodが、すべての名前空間を越えて、制限なく他のすべてのPodと通信できるということです。これは、すべてのドアが開錠され、すべてのファイルキャビネットが開いており、すべての従業員がすべての部屋にアクセスできるオフィスを建てるようなものです。便利でしょうか?はい。安全でしょうか?絶対に違います。
機密データの取り扱い、規制コンプライアンス、またはマルチテナント環境を扱うエンタープライズにとって、このフラットなネットワークモデルは時限爆弾です。1つの侵害されたPodが、クラスタ全体への横方向の移動の起点となる可能性があります。ここでKubernetesネットワークポリシーが重要になるだけでなく、不可欠になります。
フラットネットワークの問題
Kubernetesはシンプルさを念頭に設計されました。デフォルトでは、ネットワークモデルはフラットです。つまり、どのPodもIPアドレスを使用して他のPodに到達できます。これにより開発が容易になり、ネットワークの複雑さが解消されますが、大きなセキュリティギャップが生じます。
典型的なエンタープライズアプリケーションを考えてみましょう:
- ユーザーリクエストを処理するフロントエンドPod
- ビジネスロジックを処理するバックエンドAPI Pod
- 機密性の高い顧客データを保存するデータベースPod
- クラスタ管理用の管理者Pod
- 外部サービスに接続するサードパーティ統合Pod
デフォルトのKubernetes設定では、侵害されたフロントエンドPodがデータベースPodに直接アクセスできます。悪用されたサードパーティ統合が管理ツールに到達できます。障壁も、チェックポイントも、セグメンテーションもありません。
🚨 侵害シナリオ
攻撃者が公開されているWebアプリケーションの脆弱性を悪用します。フロントエンドPodへのシェルアクセスを取得します。ネットワークポリシーがなければ、クラスタ全体をスキャンし、データベースPodを発見し、顧客データを流出させることができます。これらの接続を阻止するものが何もないためです。
これは理論的な話ではありません。2020年のTesla Kubernetes侵害は、公開されたKubernetesダッシュボードが、クラスタ内の他の場所に保存されたAWS認証情報にアクセスできる侵害されたPodにつながったために発生しました。ネットワークセグメンテーションがあれば、被害範囲を制限できたでしょう。
ネットワークポリシーの登場:Kubernetesのゼロトラスト
Kubernetesネットワークポリシーは、Podが互いに、および外部エンドポイントとどのように通信できるかを定義する仕様です。これはクラスタのファイアウォールですが、IPアドレスとポートの代わりに、Podラベル、名前空間、CIDRブロックに基づいてルールを定義します。
核となる原則はシンプルです:デフォルトで拒否し、明示的に許可する。これがゼロトラストネットワーキングです。必要であることが証明されるまで、何も信頼されません。
基本的なネットワークポリシーは次のようになります:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
このポリシーは次のように述べています:「バックエンドPodは、ポート8080でフロントエンドPodからのトラフィックのみを受信でき、ポート5432でデータベースPodにのみトラフィックを送信できます。」それ以外はすべてブロックされます。
✅ 多層防御
ネットワークポリシーは、アプリケーションレベルのセキュリティ、認証、または暗号化に取って代わるものではありません。これらは多層防御戦略の1つのレイヤーです。攻撃者がPodを侵害したとしても、ネットワークポリシーは到達できる範囲を制限します。
エンタープライズがこれを無視できない理由
エンタープライズにとって、ネットワークポリシーはオプションではありません。コンプライアンスとセキュリティの必要性です:
規制コンプライアンス:PCI-DSS、HIPAA、SOC 2などの標準では、ネットワークセグメンテーションが必要です。機密データが信頼性の低いコンポーネントから分離されていることを実証する必要があります。ネットワークポリシーは、監査可能で宣言的なセグメンテーションの証拠を提供します。
マルチテナンシー:同じクラスタで複数のチームまたは顧客を実行している場合、ネットワークポリシーは1つのテナントが別のテナントのリソースにアクセスするのを防ぎます。これらがなければ、名前空間の分離は純粋に論理的であり、強制されません。
被害範囲の制限:セキュリティインシデントが発生した場合(発生しないかではなく、いつ発生するか)、ネットワークポリシーは被害を封じ込めます。開発名前空間で侵害されたPodは本番環境に到達できません。侵害されたフロントエンドはデータベースに直接アクセスできません。
監査と可視性:ネットワークポリシーは宣言的であり、バージョン管理されています。誰が何をいつ、なぜ変更したかを監査できます。これをネットワークアプライアンスに埋め込まれた従来のファイアウォールルールと比較してください。
コスト効率:各セキュリティゾーンに個別のクラスタをデプロイする代わりに(高価で運用が複雑)、ネットワークポリシーを使用して単一のクラスタ内に安全な境界を作成できます。
📊 コンプライアンス要件
PCI-DSS要件1.2.1は、カード会員データ環境に必要なトラフィックに対する受信および送信トラフィックの制限を明示的に義務付けています。ネットワークポリシーは、この要件を満たすKubernetesネイティブな方法です。
代替手段:属性ベースファイアウォールとサービスメッシュ
ネットワークポリシーだけが選択肢ではありません。エンタープライズには、Kubernetesネットワーキングを保護するための他のオプションがあります:
従来のファイアウォール:ノードレベルの罠
従来のネットワークファイアウォールまたはクラウドセキュリティグループを使用して、Kubernetesノード間のトラフィックを制御できます。しかし、このアプローチには、多くのエンタープライズが遅すぎる段階で発見する致命的な欠陥があります。
問題点:従来のファイアウォールは、Podレベルではなく、ノードレベルで動作します。これが危険な理由は次のとおりです:
3つのPodを実行しているKubernetesノードがあるとします:
- Pod A:フロントエンドアプリケーション(CDNのためにインターネットアクセスが必要)
- Pod B:バックエンドAPI(インターネットにアクセスすべきではない)
- Pod C:データベース(絶対にインターネットにアクセスしてはならない)
従来のファイアウォールでは、Pod Aが必要とするため、ノードのセキュリティグループを構成してアウトバウンドインターネットアクセスを許可します。しかし、ここに落とし穴があります:3つのPodすべてがインターネットアクセスを持つようになります。ファイアウォールはPodを区別できません。ノードのIPアドレスしか認識しません。
これは次のことを意味します:
- データベースPodが外部サーバーにデータを流出させることができる
- バックエンドAPIがアウトバウンド攻撃のプロキシとして使用される可能性がある
- 侵害されたPodがマルウェアをダウンロードしたり、コマンド&コントロールサーバーと通信したりできる
🔓 ノードレベルのセキュリティギャップ
ファイアウォールルールがノードにインターネットへのアクセスを許可する場合(1つのPodのためだけであっても)、そのノード上のすべてのPodがそのアクセスを継承します。従来のファイアウォールでは、Pod固有のエグレスポリシーを強制できません。これが、ノードレベルのセキュリティがKubernetesには不十分である理由です。
(インターネットが必要)"] PodB1["Pod B
(インターネットにアクセスすべきでない)"] PodC1["Pod C - データベース
(インターネットにアクセスしてはならない)"] end PodA1 -->|"✓ 許可"| Internet1["インターネット"] PodB1 -->|"✓ 許可(問題!)"| Internet1 PodC1 -->|"✓ 許可(危険!)"| Internet1 end subgraph "ネットワークポリシー(Podレベル)" Node2["Kubernetesノード"] subgraph Node2 PodA2["Pod A
(インターネットが必要)"] PodB2["Pod B
(インターネットにアクセスすべきでない)"] PodC2["Pod C - データベース
(インターネットにアクセスしてはならない)"] end NP1["ネットワークポリシー:
Pod Aのみ許可"] NP1 -.->|"特定のPodに適用"| PodA2 PodA2 -->|"✓ 許可"| Internet2["インターネット"] PodB2 -.->|"✗ ブロック"| Internet2 PodC2 -.->|"✗ ブロック"| Internet2 end style PodB1 fill:#ffcccc style PodC1 fill:#ff9999 style PodB2 fill:#ccffcc style PodC2 fill:#ccffcc style FW1 fill:#ffeecc style NP1 fill:#ccffee
その他の制限事項:
- IPベース、Podベースではない:Podは動的IPを持つ一時的なものです。IPアドレスに基づくファイアウォールルールは、Podが作成および破棄されるにつれて管理不能になります。
- Kubernetesの認識がない:ファイアウォールは名前空間、ラベル、またはPodセレクタを理解しません。宣言的でKubernetesネイティブなアプローチを失います。
- 粗粒度の制御:ノードレベルでのみトラフィックを制御でき、実際のセキュリティ境界が存在するワークロードレベルでは制御できません。
属性ベースアクセス制御(ABAC)ファイアウォール
一部の次世代ファイアウォールは、IPアドレスではなくメタデータ属性を使用してルールを定義する属性ベースのポリシーをサポートしています。これは哲学的にはKubernetesネットワークポリシーに近いものです:
- メタデータ駆動:アプリケーションID、ユーザーコンテキスト、またはワークロード属性に基づくルール
- 動的:手動でIPを更新することなく、ワークロードの変更に応じてポリシーが適応
- 集中管理:インフラストラクチャ全体の単一ポリシーエンジン
ただし、ABACファイアウォールは通常Kubernetesの外部にあり、統合が必要で、多くの場合かなりのコストがかかります。ハイブリッド環境(Kubernetes + VM +クラウドサービス)には強力ですが、複雑さが増します。
サービスメッシュ(Istio、Linkerd、Consul)
サービスメッシュは、レイヤー7(アプリケーションレベル)のトラフィック管理とセキュリティを提供します:
- 相互TLS:サービス間の自動暗号化と認証
- きめ細かいポリシー:HTTPメソッド、ヘッダー、パスに基づく制御
- 可観測性:詳細なトラフィックメトリクスとトレーシング
- 高度なルーティング:カナリアデプロイメント、トラフィック分割、リトライ
サービスメッシュは非常に強力ですが、トレードオフがあります:
複雑さ:大きな学習曲線と運用オーバーヘッド。すべてのPodにサイドカーを追加し、コントロールプレーンを管理し、新しいインフラストラクチャレイヤーをデバッグすることになります。
パフォーマンスオーバーヘッド:サイドカープロキシはレイテンシ(通常ホップあたり1〜5ms)とリソース消費を追加します。
コスト:より多くのリソース、より多くの複雑さ、より多くの運用負担。
💡 何をいつ使用するか
ネットワークポリシー:ここから始めましょう。Kubernetesに組み込まれており、実装が簡単で、エンタープライズセキュリティニーズの80%をカバーします。追加のインフラストラクチャは不要です。
サービスメッシュ:相互TLS、高度なルーティング、または詳細な可観測性などのレイヤー7機能が必要な場合に追加します。複雑なサービス間通信を持つマイクロサービスアーキテクチャに最適です。
ABACファイアウォール:Kubernetes、VM、クラウドサービス全体で一貫したポリシーが必要なハイブリッド環境を検討してください。通常、Kubernetesだけでなく、エンタープライズ全体の決定です。
比較:ネットワークポリシー vs サービスメッシュ vs ABACファイアウォール
機能 | ネットワークポリシー | サービスメッシュ | ABACファイアウォール |
---|---|---|---|
レイヤー | レイヤー3/4(IP/ポート) | レイヤー7(HTTP/gRPC) | レイヤー3-7 |
複雑さ | 低 | 高 | 中 |
パフォーマンス影響 | 最小限 | 1〜5msレイテンシ | 製品による |
コスト | 無料(組み込み) | リソースオーバーヘッド | ライセンスコスト |
暗号化 | なし(別のソリューションが必要) | 相互TLS含む | 製品による |
可観測性 | 基本(CNI依存) | 優れている | 良好 |
Kubernetesネイティブ | はい | はい | いいえ |
学習曲線 | 緩やか | 急 | 中程度 |
最適な用途 | 基本的なセグメンテーション | マイクロサービスセキュリティ | ハイブリッド環境 |
実世界での実装
実用的な例を見てみましょう:3層アプリケーションの保護。
アーキテクチャ:
- フロントエンドPod(公開)
- バックエンドAPI Pod(内部)
- データベースPod(機密データ)
セキュリティ要件:
- フロントエンドはバックエンドAPIとのみ通信可能
- バックエンドAPIはデータベースとのみ通信可能
- データベースはバックエンドからの接続のみを受け入れる
- フロントエンド以外のPodはインターネットにアクセスできない(CDNアセット用)
実装:
# デフォルトですべてのトラフィックを拒否
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# フロントエンドが外部トラフィックを受信できるようにする
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-policy
namespace: production
spec:
podSelector:
matchLabels:
tier: frontend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 80
egress:
- to:
- podSelector:
matchLabels:
tier: backend
ports:
- protocol: TCP
port: 8080
- to:
- namespaceSelector: {}
podSelector: {}
ports:
- protocol: TCP
port: 443 # CDN用のHTTPSを許可
---
# バックエンドがデータベースとのみ通信できるようにする
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: production
spec:
podSelector:
matchLabels:
tier: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
tier: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
tier: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53 # DNSを許可
---
# データベースはバックエンドからの接続のみを受け入れる
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-policy
namespace: production
spec:
podSelector:
matchLabels:
tier: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: backend
ports:
- protocol: TCP
port: 5432
この設定により、明確な境界が作成されます。攻撃者がフロントエンドを侵害したとしても、データベースに直接アクセスすることはできません。機密データに到達するには、フロントエンドとバックエンドの両方を侵害する必要があり、ハードルが大幅に上がります。
⚠️ DNSを忘れずに
よくある間違いは、DNSトラフィックを許可するのを忘れることです。Podはサービス名をIPアドレスに解決する必要があります。kube-dnsまたはCoreDNSのエグレスルールを常に含めてください。通常、UDPポート53です。
始め方
ネットワークポリシーの実装は、オールオアナッシングである必要はありません。実用的なアプローチは次のとおりです:
1. CNIサポートの確認:すべてのContainer Network Interface(CNI)プラグインがネットワークポリシーをサポートしているわけではありません。Calico、Cilium、Weave Netはサポートしています。AWS VPC CNIとAzure CNIには追加の構成が必要です。CNIドキュメントを確認してください。
2. 監視から始める:ポリシーを強制する前に、監査モードでデプロイするか(CNIがサポートしている場合)、Cilium Hubbleなどのツールを使用して既存のトラフィックパターンを視覚化します。
3. deny-allから始める:重要でない名前空間にデフォルトのdeny-allポリシーを作成します。これにより、必要なトラフィックを明示的に許可する必要があり、実際の通信パターンが明らかになります。
4. 段階的にホワイトリスト化:一度に1つずつ許可ルールを追加し、各変更後にテストします。明白なフロー(フロントエンド→バックエンド)から始めて、エッジケースに向かって作業します。
5. テストの自動化:netassertなどのツールを使用して、ネットワークポリシーのテストを作成します。これにより、ポリシーが変更されたときの回帰を防ぎます。
6. ドキュメント化とバージョン管理:ポリシーをアプリケーションマニフェストと一緒にGitに保存します。各ルールが存在する理由を文書化します。将来のあなた(またはチームメイト)が感謝するでしょう。
🛠️ 役立つツール
- Cilium Editor:ビジュアルネットワークポリシーエディタ
- Network Policy Viewer:ポリシーをグラフとして視覚化
- Inspektor Gadget:リアルタイムでネットワークトラフィックをデバッグ
- Calico Enterprise:高度なポリシー管理(商用)
結論
Kubernetesネットワークポリシーは、エンタープライズにとってオプションではありません。これはクラスタセキュリティの基盤であり、横方向の移動に対する最初の防衛線であり、規制産業のコンプライアンス要件です。
はい、代替手段があります。サービスメッシュはより多くの機能を提供し、ABACファイアウォールはより広範なカバレッジを提供します。しかし、ネットワークポリシーはKubernetesに組み込まれており、追加のインフラストラクチャを必要とせず、最も重要な問題を解決します:無制限のPod間通信の防止。
シンプルに始めましょう。デフォルトのdenyポリシーをデプロイします。必要なトラフィックをホワイトリスト化します。徹底的にテストします。セキュリティチーム、コンプライアンス監査人、そして将来のインシデント対応者が感謝するでしょう。
Kubernetesでは、デフォルトは信頼です。エンタープライズにとって、標準はゼロトラストでなければなりません。ネットワークポリシーは、そこに到達する方法です。