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

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

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

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

ネットワーク ポリシーを適用した 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