Kubernetes (GKE) の Network Policy を使ってみる

Kubernetes (GKE) の Network Policy を使ってみる

Network Policy とは

簡単に言うと Pod のファイアウォールのようなものです。
この Network Policy により Pod 間の通信を制御することができます。

Network Policy では Ingress と Egress の2種類に対してポリシーを定義できます。
Ingress は Pod のインバウンドに対して、 Egress は Pod のアウトバウンドに対して制限をかけることができます。

Ingress/Egress の送信元/送信先の指定には以下が使用できます。

  • IPアドレス
  • Namespase/Pod のラベル

Google Kubernetes Engine がまだベータですが Network Policy に対応したので、そちらで色々と試してみてケース別にまとめてみました。

 

 

環境

クライアント

  • Windows 10 Pro (ただしWSLを使っています)

WSLには Cloud SDK をインストールし、アカウント認証および kubectl のインストールなど必要な初期設定を済ませています。

 

サーバ

  • Kubernetes (GKE) 1.8.4
  • n1-standard-1 ノード3台

 

クラスタ作成

CLI からクラスタを作成します。
--enable-network-policyオプションをつけるだけで Network Policy がクラスタで有効になります。
Network Policy は Kubernetes のバージョンが 1.7.6 以降である必要があるため、以下のコマンドでは執筆時点で最新の 1.8.4 を指定して作成しています。
ちなみに 1.8.3 だと Ingress は機能しましたが、 Egress が機能しませんでした。

 

デフォルトの Network Policy

Network Policy が作成されていない Namespace では、その Namespace 内の Pod のインバウンド/アウトバウンドが制限されていない状態です。

 

ケース別Network Policy

 

Ingress

全てのインバウンドを拒否

Network Policy

spec.podSelector を空にし、その Namespace 内の全 Pod を対象に全てのインバウンドを拒否します。
デフォルトではインバウンドは制限されていないため、この Network Policy を作成して全てのインバウンドを拒否し、個別に許可する Network Policy を作成するのが基本になるかと思います。

 

試す

接続テスト用の Pod をデプロイして wget コマンドでテストします。

 

クリーンアップ

 

特定 Pod からのインバウンドを許可

Network Policy

この Network Policy ではラベル app=client1 または app=client2 が付与された Pod から、ラベル app=web が付与された Pod の TCP:80 へのインバウンドを許可します。
それ以外は拒否します。

 

試す

接続テスト用の Pod をデプロイして wget コマンドでテストします。

 

クリーンアップ

 

特定 Namespace 内の全 Pod からのインバウンドを許可

Network Policy

この Network Policy ではラベル name=foo が付与された Namespace の全 Pod から、ラベル app=web が付与された Pod のTCP:80 へのインバウンドを許可します。
ここで少し注意が必要なのが、特定 Namespace 内の特定 Pod からのインバウンドだけを許可をする、というのができません。
以下のように Namespace と Pod の両方を記載しても論理積にはならず、その Namespace または同一 Namespace 内のその Pod からのインバウンドを許可するという意味になります。

 

試す

接続テスト用の Pod をデプロイして wget コマンドでテストします。

 

クリーンアップ

 

HTTP(S) GCLB からのインバウンドを許可 1

Network Policy

この Network Policy では HTTP(S) GCLB から、ラベル app=web が付与された Pod のTCP:80 へのインバウンドを許可します。
許可する送信元として GCLB のネットワークとノードが所属しているネットワークを指定しています。
なぜノードが所属しているネットワークも指定しているかと言うと、そうしないと GCLB のヘルスチェックに失敗するためです(正確に言うと、 Pod が配置されているノードのヘルスチェックはOKになりますが、配置されていないノードのヘルスチェックがNGとなります)。

GCLB のネットワークはGCE HTTP(S) 負荷分散の設定で確認しました。
ノードが所属しているネットワークはコンソール等で確認してください。

 

試す

作成する Ingress は以下になります。

接続テスト用の Pod をデプロイして wget コマンドで接続テスト後、クライアントPCで接続テストをします。
xxx.xxx.xxx.xxx は GCLB に割り当てられた実際のIPアドレスに置き換えてください。

 

クリーンアップ

HTTP(S) GCLB からのインバウンドを許可 2

Network Policy

HTTP(S) GCLB からのインバウンドを許可 1 に+αして、 web Pod から api Pod のTCP:8080へのインバウンドを許可する設定を付け加えました。
図にするとこのような形になります。

web Pod はインターネット(GCLB)からのインバウンドを許可し、 api Pod は web Pod からのインバウンドを許可します。
web Pod は GCLB からのインバウンドしか許可していないため、 api Pod からのインバウンドは拒否されます。

 

試す

api Pod の Docker イメージにはhirsim/hello-serverという、 Hello World! をレスポンスとして返すイメージを使用します(ちなみに私が作っています)。
また api Pod へのパスを追加するために、 ConfigMap を使用して nginx の conf.d/default.conf の設定を上書きします。

今回 web Pod は ConfigMap を使用して nginx の設定を上書きするため、Deployment を用意します。

作成する Ingress は以下になります。

クライアントPCから接続テストをします。
xxx.xxx.xxx.xxx は GCLB に割り当てられた実際のIPアドレスに置き換えてください。

また、 api Pod から web Pod にアクセスできないかをテストします。

 

クリーンアップ

 

Egress

全てのアウトバウンドを拒否

spec:podSelector を空にし、その Namespace 内の全 Pod を対象に全てのアウトバウンドを拒否します。
Ingress 同様、デフォルトではアウトバウンドも制限されていないため、この Network Policy を作成して全てのアウトバウンドを拒否し、個別に許可する Network Policy を作成するのが基本になるかと思います。

 

試す

接続テスト用の Pod をデプロイして wget コマンドでテストします。
全てのアウトバウンドを拒否しているため、名前解決にも失敗します。

 

クリーンアップ

 

特定 Pod へのアウトバウンドを許可

Network Policy

この Network Policy ではラベル app=client が付与された Pod から、ラベル app=web が付与された Pod の TCP:80 へのアウトバウンドを許可します。
また、名前解決をするために Namespace 内の全 Pod の DNS サーバへのアウトバウンドも合わせて許可します。
それ以外は拒否します。

 

試す

接続テスト用の Pod をデプロイして wget コマンドでテストします。

 

クリーンアップ

 

特定のIPアドレスへのアウトバウンドを許可

Network Policy

この Network Policy ではラベル app=client が付与された Pod から、 IPアドレス xxx.xxx.xxx.xxx の TCP:80 へのアウトバウンドを許可します。
また、名前解決をするために Namespace 内の全 Pod の DNS サーバへのアウトバウンドも合わせて許可します。
それ以外は拒否します。

xxx.xxx.xxx.xxx にはアクセスしたいサーバのIPアドレスに置き換えてください。
ここでは、ノードと同じサブネット内に nginx コンテナをデプロイしたインスタンスを立ち上げ、それをターゲットとします。

 

試す

接続テスト用の Pod をデプロイして wget コマンドでテストします。

 

クリーンアップ

 

クラスタ削除

 

おわりに

このように Network Policy を使うことにより柔軟かつ容易に Pod 間の通信を制御することができます。これにより不必要な通信を制限する事ができますね。
ただしインバウンド/アウトバウンドの制限はできても、当然の事ながら通信経路の暗号化やクライアント認証はされません。
よりセキュアにするには gRPC のTLSによる暗号化/クライアント認証や Istio などのフレームワークやミドルウェアを使いましょう。

 

参考