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

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

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

このページでは、GKE でネットワーク ポリシーを構成する方法について説明します。

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

目標

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

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

始める前に

次の手順で Kubernetes Engine API を有効にします。
  1. Google Cloud Console で Kubernetes Engine ページにアクセスします。
  2. プロジェクトを作成または選択します。
  3. API と関連サービスが有効になるのを待ちます。 これには数分かかることがあります。
  4. Google Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

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

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

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

次のコマンドを実行してデフォルト値を設定しておくと、gcloud コマンドライン ツールでプロジェクト IDCompute Engine ゾーンの各オプションを入力する時間を節約できます。
gcloud config set project project-id
gcloud config set compute/zone compute-zone

ステップ 1: GKE を作成する

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

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

ステップ 2: Pod への着信トラフィックを制限する

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

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

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

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

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

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

kubectl run hello-web --labels app=hello \
  --image=gcr.io/google-samples/hello-app:1.0 --port 8080 --expose

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

次の構成を hello-allow-from-foo.yaml に保存します。

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

このポリシーは、ラベル app=hello を持つ Pod を選択し、ラベル app=foo の Pod からのトラフィックのみを許可する上り(内向き)ポリシーを指定します。

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

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

ステップ 3: Pod からの発信トラフィックを制限する

着信トラフィックと同じように、発信(下り: 外向き)トラフィックを制限できます。

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

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

次の構成を foo-allow-to-hello.yaml に保存し、それをクラスタに適用します。

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

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

  1. app=hello というラベルの、同じ名前空間内の Pod
  2. ポート 53(UDP および TCP)のクラスタ Pod または外部エンドポイント

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

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

kubectl run hello-web-2 --labels app=hello-2 \
  --image=gcr.io/google-samples/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 Platform アカウントに課金されないようにする手順は次のとおりです。

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

    gcloud container clusters delete test

次のステップ