アプリケーション向けのネットワーク ポリシーの構成


このチュートリアルでは、クラスタ ネットワーク ポリシーを使用することにより、どの Pod が着信ネットワーク トラフィックを受信するか、またどの Pod が発信トラフィックを送信できるかを制御する方法を示します。詳細については、クラスタ ネットワーク ポリシーの作成をご覧ください。

ネットワーク ポリシーを使用すると、Pod 間の接続を制限できます。したがって、ネットワーク ポリシーを使用して妥協範囲を狭めることで、セキュリティが強化されます。

ネットワーク ポリシーは、接続が許可されるかどうかを決定しますが、認可やセキュリティ保護トランスポート(たとえば SSL / TLS)などの高度な機能を提供するものではないことに注意してください。

目標

このチュートリアルでは、次のことを学びます。

  • ネットワーク ポリシーを適用してクラスタを作成する方法
  • ラベルを使用して Pod への着信トラフィックを制限する方法
  • ラベルを使用して Pod からの発信トラフィックを制限する方法

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

次の手順で Kubernetes Engine API を有効にします。
  1. Google Cloud コンソールの Kubernetes Engine ページにアクセスします。
  2. プロジェクトを作成または選択します。
  3. API と関連サービスが有効になるのを待ちます。 これには数分かかることがあります。
  4. Make sure that billing is enabled for your Google Cloud project.

このチュートリアルで使用されている以下のコマンドライン ツールをインストールします。

  • gcloud は、Kubernetes Engine クラスタの作成と削除に使用されます。gcloudgcloud CLI に含まれています。
  • kubectl は、Kubernetes Engine で使用されるクラスタ オーケストレーション システムである Kubernetes の管理に使用されます。gcloud を使用して kubectl をインストールできます。
    gcloud components install kubectl

GitHub からサンプルコードのクローンを作成します。

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/networking/network-policies

gcloud コマンドライン ツールのデフォルト値を設定する

次のようにしてデフォルト値を設定しておくと、gcloud コマンドライン ツールでプロジェクト ID および Compute Engine ゾーン オプションを入力する時間が節約されます。
gcloud config set project project-id
gcloud config set compute/zone compute-zone

ネットワーク ポリシーを適用した GKE クラスタを作成する

ネットワーク ポリシーを適用してコンテナ クラスタを作成するには、次のコマンドを実行します。

gcloud container clusters create test --enable-network-policy

Pod への着信トラフィックを制限する

Kubernetes NetworkPolicy リソースにより、Pod のネットワーク アクセス ポリシーを構成できます。NetworkPolicy オブジェクトには次の情報が含まれます。

  • ネットワーク ポリシーの適用対象となる Pod。通常は、ラベルセレクタによって指定されます。

  • ネットワーク ポリシーの影響を受けるトラフィックのタイプ: 着信トラフィックの場合は Ingress、発信トラフィックの場合は Egress、あるいはその両方

  • Ingress ポリシーの場合、指定した Pod に接続できる Pod

  • Egress ポリシーの場合、指定した Pod が接続できる接続先 Pod

まず、ラベル app=hello のウェブサーバー アプリケーションを実行し、クラスタ内でそれを内部公開します。

kubectl run hello-web --labels app=hello \
  --image=us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0 --port 8080 --expose

次に、hello-web Pod へのトラフィックが app=foo Pod から送られる場合にのみ許可されるように NetworkPolicy を構成します。このラベルがない Pod からの他の着信トラフィック、外部トラフィック、他の Namespace 内の Pod からのトラフィックはブロックされます。

次のマニフェストでは、ラベルが app=hello の Pod を選択し、ラベルが app=foo の Pod からのトラフィックのみを許可する Ingress ポリシーを指定しています。

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: hello-allow-from-foo
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: hello
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: foo

このポリシーをクラスタに適用するには、次のコマンドを実行します。

kubectl apply -f hello-allow-from-foo.yaml

上り(内向き)ポリシーを検証する

まず、app=foo というラベルを使って一時 Pod を実行し、その Pod でシェルを取得します。

kubectl run -l app=foo --image=alpine --restart=Never --rm -i -t test-1

hello-web:8080 エンドポイントに対してリクエストを発行して、着信トラフィックが許可されていることを確認します。

/ # wget -qO- --timeout=2 http://hello-web:8080
Hello, world!
Version: 1.0.0
Hostname: hello-web-2258067535-vbx6z
/ # exit

Pod app=foo から app=hello Pod へのトラフィックが有効になっています。

次に、別のラベル(app=other)を使って一時 Pod を実行し、その Pod 内でシェルを取得します。

kubectl run -l app=other --image=alpine --restart=Never --rm -i -t test-1

同じリクエストを発行して、トラフィックが許可されないために要求がタイムアウトすることを観察した後、Pod シェルを終了します。

/ # wget -qO- --timeout=2 http://hello-web:8080
wget: download timed out
/ # exit

Pod からの発信トラフィックを制限する

着信トラフィックと同じように、発信トラフィックを制限できます。

ただし、hello-web などの内部ホスト名や、www.example.com などの外部ホスト名を照会できるようにするには、下り(外向き)ネットワーク ポリシーで DNS(ドメイン ネーム システム)解決を可能に必要があります。DNS トラフィックは、TCP プロトコルおよび UDP プロトコルを使用するポート 53 で発生します。

下り(外向き)ネットワーク ポリシーを有効にするには、app=foo というラベルの Pod からの送信トラフィックを制御する NetworkPolicy をデプロイし、DNS トラフィックに加えて、app=hello というラベルの Pod へのトラフィックのみを許可します。

次のマニフェストは、次の 2 つの宛先を許可する、ラベルが app=foo の Pod からの下り(外向き)トラフィックを制御するネットワーク ポリシーを指定します。

  1. app=hello というラベルの、同じ Namespace 内の Pod
  2. ポート 53(UDP および TCP)のクラスタ Pod または外部エンドポイント
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: foo-allow-to-hello
spec:
  policyTypes:
  - Egress
  podSelector:
    matchLabels:
      app: foo
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: hello
  - ports:
    - port: 53
      protocol: TCP
    - port: 53
      protocol: UDP

このポリシーをクラスタに適用するには、次のコマンドを実行します。

kubectl apply -f foo-allow-to-hello.yaml

外向き(下り)ポリシーを検証する

まず、hello-web-2 という新しいウェブ アプリケーションをデプロイし、クラスタ内でそれを内部公開します。

kubectl run hello-web-2 --labels app=hello-2 \
  --image=us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0 --port 8080 --expose

次に、app=foo というラベルの一時 Pod を実行し、コンテナ内でシェルを開きます。

kubectl run -l app=foo --image=alpine --rm -i -t --restart=Never test-3

その Pod が hello-web:8080 への接続を確立できることを確認します。

/ # wget -qO- --timeout=2 http://hello-web:8080
Hello, world!
Version: 1.0.0
Hostname: hello-web-2258067535-vbx6z

Pod が hello-web-2:8080 への接続を確立できないことを確認します。

/ # wget -qO- --timeout=2 http://hello-web-2:8080
wget: download timed out

Pod が www.example.com などの外部ウェブサイトへの接続を確立できないことを確認し、Pod シェルを終了します。

/ # wget -qO- --timeout=2 http://www.example.com
wget: download timed out
/ # exit

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

  1. コンテナ クラスタを削除する: コンテナ クラスタを構成するリソース(コンピューティング インスタンス、ディスク、ネットワーク リソースなど)を削除します。

    gcloud container clusters delete test

次のステップ