使用网络政策控制 Pod 和服务之间的通信

本页面介绍了如何使用 GKE 的网络政策实施功能来控制集群的 Pod 和 Service 之间的通信。

GKE 网络政策实施功能的简介

借助网络政策实施功能,您可以在集群中创建 Kubernetes 网络政策。默认情况下,集群中的所有 Pod 都可以自由通信。网络政策会创建 Pod 级层防火墙规则,以确定哪些 Pod 和 Service 可以在您的集群内相互访问。

定义网络政策可帮助您在集群服务于多级应用时启用深度防御等功能。例如,您可以创建网络政策,以确保应用中受侵的前端服务无法直接与低了几个级层的结算或记账服务进行通信。

网络政策还可以使您的应用更容易同时托管来自多个用户的数据。例如,您可以通过定义每个命名空间一个租户的模型来提供安全的多租户服务。在此类模型中,网络政策规则可确保给定命名空间中的 Pod 和服务无法访问其他命名空间中的其他 Pod 或服务。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行 gcloud components update 以获取最新版本。

要求和限制

需要遵循以下要求和限制:

启用网络政策实施功能

默认情况下,Autopilot 集群会启用网络政策实施功能,因此您可以跳至创建网络政策

创建网络政策

您可以使用 Kubernetes Network Policy API 创建网络政策。

如需详细了解如何创建网络政策,请参阅 Kubernetes 文档中的以下主题:

网络政策和适用于 GKE 的工作负载身份联合

如果您将网络政策与适用于 GKE 的工作负载身份联合搭配使用,您必须允许流向以下 IP 地址的出站流量,以便 Pod 能够与 GKE 元数据服务器通信。

  • 对于运行 GKE 1.21.0-gke.1000 及更高版本的集群,允许出站流量经端口 988 流向 169.254.169.252/32
  • 对于运行低于 1.21.0-gke.1000 的 GKE 版本的集群,允许出站流量经端口 988 流向 127.0.0.1/32
  • 对于运行 GKE Dataplane V2 的集群,允许出站流量经端口 80 流向 169.254.169.254/32

如果您不允许出站流量流向这些 IP 地址和端口,则在自动升级期间可能会遇到中断。

使用应用负载均衡器

将 Ingress 应用于 Service 以构建应用负载均衡器时,您必须配置应用于该 Service 背后的 Pod 的网络政策,以允许适当的应用负载均衡器健康检查 IP 范围。如果您使用的是内部应用负载均衡器,则还必须配置网络政策以允许代理专用子网

如果您没有对网络端点组使用容器原生负载均衡,则 Service 的节点端口可能会将连接转发到其他节点上的 Pod,除非通过在 Service 定义中将 externalTrafficPolicy 设置为 Local 来阻止它们这样做。如果 externalTrafficPolicy 未设置为 Local,则网络政策还必须允许从集群中的其他节点 IP 进行连接。

在 ipBlock 规则中包含 Pod IP 地址范围

如需控制特定 Pod 的流量,请始终使用 NetworkPolicy 入站流量或出站流量规则中的 namespaceSelectorpodSelector 字段按命名空间或 Pod 标签选择 Pod。请勿使用 ipBlock.cidr 字段有意选择 Pod IP 地址范围,因为它们本质上是临时性的。Kubernetes 项目未明确定义 ipBlock.cidr 字段包含 Pod IP 地址范围时的行为。在此字段中指定宽泛的 CIDR 范围(例如 0.0.0.0/0 [包括 Pod IP 地址范围])在 NetworkPolicy 的不同实现中可能会产生意外结果。

GKE Dataplane V2 中的 ipBlock 行为

使用 GKE Dataplane V2 实现的 NetworkPolicy 时,Pod 流量永远不会受 ipBlock 规则的覆盖。因此,即使您定义了 cidr: '0.0.0.0/0' 等宽泛规则,它也不会包含 Pod 流量。这非常有用,例如,您可以允许命名空间中的 Pod 接收来自互联网的流量,但不允许来自 Pod 的流量。如需同时添加 Pod 流量,请在 NetworkPolicy 的入站流量或出站流量规则定义中使用其他 Pod 或命名空间选择器明确选择 Pod。

问题排查

Pod 无法与使用 Private Service Connect 的集群上的控制平面通信

如果出站流量网络政策限制使用 Private Service Connect 的 GKE 集群上的 Pod 到控制平面的内部 IP 地址的出站流量,则 Pod 可能会遇到与控制平面的通信问题。

为了缓解这一问题:

  1. 查看您的集群是否使用 Private Service Connect。如需了解详情,请参阅使用 Private Service Connect 的公共集群。在使用 Private Service Connect 的集群上,每个控制平面都分配有集群节点子网中的内部 IP 地址。

  2. 配置集群的出站流量政策以允许发送到控制平面的内部 IP 地址的流量。

    如需查找控制平面的内部 IP 地址,请执行以下操作:

    gcloud

    如需查找 privateEndpoint,请运行以下命令:

    gcloud container clusters describe CLUSTER_NAME
    

    CLUSTER_NAME 替换为您的集群的名称。

    此命令会检索指定集群的 privateEndpoint

    控制台

    1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

      转到 Google Kubernetes Engine

    2. 在导航窗格的集群下,点击要查找内部 IP 地址的集群。

    3. 集群基本信息下,找到列出内部 IP 地址的 Internal endpoint

    在找到 privateEndpointInternal endpoint 后,请配置集群的出站流量政策以允许发送到控制平面的内部 IP 地址的流量。如需了解详情,请参阅创建网络政策

集群更新缓慢

在现有集群上启用或停用网络政策强制执行功能时,如果集群配置了维护期或排除项,则 GKE 可能不会立即更新节点。

取消安排手动部署的 Pod

在现有集群的控制平面上启用网络政策强制执行功能后,GKE 会取消安排任何手动部署的 ip-masquerade-agent 或 calico 节点 Pod。

在集群节点上启用网络政策强制执行功能并重新创建节点之前,GKE 不会重新安排这些 Pod。

如果您配置了维护时段或排除项,这可能会导致中断时间变长。

为了最大限度地减少中断的时长,您可以手动为集群节点分配以下标签:

  • node.kubernetes.io/masq-agent-ds-ready=true
  • projectcalico.org/ds-ready=true

网络政策未生效

如果 NetworkPolicy 未生效,则可以按照以下步骤进行问题排查:

  1. 确认已启用网络政策实施功能。使用的命令取决于您的集群是否已启用 GKE Dataplane V2。

    如果您的集群已启用 GKE Dataplane V2,请运行以下命令:

    kubectl -n kube-system get pods -l k8s-app=cilium
    

    如果输出为空,则表明未启用网络政策实施功能。

    如果您的集群未启用 GKE Dataplane V2,请运行以下命令:

    kubectl get nodes -l projectcalico.org/ds-ready=true
    

    如果输出为空,则表明未启用网络政策实施功能。

  2. 检查 Pod 标签:

    kubectl describe pod POD_NAME
    

    POD_NAME 替换为 Pod 的名称。

    输出内容类似如下:

    Labels:        app=store
                   pod-template-hash=64d9d4f554
                   version=v1
    
  3. 确认政策上的标签与 Pod 上的标签匹配:

    kubectl describe networkpolicy
    

    输出内容类似如下:

    PodSelector: app=store
    

    在此输出中,app=store 标签与上一步中的 app=store 标签匹配。

  4. 检查是否有任何网络政策选择您的工作负载:

    kubectl get networkpolicy
    

    如果输出为空,则表明没有在命名空间中创建 NetworkPolicy,并且没有任何网络政策选择您的工作负载。如果输出不为空,请检查政策是否选择了您的工作负载:

    kubectl describe networkpolicy
    

    输出内容类似如下:

    ...
    PodSelector:     app=nginx
    Allowing ingress traffic:
       To Port: <any> (traffic allowed to all ports)
       From:
          PodSelector: app=store
    Not affecting egress traffic
    Policy Types: Ingress
    

后续步骤