为应用配置网络政策


本教程演示了如何使用集群网络政策来控制哪些 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 集群。gcloud 包含在 gcloud CLI 中。
  • kubectl 用于管理 Kubernetes(即 Kubernetes Engine 使用的集群编排系统)。您可以使用 gcloud 安装 kubectl
    gcloud components install kubectl

从 GitHub 克隆示例代码:

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

gcloud 命令行工具设置默认值

如需节省在 gcloud 命令行工具中输入项目 IDCompute 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

  • 哪些 Pod 可以连接指定的 Pod(对于入站流量政策)

  • 出站流量政策规定指定的 Pod 可以连接哪些 Pod

首先,运行带有标签 app=hello 的 Web 服务器应用,并在集群内部将其公开:

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

接下来,配置 NetworkPolicy 以仅允许来自 app=foo Pod 的流量传入 hello-web Pod。来自未带此标签的 Pod 的其他传入流量、外部流量和来自其他命名空间中的 Pod 的流量均会被阻止。

以下清单选择带有标签 app=hello 的 Pod,并指定入站流量政策,以仅允许来自带有标签 app=foo 的 Pod 的流量:


# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

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

验证 Ingress 政策

首先,运行带有标签 app=foo 的临时 Pod,并获取 Pod 中的 shell:

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=fooapp=hello Pod 的流量传输已启用。

接下来,运行带有不同标签 (app=other) 的临时 Pod,并在 Pod 中获取 shell:

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

发出相同的请求,观察到流量不被允许,因此请求超时;然后退出 Pod shell:

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

限制传出 Pod 的流量

您可以像限制传入流量一样限制传出流量。

但是,为了能够查询内部主机名(如 hello-web)或外部主机名(如 www.example.com),您必须在出站流量网络政策中允许 DNS(域名系统)解析。DNS 流量使用 TCP 和 UDP 协议在端口 53 上产生。

若要启用出站网络政策,请部署 NetworkPolicy 以控制从带有标签 app=foo 的 Pod 传出的流量,同时仅允许该流量传入带有标签 app=hello 的 Pod 并允许 DNS 流量。

以下清单指定了一个网络政策,对从带有标签 app=foo 的 Pod 传出的流量进行控制,仅允许该流量传入下面两个目的地:

  1. 同一命名空间中带有 app=hello 标签的 Pod。
  2. 端口 53 上的集群 Pod 或外部端点(UDP 和 TCP)。

# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

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 的全新 Web 应用,并在集群内部公开该应用:

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,并在容器中打开 shell:

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 shell。

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

清除数据

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

  1. 删除容器集群:此步骤将删除构成容器集群的资源,如计算实例、磁盘和网络资源。

    gcloud container clusters delete test

后续步骤