Kubernetes ネットワークポリシー
Kubernetes のネットワークモデルでは、デフォルトですべてのポッドが他のすべてのポッドにアクセスできることが求められています。これは「フラットネットワーク」と呼ばれるのは、どのモデルでも続いているからです。Kubernetes ネットワークの設計と実装が大幅に簡素化され、拡張性が大幅に高まります。
第4章では、Kubernetes がネットワーク実装に適用する要件について説明します。
セキュリティは重要な問題です。実際には、特定のレベルのネットワークセグメンテーション方式で、一部のポッドのみが相互に通信できるようにし、Kubernetes のネットワークポリシーが画像に含まれていることを確認する必要があります。Kubernetes のネットワークポリシーは、VM インスタンスへのアクセスを制御するためにクラウドのセキュリティグループを使用する場合と同じ方法で、ポッドのグループに対してアクセス許可を定義します。
Kubernetes は、Kubernetes のリソースである NetworkPolicy オブジェクトを介してネットワークポリシーをサポートしています。これは、ポッド’、サービス、入口など、この章で先に学習した多くの他の人と同様です。ネットワークポリシーオブジェクトの役割は、ポッドのグループ間の通信をどのように許可するかを定義することです。
Kubernetes’ネットワークポリシーの仕組みをご確認ください。
1 Kubernetes クラスター内では、すべてのポッドがデフォルトで非分離され、すべての pod が任意のモデルで動作するようになっています。そのため、任意のポッドで他の pod と通信できます。
2. ここで、policy1 という名前のネットワークポリシーをポッド A に適用します。ポリシー policy1 では、pod A が pod B との通信を明示的に許可するルールを定義します。この場合、発信’側ポッドは、ネットワークポリシーの適用対象となるポッドであるため、ポッドによって pod として使用されます。
3. この瞬間には、以下のようなことが起こります。
ターゲットポッド A は pod B と通信できます。また、B がポリシーで許可されている唯一の pod であるため、ポッド b にのみ接続できます。ポリシールールの性質により、このルールをホワイトリストと呼ぶことができます。
ターゲットポッド A のみの場合、このネットワークポリシー policy1 のホワイトリストで明示的に許可されていない接続は拒否されます。’Policy1 は、Kubernetes のネットワークポリシーの性質によって適用されるため、明示的に定義する必要はありません。ここ’では、この暗黙のポリシーを「すべて拒否」ポリシーを呼び出してみましょう。
たとえば、policy1 やその他のネットワークポリシーには適用されない pod B や pod C などのターゲット化していないポッドの場合も、any モデルに従って処理が継続されます。そのため、影響を受けずに、クラスター内の他のすべてのポッドとの通信を続けることができます。これはもう1つの暗黙のポリシーであり、すべてのポリシーが許可されています。
Pod A が pod C と通信できるようにする場合は、ネットワークポリシー policy1 とルールを更新して、明示的に許可する必要があります。言い換えると、ホワイトリストを更新して、トラフィックのタイプ数を増やすことができるようにしておく必要があります。
ご覧のように、ポリシーを定義すると、少なくとも3つのポリシーがクラスターに適用されます。
明示的 policy1: これは、定義したネットワークポリシーです。ホワイトリストルールを使用して、選択した (ターゲット) ポッドに特定タイプのトラフィックを許可します。
暗黙的拒否すべてのネットワークポリシー: これにより、ターゲットポッドのホワイトリストに含まれていないその他すべてのトラフィックが拒否されます。
暗黙的に許可されるすべてのネットワークポリシー: これにより、policy1 によって選択されていないその他のターゲットではないポッドに対して、その他すべてのトラフィックを許可します。’「すべて拒否」と「すべてのポリシーをもう一度許可する」については、「第8章」をご覧ください。
ここでは、Kubernetes ネットワークポリシーの概要を示します。
Pod 固有: ネットワークポリシーの仕様は、rc や導入 do と同様に、ラベルに基づいて1つのポッドまたはポッドのグループに適用されます。
ホワイトリストベースのルール: ホワイトリストを構成する明示的なルール。各ルールには、許可する特定タイプのトラフィックが記述されています。このホワイトリストのルールに記載されていないその他のトラフィックはすべて、ターゲットポッド用に削除されることになります。
暗黙的に許可: ポッドは、ターゲットとしてネットワークポリシーによって選択された場合にのみ影響を受け、選択したネットワークポリシーによってのみ影響を受けます。Pod にネットワークポリシーが適用されていない場合は、この pod にすべてのポリシーを許可することが暗示的に示されています。つまり、非ターゲットポッドが任意のネットワークモデルを継続する場合は、
入口と出口の分離: ポリシールールは特定の方向に定義されている必要があります。方向には、入口、出口、なし、またはその両方を指定できます。
フローベース (パケットベースの比較): 開始パケットが許可されると、同じフローのリターンパケットも許可されます。たとえば、ポッド A に適用された受信ポリシーが受信 HTTP 要求を許可したとすると、HTTP 相互作用全体が pod A に許可されます。これには、双方向 TCP 接続の確立とすべてのデータおよび肯定応答が、どちらの方向にも含まれています。
ネットワークポリシーはネットワークコンポーネントによって実装されるため、ネットワークポリシーをサポートするネットワークソリューションを使用する必要があります。これを実装するためのコントローラがない状態でネットワークポリシーリソースを作成しただけでは、効果はありません。このガイドでは、Contrail はネットワークポリシーが実装されたネットワークコンポーネントを使用しています。第8章では’、これらのネットワークポリシーが Contrail でどのように機能するかをご紹介します。
ネットワークポリシーの定義
Kubernetes のその他すべてのオブジェクトと同様に、ネットワークポリシーは YAML ファイルで定義できます。例’を見てみましょう (第8章では同じ例を使用しています)。
#policy1-do.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: policy1 namespace: dev spec: podSelector: matchLabels: app: webserver-dev policyTypes: - Ingress - Egress ingress: - from: - ipBlock: cidr: 10.169.25.20/32 - namespaceSelector: matchLabels: project: jtac - podSelector: matchLabels: app: client1-dev ports: - protocol: TCP port: 80 egress: - to: - podSelector: matchLabels: app: dbserver-dev ports: - protocol: TCP port: 80
他’のセクションが自明であるため、この yaml ファイルのスペック部分を見てみましょう。この仕様は次のような構造になっています。
spec: podSelector: ...... policyTypes: - Ingress - Egress ingress: - from: ...... egress: - to: ......
ここでは、ネットワークポリシー定義 YAML ファイルを論理的に4つのセクションに分けることができることをご確認いただけます。
podSelector: ここで選択したポッドが定義されます。現在のネットワークポリシーが適用されるポッドを識別します。
policyTypes: ポリシールールのタイプを指定します。入口、出口、またはその両方。
入口ターゲットポッドの入口ポリシールールを定義します。
エグレスターゲットポッドの送信ポリシールールを定義します。
次に’、各セクションについて詳しく見ていきましょう。
ターゲットポッドの選択
ネットワークポリシーを定義する場合、Kubernetes はこのポリシーの適用対象となるポッドを知る必要があります。サービスがバックエンドポッドを選択する方法と同様に、ネットワークポリシーはラベルに基づいて、適用されるポッドを選択します。
podSelector: matchLabels: app: webserver-dev
ここでは、ラベルが付いたすべてのポッド app: webserver-dev
は、ネットワークポリシーによってターゲットポッドとして選択されています。以下の仕様の内容はすべて、ターゲットポッドのみに適用されます。
ポリシータイプ
2つ目のセクションでは、 policyTypes
ターゲットポッドの場合:
policyTypes: - Ingress - Egress
PolicyTypes は、入口、出口、または両方のいずれかです。さらに、次に説明するように、どちらのタイプも、1つ以上のルールの形式で特定のトラフィックタイプを定義します。
ポリシールール
入口と出口のセクションは、選択されたターゲットポッド’の視点から、トラフィックの方向を定義します。たとえば、次のような簡素化された例を考えてみましょう。
ingress: - from: - podSelector: matchLabels: app: client1-dev ports: - protocol: TCP port: 80 egress: - to: - podSelector: matchLabels: app: client1-dev ports: - protocol: TCP port: 8080
ターゲットポッドが webserver-dev pod で、クラスター内に pod client1-dev が1つしかない場合は、次のような2点が発生します。
入口の方向: pod webserver は、pod client1 から開始した宛先ポート80との間で TCP セッションを受け入れることができます。これは、パケットベースではなく Kubernetes のネットワークポリシーがフローベースであると回答した理由を示しています。TCP 接続を確立できませんでした。このポリシーがパケットベースで設計されている場合、受信 tcp 同期を受信するときに、送信 TCP 同期-ack を返すことが拒否されます。対応する発信ポリシーはありません。
出口方向: pod webserver は、宛先ポート8080を使用して TCP セッションを開始できます。
送信接続を通過するために、もう1つの終端は受信接続を許可する入口ポリシーを定義する必要があります。
ネットワークポリシールール
From または to ステートメントごとに、ネットワークポリシーのルールを定義します。
From 文は、入口ポリシールールを定義します。
A to 文は、送信ポリシールールを定義します。
どちらのルールでも、オプションでポート文を指定できます。これについては後ほど説明します。
そのため、複数のルールを定義して、それぞれの方向に複雑なトラフィックモードを許可することができます。
ingress: INGRESS RULE1 INGRESS RULE2 egress: EGRESS RULE1 EGRESS RULE2
各ルールは、ターゲットポッドが通信できるネットワークエンドポイントを識別します。ネットワークエンドポイントは、さまざまな方法で特定できます。
ipBlock: IP アドレスブロックに基づいてポッドを選択します。
namespaceSelector: 名前空間のラベルに基づいてポッドを選択します。
podSelector: ポッドのラベルに基づいてポッドを選択します。
PodSelector は、YAML ファイルの異なる場所で使用されたときに、異なる項目を選択します。以前 (仕様下)、ネットワークポリシーが適用されるポッドを選択しまし’た。これはターゲットポッドと呼ばれていました。ここでは、ルール (from または to の下) で、ターゲットポッドが通信するポッドを選択します。このような podピアリングポッドを呼び出すこともあります。
このため、ルールの YAML 構造は次のようになります。
ingress: - from: - ipBlock: ..... - namespaceSelector: ..... - podSelector: ..... ports: ......
たとえば、以下のように記述します。
ingress: - from: - ipBlock: cidr: 10.169.25.20/32 - namespaceSelector: matchLabels: project: jtac - podSelector: matchLabels: app: client1-dev ports: - protocol: TCP port: 80 egress: - to: - podSelector: matchLabels: app: dbserver-dev ports: - protocol: TCP port: 80
ここでは、入口ネットワークエンドポイントはサブネット 10.169.25.20/32 です。または、次のラベルプロジェクトを持つ名前空間のすべてのポッド: jtacまたは、ラベルアプリケーションを持つポッド: client1-現在の名前空間 (ターゲットポッドの名前空間) 内の dev、送信ネットワークポイントは pod dbserver-dev です。’すぐにポートの部分に到達します。
または
’また、すべてのポッドと通信するのではなく、名前空間の一部のポッドだけを指定することもできます。この例では、podSelector はすべて使用され、ターゲットポッドと同じ名前空間を前提としています。もう1つの方法は、namespaceSelector と共に podSelector を使用することです。この場合、ポッドが属する名前空間は、ターゲット pod’s の名前空間とは異なり、namespaceSelector と一致するラベルを持つものです。
たとえば、ターゲットポッドが webserver で、名前空間が dev であると仮定すると、ネームスペース qa のみが namespaceSelector というラベルを持つことになります。
ingress: - from: - namespaceSelector: matchLabels: project: qa podSelector: matchLabels: app: client1-qa
ここでは、ターゲットポッドは、名前空間の qa にあるポッド (またはラベルではない) とのみ通信できます。 app:
client1-qa
。
ここでは、以下の定義とはまったく異なるので注意してください。ターゲットポッドは、以下のようなポッドと通信できます。名前空間で qa
または (not AND) ラベル付き app: client1-qa
ターゲットポッド’s の名前空間 dev:
ingress: - from: - namespaceSelector: matchLabels: project: qa - podSelector: matchLabels: app: client1-qa
プロトコルとポート
入口と出口のルールのポートを指定することもできます。プロトコルタイプとプロトコルポートを同時に指定することもできます。たとえば、以下のように記述します。
egress: - to: - podSelector: matchLabels: app: dbserver-dev ports: - protocol: TCP port: 80
受信したポートは、ターゲットポッドが、指定されたポートとプロトコルの着信トラフィックを許可できることを伝えます。送信のポートは、ターゲットポッドが特定のポートとプロトコルへのトラフィックを開始できることを述べています。ポートが記載されていない場合は、すべてのポートとプロトコルが許可されます。
ラインバイラインの説明
次’の例をもう一度詳しく見てみましょう。
podSelector: matchLabels: app: webserver-dev policyTypes: - Ingress - Egress ingress: - from: - ipBlock: cidr: 10.169.25.20/32 - namespaceSelector: matchLabels: project: jtac - podSelector: matchLabels: app: client1-dev ports: - protocol: TCP port: 80 egress: - to: - podSelector: matchLabels: app: dbserver-dev ports: - protocol: TCP port: 80
ネットワークポリシーが適用しようとしていることを正確に把握する必要があります。
ライン 1-3: pod webserver-dev はポリシーによって選択されるため、ターゲットポッドとなります。以下のポリシールールがすべて適用されます。
ライン 4-6: このポリシーでは、受信/送信トラフィックの両方のルールが定義されます。
ライン 7-19: 入口セクションでは、受信ポリシーを定義しています。
ライン 8: 差出人:とライン 17: この2つのセクションでは、入口ポリシーにおける1つのポリシールールを定義しています。
ライン 9-16: 以下の8行が from: セクションでは、入口のホワイトリストを作成します。
ライン 9-10: 送信元 IP が 10.169.25.20/32 であるすべての受信データは、ターゲット pod webserver-dev にアクセスできます。
ライン 11-13: 名前空間 jtac 下の任意のポッドから、ターゲットポッド webserver-dev にアクセスできます。
ライン 14-16: ラベル client1 で使用される任意のポッドは、ターゲット pod web サーバ-dev にアクセスできます。
ライン 17-19: ports セクションは、同じポリシールールの2つ目 (オプション) の一部になっています。ターゲットポッド webserver では、TCP ポート 80 (web サービス) のみが公開され、アクセスできます。その他すべてのポートへのアクセスは拒否されます。
ライン 20-26: エグレスセクションでは、送信ポリシーを定義しています。
21行: 目的:とライン 24: これらの2つのセクションでは、送信ポリシーにおける1つのポリシールールを定義しています。
ライン 21-24: 以下の4行を対象としています。セクションでは、出力ホワイトリストを作成します。ここで、ターゲットポッドは、出力トラフィックを pod dbserver に送信できます。
ライン 25: ports セクションは、同じポリシールールの2番目の部分です。ターゲットポッドの pod は、宛先ポートが80の TCP セッションのみを、他のポッドに対してのみ起動できます。
’それだけではありません。この章の冒頭で覚えていると思いますが、Kubernetes デフォルトのネットワークモデルと暗黙で拒否するすべてのポリシーについて説明したところで、これまでに it の明示的な部分であることを理解しています (『 the network policy イントロダクション』セクションを参照してください)。その後、さらに暗黙のポリシーが2つあります。
すべてのネットワークポリシーを拒否します。ターゲット pod webserver 開発において、上記のホワイトリストで明示的に許可されている以外のすべてのトラフィックを拒否します。これには、少なくとも2つのルールが必要です。
入口入口ホワイトウェブに記載されている受信トラフィックをすべて拒否します。このようなものは、入り口で定義されるものとは異なります。
エグレス出力ホワイトリストで定義されているものを除く、対象の pod ウェブサーバから送出するすべての送信トラフィックを拒否します。
[すべてのネットワークポリシーを許可] では、このネットワークポリシーのターゲットではないその他のポッドのすべてのトラフィックが、入口と出口の両方で許可されます。
第8章で’は、これらの暗黙のネットワークポリシーと、Contrail 実装におけるそれらのルールについて詳しく見ていきましょう。
ネットワークポリシーの作成
他の Kubernetes オブジェクトを作成するのと同じ方法で、ネットワークポリシーを作成して検証することができます。
$ kubectl apply -f policy1-do.yaml networkpolicy.networking.k8s.io/policy1-do created $ kubectl get netpol -n dev NAME POD-SELECTOR AGE policy1 app=webserver-dev 6s $ kubectl describe netpol policy -n dev Name: policy1 Namespace: dev Created on: 2019-10-01 11:18:19 -0400 EDT Labels: <none> Annotations: <none> Spec: PodSelector: app=webserver-dev Allowing ingress traffic: To Port: 80/TCP From: IPBlock: CIDR: 10.169.25.20/32 Except: From: NamespaceSelector: project=jtac From: PodSelector: app=client1-dev Allowing egress traffic: To Port: 80/TCP To: PodSelector: app=dbserver-dev Policy Types: Ingress, Egress
第 8’章では、このネットワークポリシーの効果をより詳しく検証するためのテスト環境を設定します。