为应用配置网络政策

本教程演示了如何使用集群网络政策来控制哪些 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(即 Kubernetes Engine 使用的集群编排系统)。您可以使用 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 表示传出流量,或两者皆有

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

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

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

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

接下来,需要配置 NetworkPolicy 以仅允许来自 app=foo Pod 的流量传入 hello-web Pod。而来自不带该标签的 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 中的 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

第 3 步:限制传出 Pod 的流量

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

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

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

将以下配置保存到 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

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

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

验证出站流量政策

首先,部署名为 hello-web-2 的全新 Web 应用,并在集群内部公开该应用:

kubectl run hello-web-2 --labels app=hello-2 \
  --image=gcr.io/google-samples/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 Platform 帐号产生费用,请执行以下操作:

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

    gcloud container clusters delete test

后续步骤