ファイアウォールポリシーの Contrail
第4章では Contrail オブジェクトマッピングの図についてFigure 1説明しました。
このマッピングにより’、Kubernetes のコアオブジェクトの実装 Contrail が明らかになります。名前空間、ポッド、サービス、受信、ネットワークポリシー。第4章から7番’まで、ネットワークポリシーを除くFigure 1すべてのことについて詳しく見てきました。
この章では’、Contrail におけるネットワークポリシーの実装について重点的に説明します。まず、’Kubernetes のネットワークポリシーを実装するための機能である Contrail ファイアウォールについて紹介します。’次に、テストケースを設定して Contrail でネットワークポリシーがどのように機能するかを確認します。次に、テスト結果’に基づいて、Contrail ファイアウォールポリシーとルールについて詳しく説明し、Contrail の実装を理解するために、オブジェクトマッピングのFigure 1図に示す2つのオブジェクト間のマッピングを示します。
Contrail ファイアウォールの導入
第3章では、Kubernetes のネットワークポリシーの概念について紹介しました。YAML ファイル定義を詳細にし、それに基づいてネットワークポリシーを作成しました。’ネットワークポリシーオブジェクトを作成するだけでは、Kubernetes’のネットワーク実装でサポートされていない限り、t は効果がありません。Kubernetes CNI は、Kubernetes のネットワークを実装し、Contrail ファイアウォールを介して Kubernetes ネットワークポリシーをサポートします。 Contrail この章’の中心となるのは、Contrail ファイアウォールを介して Contrail 環境でネットワークポリシーがどのように機能するかを示しています。
まず、’Contrail の重要な概念を確認してみましょう。
VN 間ルーティング
Contrail では、仮想ネットワークはデフォルトで分離されています。つまり、VN1 のワークロードは、他の VN2 のワークロードと通信できません。VN1 と VN2 間で仮想ネットワーク間の通信を可能にするには、Contrail ネットワークポリシーが必要です。Contrail ネットワークポリシーは、指定されたトラフィックを許可または拒否することで、2つの仮想ネットワーク間のセキュリティも提供できます。
ネットワークポリシーを Contrail します。
Contrail ネットワークポリシーを使用して、仮想ネットワーク間通信を許可したり、仮想ネットワーク内のトラフィックを変更したりすることができます。また、仮想ネットワーク間で許可されるトラフィックを説明します。デフォルトでは、Contrail のネットワークポリシーがない場合、仮想ネットワーク内の通信は許可されますが、仮想ネットワーク間のトラフィックは拒否されます。ネットワークポリシーを作成する場合、それを仮想ネットワークに関連付けて効果を持たせる必要があります。
Contrail’ネットワークポリシーと Kubernetes ネットワークポリシーを混同しないようにしてください。2つのセキュリティ機能を備えており、別々に動作しています。
セキュリティグループ (SG)。
セキュリティーグループは、多くの場合、SG として略記され、ポートの通過を許可または禁止するトラフィックのタイプをユーザーが指定できるようにするルールのグループです。VM または pod が仮想ネットワーク内に作成されると、SG を起動時にその VM に関連付けることができます。グローバルに設定され、仮想ネットワークに関連付けられる Contrail ネットワークポリシーとは異なり、SG はポートごとに構成され、VM ポートに関連付けられた特定の vRouter フローに反映されるようになります。
Contrail のネットワークポリシーと SG の制限
現代の Contrail クラウド環境では、既存のネットワークポリシーとセキュリティグループのみを使用して、目的のセキュリティ目標を達成することが困難になる場合があります。たとえば、クラウド環境では、ワークロードがサーバー間で移動する場合があるため、多くの場合、IP は変化してしまいます。保護するエンドポイントを特定するために IP アドレスを信頼しているだけでは、苦痛があります。そのため、ユーザーはアプリケーションレベルの属性を利用してポリシーを操作し’、ワークロードが移動するたびにポリシーを更新したり、関連するネットワーク環境を変更したりする必要がないようにする必要があります。また、実稼働環境では、ユーザーはタグの組み合わせに基づいてワークロードをグループ化しなければならない場合があります。これは、ネットワークポリシーまたは SG の既存の言語に翻訳するのが困難です。
ファイアウォールセキュリティーポリシーを Contrail します。
この章では、その他の重要な機能について説明します。ファイアウォールセキュリティーポリシーを Contrail します。
Contrail ファイアウォールセキュリティポリシーを使用すると、セキュリティポリシーからルーティングを分離し、複数のディメンションのセグメンテーションとポリシー移植性を提供しながら、ユーザーの可視化と分析機能を大幅に向上させることができます。
マルチディメンショントラフィックのセグメンテーションを実装するために、Contrail ファイアウォールはタグの概念を導入しています。タグは、導入環境内のさまざまなエンティティに関連付けられたキーと値のペアです。タグの事前定義またはカスタム/ユーザー定義が可能です。Contrail タグは、Kubernetes のラベルとほぼ同じです。どちらも、オブジェクトとワークロードを特定するために使用されます。これまで見てきたように、これは Kubernetes のネットワークポリシー設計に似ていますが、ファイアウォールセキュリティポリシーを使用して Kubernetes ネットワークポリシーを実装することが Contrail には自然なものです。理論的には、Contrail ネットワークポリシーまたは SG を拡張して作業を行うことができますが、Contrail ファイアウォールでタグをサポートすることで、より簡素化されています。
場合によっては Contrail ファイアウォールセキュリティーポリシーは Contrail セキュリティ、Contrail ファイアウォール、Contrail ファイアウォールセキュリティー、または Contrail FW と呼ばれることがあります。
Contrail Kubernetes ネットワークポリシーの使用事例
このセクションでは、’Contrail 環境でのネットワークポリシーの仕組みを検証するユースケースを作成します。’まず、テストに必要ないくつかの Kubernetes 名前空間とポッドを作成します。’デフォルトのネットワークモデルによって、すべてのポッドが dut (テスト中のデバイス) と通信できることを確認し、ネットワークポリシーを作成して、同じトラフィックパターンを使用した変更を監視します。
ネットワーク設計
Figure 2は、ユースケース設計を示しています。
Figure 2では、次の3つの部門に6つのノードが分散されています。開発、qa、jtac 開発部門では、顧客から収集した貴重なデータをすべて保持するデータベースサーバー (dbserver) を実行しています。この設計では、このデータベースサーバーに直接アクセスできない人はいないことが求められます。その代わりに、データベースサーバーへのアクセスは、dev 部門の別の Apache フロントエンドサーバーを通じてのみ許可されます。さらに、セキュリティ上の理由により、顧客情報へのアクセスは許可されたクライアントにのみ付与する必要があります。たとえば、jtac 署のノード、dev department 内のノード 1 ~ client1、およびソース IP 10.169.25.20 は、web サーバ経由でデータベースにアクセスできます。最後に、データベースサーバー dbserver は他のノードへの接続を開始するべきではありません。
ラボの準備
ここでは、きわめてシンプルで簡素化されたネットワーク設計をどこでも見ることができます。Kubernetes の世界でこれらのすべてのネットワーク要素をモデル化すると、Figure 3のようになります。
ポッドには、以下のリソースを作成する必要があります。
3つのネームスペース: 開発、qa、jtac
6個のポッド:
2つのサーバーポッド: webserver-dev、dbserver
同じ名前空間で2つのクライアントポッドをサーバーポッドとして: client1-dev, client2-dev
2つの異なる名前空間からの2つのクライアントポッド: クライアント-qa、クライアント-jtac
2つの CIDRs:
cidr 10.169.25.20/32 は、ノード cent222 のファブリック IP です。
cidr 10.169.25.21/32 は、ノード cent333 のファブリック IP です。
Table 1: Kubernetes ネットワークポリシーテスト環境
ECN | pod | ロール |
向け | client1-dev | web クライアント |
向け | client2-dev | web クライアント |
保証 | クライアント-qa | web クライアント |
jtac | クライアント-jtac | web クライアント |
向け | web サーバ-dev | web サービスを提供するクライアント |
向け | dbserver-dev | dbserver サービスウェブサーバ |
ここ’では、必要な k8s 名前空間を準備し、dev、qa、および jtac 名前空間を定義するオールインワンの yaml ファイルを使用してリソースをポッドにします。
各ポッドを異なる画像で実行するのが理想的です。また、TCP ポートは、通常、web サーバーとデータベースの間では異なります。この例では、テストを容易にするために、すべてのポッドに関して本書’全体で使用していたのとまったく同じ contrail の画像を使用しています。そのため、クライアントから web サーバーへの接続には、同じ HTTP サーバーが提供する同じポート番号80を使用します。また、ラベルを追加しました。すべてのポッドのポリシーにより、このテストに使用されているすべてのポッドを簡単に表示できます。
では、すべてのリソースを作成しましょう。
Kubernetes ネットワークポリシー作成前のトラフィックモード
すべての名前空間とポッドがあるため、ネットワークポリシーを定義する前に、’クライアントとサーバー間でトラフィックを送信してみましょう。
もちろん、デフォルトでは Kubernetes ネットワークは any モデルに準拠しているため、完全メッシュアクセスの関係となる pod 間でアクセスが機能することを前提としています。しかし、このテストの DUT は webserver であり、dbserver は、さらに注目すべきものであることを覚えておいてください。図8.4 に示すように、検証’を簡素化するために、クライアントポッドからのサーバーポッドへのアクセスに重点を置いています。
図8.4 の重要な点は、すべてのクライアントがサーバーにアクセスできるということです。すべてのモデルには次のものがあります。
クライアントと webserver のデバイスポッドの間に制限はありません。
クライアントと dbserver のポッドの間に制限はありません。
さらに、クライアントとサーバー間の通信は、双方向–で対称に行われており、セッションを開始したり、セッションを受け入れたりすることができます。これらの Kubernetes では、送信ポリシーと受信ポリシーがそれぞれマップされます。
これらは設計の目標を満たしていません。その理由は、Kubernetes ネットワークポリシーが必要なこと’です。この部分についてはすぐに説明します。ここでは、’どのようなネットワークモデルかを簡単に確認してみましょう。
まず、’web サービスの開発および dbserver ポッドのポート80で実行されている HTTP サーバーを確認してみましょう。
$kubectl exec -it webserver-dev -n dev -- netstat -antp| grep 80 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/python $kubectl exec -it dbserver-dev -n dev -- netstat -antp| grep 80 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/python
前述したように、このテストでは、すべてのポッドが同じコンテナイメージを使用しているため、すべてのポッドがコンテナーで同じ web サーバアプリケーションを実行しています。各ポッドに名前を指定するだけで、それぞれの役割が図に反映されます。
これで、以下のコマンドを使用して、他のポッドからこの HTTP サーバーへのアクセスを検証できます。受信トラフィックをテストするには、次のようにします。
これらのコマンドは、2つのノードのすべてのクライアントおよびホストから、ウェブ・デバイス・ポッドに対して HTTP リクエストをトリガーします。-M5 curl コマンドオプションを使用すると、curl がタイムアウトする前に、応答に対して最大5秒間待機します。期待どおり、すべてのアクセスが通過し、次に示す同じ出力を返します。
Client1 から (dev):
$ kubectl exec -it client1-dev -n dev -- \ curl http://$webserverIP | w3m -T text/html | grep -v "^$" Hello This page is served by a Contrail pod IP address = 10.47.255.234 Hostname = webserver-dev
W3m は、curl からの出力を取得して、web ページの HTML コードを返し、それを読みやすいテキストにレンダリングしてから、それを grep に送って空の行を削除しています。コマンドを短くするには、次のようにエイリアスを定義します。
alias webpr='w3m -T text/html | grep -v "^$"'
その結果、コマンドは短くなります。
$ kubectl exec -it client1-dev -n dev -- curl http://$webserverIP | webpr Hello This page is served by a Contrail pod IP address = 10.47.255.234 Hostname = webserver-dev
同様に、’他のポッドから dbserver dev へのアクセスについても、同じテスト結果が得られます。
Kubernetes ネットワークポリシーの作成
では’、設計を実装するための k8s ネットワークポリシーを作成してみましょう。最初の設計目標からは、次のようなネットワークポリシーを使用して達成する必要があります。
client1-jtac の名前空間 (jtac ポッド) 下の dev およびポッドは、ウェブ・デバイスポッドにアクセスできます。
dbserver は、ウェブ・デバイスポッドへのアクセスを許可されています。
その他のすべてのクライアントポッドは、2つのサーバーポッドへのアクセスを許可されていません。
他のすべてのクライアントポッドは、相互に通信できます。
このような要件を Kubernetes ネットワークポリシーの言語に変換’するために、次のネットワークポリシー yaml ファイルを使用します。
ネットワークポリシー定義では、第3章で学習’した内容に基づいて、ポリシーが現在のセットアップに何を適用しようとしているかを簡単に判断できるようにする必要があります。
入口ポリシーによれば、次のクライアントは、dev 名前空間にある web サービス・デベロッパー・サーバー・ポッドに到達できます。
client1-dev 名前空間からの開発
jtac の名前空間からのすべてのポッド (クライアント/jtac ポッドで構成されています)
ソース IP 10.169.25.20 を持つクライアント (cent222 の設定では)
送信ポリシーに従って、dev 名前空間内の webserver-dev サーバーポッドは、宛先ポート80を使用してデータにアクセスする dbserver-dev ポッドへの TCP セッションを開始できます。
ターゲットポッドサーバー-dev では、その他のアクセスはすべて拒否されます。
その他すべてのポッド間の通信は、このネットワークポリシーの影響を受けません。
実際、これは、第3章で紹介’した正確なネットワークポリシー yaml ファイルです。
ポリシー’を作成して、その効果を確認しましょう。
$ kubectl apply -f policy1- do.yaml networkpolicy.networking.k8 s.io/policy1 created
$ kubectl get networkpolicies -- all-namespaces NAMESPACE NAME POD- SELECTOR AGE dev policy1 app=webserver-dev 17s
ポスト Kubernetes ネットワークポリシーの作成
ネットワークポリシー policy1 が作成されたら、’次のようにして、webserver client1 の dev、クライアント-jtac、およびノード cent222 ホストから、web サービス開発 POD で HTTP サーバーへのアクセスをテストします。
$ kubectl exec -it client1-dev -n dev -- curl http://$webserverIP | webpr Hello This page is served by a Contrail pod IP address = 10.47.255.234 Hostname = webserver-dev
これらの2つのポッドから web サーバへのアクセスには問題がありません。そのようなものではありません。ここで、他のポッドからの同じテストを繰り返すと、クライアント qa と別のノード cent333 がタイムアウトになります。
$ kubectl exec -it client2-dev -n dev -- curl http://$webserverIP -m 5 curl: (28) Connection timed out after 5000 milliseconds command terminated with exit code 28
$ kubectl exec -it client-jtac -n jtac -- curl http://$webserverIP -m 5 curl: (28) Connection timed out after 5000 milliseconds command terminated with exit code 28
$ curl http://$webserverIP -m 5 curl: (28) Connection timed out after 5000 milliseconds
ネットワークポリシーが適用された後の新しいテスト結果は、Figure 5に示されています。
ネットワークポリシーオブジェクトの詳細については、次のことを示しています。
$ kubectl describe netpol -n dev policy1 Name: policy1 Namespace: dev Created on: 2019-09-29 21:21:14 -0400 EDT Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.k8s.io/v1", "kind":"NetworkPolicy", "metadata":{"annotations":{},"name": "policy1","namespace":"dev"}, "spec":{"egre... 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
上記の練習から、k8s のネットワークポリシーが期待どおりに Contrail で動作することを結論づけることができます。
しかし、テストはまだ行われていません。ネットワークポリシーでは、入口と出口両方のポリシーを定義しましたが、web サーバ’-dev pod’s の観点からは、policy1 の受信ポリシーが正常に機能することをテストしました。さらに、他のサーバーポッド dbserver にポリシーを適用していませんでした。デフォルトでは、すべてのポリシーを許可しているため、任意のポッドから問題なく直接アクセスできます。当然ですが、これは元の設計によるものではありませんでした。Dbserver のデバイスには、別の入口ネットワークポリシーが必要です。最後に、他のポッドに接続でき’ないようにするために、dbserver に送信ポリシーを適用する必要があります。そのため、少なくとも3つのテスト項目があることを確認する必要があります。
ウェブ・デバイス・ポッドに適用された policy1 の送信ポリシーをテストします。
Dbserver ポッド用の入口ポリシーを定義してテストします。
Dbserver ポッドの送信ポリシーを定義してテストします。Policy1’の送信ポリシーを最初に確認してみましょう。
ウェブ・デバイス・ポッドの送信ポリシー
ここ’では、送信トラフィックに対するテストを行います。
結果として、他の送信アクセスがタイムアウトになっても、dbserver へのアクセスが成功していることがわかります。
$ kubectl exec -it webserver-dev -n dev -- curl $dbserverIP -m5 | webpr Hello This page is served by a Contrail pod IP address = 10.47.255.233 Hostname = dbserver-dev $ kubectl exec -it webserver-dev -n dev -- curl 10.47.255.232 -m5 curl: (28) Connection timed out after 5001 milliseconds command terminated with exit code 28
Dbserver のネットワークポリシー-dev ポッド
今のところ大丈夫です。’2 つ目のテスト項目を見て、dbserver の他のポッドから、ウェブ・デバイス・ポッド以外の pod を使用して、入口にアクセスします。送信トラフィックをテストします。
すべてのポッドは、dbserver のデバイスに直接アクセスできます。
$ kubectl exec -it client1-dev -n dev -- curl http://$dbserverIP -m5 | webpr Hello This page is served by a Contrail pod IP address = 10.47.255.233 Hostname = dbserver-dev
当社の設計では、web サーバのデバイスポッド以外のすべてのポッドからのアクセスをブロックしています。そのために、別のポリシーを適用する必要があります。2つ目のポリシーの YAML ファイルは次のとおりです。
このネットワークポリシーである policy2 は、以前の policy1 とよく似ていますが、 –ポリシータイプがリストに表示されているだけではなく、受信ポリシーのみを定義するという点が異なります。また、受信ポリシーでは podSelector のみを使用してホワイトリストが定義されています。このテストケースでは、1つの pod webserver デバイスにのみ対応するラベルがあり、ポート80のターゲットポッド dbserver への TCP 接続を開始できるのは1つだけです。ポリシー’policy2 を今すぐ作成し、結果を確認してみましょう。
$ kubectl exec -it webserver-dev -n dev -- curl http://$dbserverIP -m5 | webpr Hello This page is served by a Contrail pod IP address = 10.47.255.233 Hostname = dbserver-dev
$ kubectl exec -it client1-dev -n dev -- curl http://$dbserverIP -m5 | webpr command terminated with exit code 28 curl: (28) Connection timed out after 5002 milliseconds
Dbserver のデバイスにアクセスできるようになりました。
Dbserver の送信ポリシー
設計目標の最終要件は次のとおりです。サーバー dbserver が他のノードへの接続を開始できないようにする必要があります。
Policy2 をレビューしたときに、どのようにしてそれを実現しているかという疑問があるかもしれません。第3章では、ネットワークポリシーはホワイトリストに基づいて設計されていることを強調しました。したがって、ホワイトリストには何が含まれていても、そのことは許されるということです。ブラックリストには拒否が表示されますが、ブラック’アウトでも、拒否するためだけに他のすべてのポッドを列挙することができます。
このことを考慮するもう1つの方法は、暗黙のポリシーのすべて拒否を使用することです。そのため、この一連のポリシーが現在の Kubernetes ネットワークポリシー設計にあると仮定しています。
policy2 on dbserver-dev
すべてを拒否して dbserver の開発に対応
他のポッドをすべて許可
Dbserver の送信ポリシーで空のホワイトリストを提供すると、何も許可されず、ターゲットポッドのすべての拒否ポリシーが機能するようになります。問題として、空のホワイトリストを定義するにはどうすればよいのでしょうか。
この’ことは期待どおりに機能しません。
$ kubectl exec -it dbserver-dev -n dev -- curl http://10.47.255.232 -m5 | webpr Hello This page is served by a Contrail pod IP address = 10.47.255.232 Hostname = client1-dev
ポリシーオブジェクトの詳細をチェックするだけでは、明らかに問題が発生することはありません。
$ kubectl describe netpol policy2-tryout -n dev Name: policy2-tryout Namespace: dev Created on: 2019-10-01 17:02:18 -0400 EDT Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.k8s.io/v1", "kind":"NetworkPolicy", "metadata":{"annotations":{},"name": "policy2-tryout", "namespace":"dev"},"spec"... Spec: PodSelector: app=dbserver-dev Allowing ingress traffic: To Port: 80/TCP From: PodSelector: app=webserver-dev Allowing egress traffic: <none> (Selected pods are isolated for egress connectivity) #< --- Policy Types: Ingress
この問題は policyTypes で発生します。送信を’追加していないため、送信ポリシーで設定されているものはすべて無視されます。単に policyTypes で出力を追加するだけで、それが修正されます。さらに、空のホワイトリストを表現するには、以下のように送信します。キーワードは省略可能であり、必須ではありません。新しい policy YAML ファイルを以下に示します。
では、古い policy2 を削除して、この新しいポリシーを適用してみましょう。Dbserver が他のポッド (pod client1、dev など) へのリクエストはブロックされます。
$ kubectl exec -it dbserver-dev -n dev -- curl http://10.47.255.232 | webpr command terminated with exit code 28 curl: (7) Failed to connect to 10.47.255.232 port 80: Connection timed out
ここでは、Figure 6に示すネットワークポリシーテストの結果を示す最終図を示しています。
フローテーブルのドロップアクション
テストを完了する前に’、トラフィックがポリシーによってドロップされた場合に vrouter フローテーブルを見てみましょう。Cent333 のノードで、pod dbserver が配置されています。
$ docker exec -it vrouter_vrouter-agent_1 flow --match 10.47.255.232:80 Flow table(size 80609280, entries 629760) Entries: Created 33 Added 33 Deleted 30 Changed 54Processed 33 Used Overflow entries 0 (Created Flows/CPU: 7 9 11 6)(oflows 0) Action:F=Forward, D=Drop N=NAT(S=SNAT, D=DNAT, Ps=SPAT, Pd=DPAT, L=Link Local Port) Other:K(nh)=Key_Nexthop, S(nh)=RPF_Nexthop Flags:E=Evicted, Ec=Evict Candidate, N=New Flow, M=Modified Dm=Delete Marked TCP(r=reverse):S=SYN, F=FIN, R=RST, C=HalfClose, E=Established, D=Dead Listing flows matching ([10.47.255.232]:80) Index Source:Port/Destination:Port Proto(V) 158672<=>495824 10.47.255.232:80 6 (5) 10.47.255.233:42282 (Gen: 1, K(nh):59, Action:D(Unknown), Flags:, TCP:Sr, QOS:-1, S(nh):63, Stats:0/0, SPort 54194, TTL 0, Sinfo 0.0.0.0) 495824<=>158672 10.47.255.233:42282 6 (5) 10.47.255.232:80 (Gen: 1, K(nh):59, Action:D(FwPolicy), Flags:, TCP:S, QOS:-1, S(nh):59, Stats:3/222, SPort 52162, TTL 0, Sinfo 8.0.0.0)
アクション: Dが D (FwPolicy) に設定されています。これは、ファイアウォールポリシーによってドロップすることを意味します。一方で、pod client1 が存在’するもう1つのノード cent222 では、生成されたフローがないので、パケットが到達していないことを示しています。
$ docker exec -it vrouter_vrouter-agent_1 flow --match 10.47.255.233 Flow table(size 80609280, entries 629760) ...... Listing flows matching ([10.47.255.233]:*) Index Source:Port/Destination:Port Proto(V)
Contrail 実装の詳細
Reiterated’は、Contrail ファイアウォールセキュリティーポリシーを使用して、Contrail に Kubernetes ネットワークポリシーを実装することをご紹介しました。また、Kubernetes のラベルがタグとして Contrail に公開されていることもわかっています。これらのタグは、指定された Kubernetes ポリシーを実装するために Contrail のセキュリティポリシーによって使用されます。タグは、Kubernetes のオブジェクトラベルから自動的に作成されるか、UI に手動で作成することができます。
このセクションでは’、Contrail ファイアウォールポリシー、ポリシールール、タグについて詳しく見ていきましょう。特に、最後’のセクションで作成してテストした Kubernetes オブジェクトと Contrail ファイアウォールシステムの対応する Contrail オブジェクトの間のマッピング関係を確認してみましょう。
Contrail ファイアウォールは、次のような階層構造で設計されています。
最上位レベルのオブジェクトは、アプリケーションポリシーセットと呼ばれるもので、短縮された AP としてのものです。
AP にはファイアウォールポリシーがあります。
ファイアウォールポリシーにはファイアウォールルールがあります。
ファイアウォールルールにはエンドポイントがあります。
エンドポイントは、タグまたはアドレスグループ (CIDRs) によって識別できます。
Figure 7は、この構造を示しています。
マッピングの構築
Kubernetes のネットワークポリシーと Contrail ファイアウォールポリシーは、それぞれが指定されているネットワークポリシーのセマンティクスに関して、2つの異なるエンティティになっています。Contrail ファイアウォールで Kubernetes ネットワークポリシーを実装するには Contrail、Kubernetes から Contrail ファイアウォールへの多数のデータ構成に1対1のマッピングを実装する必要があります。これらのデータ構成要素は、Kubernetes ネットワークポリシーとそれに対応する Contrail ファイアウォールポリシーの基本的な構成要素です。
Table 2は、Kubernetes Contrail のネットワークポリシー構成要素と、それに対応する構成要素をリストしています。
Table 2: K8s のネットワークポリシーと Contrail ファイアウォール構成のマッピング
K8s ネットワークポリシー構成要素 | Contrail ファイアウォール構成 |
クラスター名 | APS (k8s クラスターごとに1つ) |
ネットワークポリシー | ファイアウォールポリシー (k8s ネットワークポリシーごとに1つ) |
入口/出口ポリシールール | ファイアウォールルール (k8s の受信/送信ポリシールールごとに1つ) |
CIDR | アドレスグループ (k8s ネットワークポリシー CIDR ごとに1つ) |
ラベル | タグ (k8s ラベルごとに1つ) |
名前空間 | カスタムタグ (名前空間ごとに1つ) |
Contrail の kube マネージャーは、このガイドの何回も’前に読まれていたように、2つの世界のすべての翻訳を行っています。Kubernetes のネットワークポリシーのコンテキストでは、基本的に以下のことが行われます。
KM は、初期化プロセスで Kubernetes のクラスター名を持つ AP を作成します。通常、デフォルトの Kubernetes クラスター名は k8s であるため、クラスターに同じ名前の AP があることがわかります。
KM は、ネットワークポリシーのイベントを監視するために kube サーバーに登録します。
Kubernetes のネットワークポリシーが作成されるたびに、対応するすべてのファイアウォールルールとネットワークエンドポイントを使用して、該当する Contrail ファイアウォールポリシーが作成されます。
Kubernetes オブジェクトで作成された各ラベルには、対応する Contrail タグが作成されます。
タグに基づいて、対応する Contrail オブジェクト (VN、ポッド、VMI、プロジェクトなど) を見つけることができます。
Contrail は、Contrail のファイアウォールポリシーとルールを Contrail オブジェクトの AP に適用します。これは、特定のトラフィックが許可または拒否される方法です。
AP は、たとえば以下のように、さまざまな Contrail オブジェクトに関連付けることができます。
VMI (バーチャルマシンインターフェイス)
VM (バーチャルマシン) またはポッド
VN (仮想ネットワーク)
作品
Contrail Kubernetes クラスターでは、AP は仮想ネットワークに関連付けられています。トラフィックがネットワークに到達するたびに、AP に関連付けられたファイアウォールポリシーが評価されるため、トラフィックに対してそれぞれの行動が取られます。
前のセクションでは、ユースケースで2つの Kubernetes ネットワークポリシーを作成しました。ここで’は、これらの Kubernetes ネットワークポリシーに対して作成された Contrail オブジェクトについて説明します。
アプリケーションポリシーセット (AP)
前に述べたように、contrail kube manager は、初期化段階で Kubernetes のクラスター名を使用して AP を作成します。第3章では Contrail 名前空間と分離について説明しましたが、クラスター名はデフォルトで Contrail に k8s されていることを学びました。したがって、k8s の名前は、Figure 8に示すような Contrail UI にも含まれています。
デフォルトで作成される、1個の APS (デフォルトのアプリケーションポリシーセット) が用意されています。
ポリシー
ここで [ファイアウォールポリシー] をクリックして、クラスター内のすべてのファイアウォールポリシーを表示します。テスト環境では、以下のポリシーを利用できます。
k8s-dev-policy1
k8s-dev-policy2
k8s-denyall
k8s-allowall
k8s-Ingress
Contrail ファイアウォールポリシーの名前付け規則
K8s の policy1 と k8s が開発した policy2 のポリシーは、私たち’が作成したものです。これらは YAML ファイルに記載されているオブジェクト名とは異なるように見えますが、それがどれであるかを簡単に見分けることができます。Kubernetes のネットワークポリシーに基づいて KM が Contrail ファイアウォールポリシーを作成する場合、ファイアウォールポリシー名の前に、次のようなクラスター名と名前空間がネットワークポリシー名の前に付加されます。
<cluster name>-<namespace-name>-<kubernetes network policy name>
これはよく知られています。これまで Contrail に、Kubernetes の UI で、YAML ファイルで作成した仮想ネットワークオブジェクトの名前の後に、KM が仮想ネットワークにどのように名前を指定しているかを示していました。
受信ロードバランサーに対して K8s のファイアウォールポリシーが作成され、受信した loadbalancer が確実に Contrail で正しく機能するようになります。詳細については、このガイドでは扱いません。
しかし、さらに大きな問題は、「allowall」や「denyall」などのネットワークポリシーをまったく作成していないため、その後も2つのファイアウォールポリシーが表示されるのはなぜでしょうか。
第3章で Kubernetes のネットワークポリシーを導入したときには、Kubernetes ネットワークポリシーがホワイトリストの方法を使用し、すべてのポリシーを暗黙的に拒否することを説明したのは覚えていますか。ホワイトリスト方式の性質は、ホワイトリストに追加されるもの以外のすべてのトラフィックに対してすべてのアクションを拒否することを示していますが、暗黙的に [すべての動作] をオンにすると、ネットワークポリシーに含まれていない pod が任意のトラフィックモデルを使用できるようになります。この implicitness に関する Contrail ファイアウォールの問題は、デフォルトでは、明示的に定義されていないすべてのモデルがブロックされるということです。このため、Contrail 実装では、これらの2つの暗黙のネットワークポリシーは KM モジュールによって生成される2つの明示的ポリシーによって受け入れられます。
この時点で1つの質問が発生する可能性があります。複数のファイアウォールポリシーを使用すると、最初に適用して評価しなければなりません。つまり、各ポリシー –を適用して評価する順序に Contrail、ファイアウォールポリシーを別の順序で評価すると、完全に異なる結果が得られます。この2つのシーケンスは、すべてが allowall-denyall であることを想像してみてください。前者は他のすべてのポッドに対して deny を提供します。後者は、応答がシーケンス番号であることを示します。
シーケンス番号
AP のファイアウォールポリシーを評価する際には、特定の順序で評価する必要があります。すべてのファイアウォールポリシーとすべてのファイアウォールルール (これについては後で紹介します) に、シーケンス番号が記載されています。一致するポリシーがある場合は、それが実行され、評価が中止されます。Contrail は、すべてのファイアウォールポリシーとファイアウォールルールの適切なシーケンス番号を割り当てて、すべての機能が正しい順序で動作するように、もう一度 Kube manager にも適用されています。手動操作を必要とせずに、プロセスが自動的に実行されます。’Kubernetes のネットワークポリシーを作成する際には、このようなことを気にする必要はありません。
’後でシーケンス番号にアクセスしますが、ここで’はファイアウォールポリシーに定義されているルールを見てみましょう。
ファイアウォールポリシールール
次に示すファイアウォールポリシーリストのキャプチャでは、右側に各ポリシーのルール数が表示されます。
K8s の policy1 ポリシーには、4つのルールがあります。ルールをクリックすると、Figure 11のようにルールの詳細が表示されます。
Kubernetes のネットワークポリシー policy1 に似ていますが’、テストしました。ここ’では、画面のキャプチャに表示されるルールをTable 3に挿入してみましょう。
Table 3: ルール
ルール# | アクション | サービス | エンド Point1 | 重役 | エンド Point2 | タグの照合 |
1 | 受け渡し | tcp:80 | プロジェクト = jtac | > | app = webserver-dev & & 名前空間 = dev | - |
2 | 受け渡し | tcp:80 | app = client1-dev & & 名前空間 = dev | > | app = webserver-dev & & 名前空間 = dev | - |
3 | 受け渡し | tcp:80 | app = webserver-dev & & 名前空間 = dev | > | app = dbserver-dev & & 名前空間 = dev | - |
4 | 受け渡し | tcp:80 | アドレスグループ: 10.169.25.20/32 | > | app = webserver-dev & & 名前空間 = dev | - |
表8.2 の最初のコラムは、追加したルール番号です。その他すべての列は、UI スクリーンショットからインポートされます。では’、Kubernetes オブジェクト情報と比較してみましょう。
$ kubectl get netpol --all-namespaces -o yaml apiVersion: v1 items: - apiVersion: extensions/v1beta1 kind: NetworkPolicy metadata: ...... spec: egress: - ports: - port: 80 protocol: TCP to: - podSelector: #<---rule#3 matchLabels: app: dbserver-dev ingress: - from: - ipBlock: #<---rule#4 cidr: 10.169.25.20/32 - namespaceSelector: #<---rule#1 matchLabels: project: jtac - podSelector: #<---rule#2 matchLabels: app: client1-dev ports: - port: 80 protocol: TCP podSelector: matchLabels: app: webserver-dev policyTypes: - Ingress - Egress
ファイアウォールポリシー k8s に記載されているルールは、Kubernetes ネットワークポリシー policy1 のルールと一致しています。
K8s のルールすべてのファイアウォールポリシー
ここで’は、Kubernetes ネットワークポリシーに対して KM が生成した k8s のすべてのポリシーのルールを確認してみましょう。
繰り返しますが、これを表に変換すると、Table 4に示すように表示されます。
Table 4: Contrail UI: k8s-denyall のポリシールール
ルール# | アクション | サービス | エンド Point1 | 重役 | エンド Point2 | タグの照合 |
1 | 拒否 | any: 任意 | app = webserver-dev & & 名前空間 = dev | > | 必要 | - |
2 | 拒否 | any: 任意 | 必要 | > | app = dbserver-dev & & 名前空間 = dev | - |
3 | 拒否 | any: 任意 | 必要 | > | app = webserver-dev & & 名前空間 = dev | - |
K8s 拒否ルールはシンプルです。Contrail には、ホワイトリストに記載されていないその他すべてのポッドとの通信を拒否することを指示するだけです。注目すべき1つのことは、app = webserver-dev & & 名前空間 = dev から any というルールがあるため、このようなルールは、アプリケーション (app = dbserver-dev & & 名前空間 = dev から任意のものへといったものではありません。前回のセクションでテストをレビューした場合、元のポリシー policy2 では、policyTypes で送信オプションを定義して dbserver の送信トラフィックを拒否していました。そのため、このようなルールは、Contrail ファイアウォールに変換されていません。Policy2 を新しいポリシーの policy2 に変更し、同じ’ことを確認した場合、ルールが見つからないことが確認されます。
K8s のすべてのポリシーは、ネットワークポリシーによって選択されたターゲットポッド–ポッドにのみ適用されるという事実に注意してください。この例では、pod webserver の dev と dbserver にのみ適用されます。クライアント-jtac やクライアント-qa などのその他のポッドは影響を受けません。代わりに、これらのポッドが k8s の任意のポリシー’によって適用されます。これは次のようになります。
K8s 内のルールすべてのファイアウォールポリシー
Figure 14では、k8s のすべてのポリシーは、他のポリシーよりも多くのルールを持っているように見えます。
ルールの数があるにもかかわらず、実際には k8s が最もシンプルなものです。NS レベルで動作し、NS ごとに2つのルールを適用しています。UI の検索フィールド内、名前空間内のキー (dev や qa’など) は、Figure 15およびFigure 16に示すような結果を示しています。
このポリシーには、以下のものがあります。ネットワークポリシーがまだ適用されていないポッドについて’は、Kubernetes のデフォルトのネットワークモデルを使用して、すべてを許可することにしましょう。
シーケンス番号
Contrail ファイアウォールポリシールールを調べてから、’シーケンス番号に戻り、その動作を正確に確認してみてください。
シーケンス番号は、すべてのファイアウォールポリシーに付加された番号であり、すべてのポリシーが適用されて評価される順序を決定することによって、特定のポリシーにおいて同じように動作します。シーケンス番号が低いほど優先度は高くなります。シーケンス番号を確認するには、Contrail 構成データベースのファイアウォールポリシーとポリシールールオブジェクト属性を確認する必要があります。
まず、’ap 内のファイアウォールポリシーオブジェクトを見て、そのシーケンス番号を確認します。
第5章では、サービスを導入したときに、loadbalancer オブジェクトデータを取得するために curl コマンドを使用しました。ここでは、Config Editor を使用して同じことを行いました。
Figure 17とFigure 18は、ファイアウォールポリシーのシーケンス番号を取得しています。
この5つのポリシー’はすべて、APS k8s の下の各スクリーンショットに記載されています。たとえば、明示的に定義された Kubernetes ネットワークポリシー policy1 にマップされる policy k8s-dev-policy1 は、システムが自動的に生成したポリシー k8s になります。図には、k8s の policy1 と k8s のすべてが含まれています。シーケンス番号は、それぞれ00038.0 と00042.0 です。そのため、k8s-policy1 はより高い優先度を持ち、最初に適用され、評価が行われることになります。つまり、ホワイトリストに定義したトラフィックタイプが最初に許可されます。その後、ターゲットポッドとの間で行われる他のすべてのトラフィックは拒否されます。これは、達成したいと考えている正確な目標です。
Table 5には、すべてのファイアウォールポリシーのすべてのシーケンス番号が、最高の優先度から最小のものまで示しています。
Table 5: シーケンス番号
シーケンス番号 | ファイアウォールポリシー |
00002.0 | k8s-Ingress |
00038.0 | k8s-dev-policy1 |
00040.0 | k8s-dev-policy2 |
00042.0 | k8s-denyall |
00043.0 | k8s-allowall |
シーケンス番号に基づいて、アプリケーションと評価順序が最初の明示的なポリシーとなり、[すべてを拒否] ポリシーに続いて、[すべて許可] ポリシーで終了します。Kubernetes の注文と同じ順序で受け入れられます。
ファイアウォールポリシールールのシーケンス番号
前述したように、同じファイアウォールポリシーでは、ポリシールールも特定の順序で適用して評価する必要があります。Contrail ファイアウォール内で、シーケンス番号によって保証されます。ファイアウォールポリシー k8s のルールのシーケンス番号は、Figure 19およびFigure 20に示されています。
およびTable 6は、ファイアウォールポリシー k8s の policy1 のすべてのルールのシーケンス番号を、最高の優先度から低い順に示しています。
Table 6: Policy1 のシーケンス番号
連番# | ファイアウォールルール |
00000.0 | dev-ingress-policy1-0-ipBlock-0-cidr-10.169.25.20/32-0 |
00001.0 | dev-ingress-policy1-0-namespaceSelector-1-0 |
00002.0 | dev-ingress-policy1-0-podSelector-2-0 |
00003.0 | dev-egress-policy1-podSelector-0-0 |
ネットワーク’ポリシー yaml ファイルの設定と比較してみてください。
ingress: - from: - ipBlock: cidr: 10.169.25.20/32 #<---seq# 00000.0 - namespaceSelector: #<---seq# 00001.0 matchLabels: project: jtac - podSelector: #<---seq# 00002.0 matchLabels: app: client1-dev ports: - protocol: TCP port: 80 egress: - to: - podSelector: #<---seq# 00003.0 matchLabels: app: dbserver-dev ports: - protocol: TCP port: 80
ルールシーケンス番号は、YAML ファイルに表示されるシーケンスと一致していることがわかります。つまり、ルールが定義されたときと同じ順序で適用されます。
Tag
’Contrail タグについて説明してきましたが、Contrail kube manager は、各 Kubernetes ラベルを、Figure 21に示すように pod の各ポートに接続された Contrail タグに変換することをすでに理解しています。
UI の可視化
Contrail UI は、Figure 22に示すように、セキュリティに優れた視覚エフェクトを提供します。Contrail’セキュリティの仕組みについて理解している方は、こちらをご覧ください。