本页面介绍了如何使用 GKE 的网络政策实施功能来控制集群的 Pod 和 Service 之间的通信。
您还可以使用完全限定的域名 (FQDN) 网络政策控制 Pod 流向集群外部的任何端点或 Service 的出站流量。如需了解详情,请参阅使用 FQDN 控制 Pod 和服务之间的通信。
GKE 网络政策实施功能的简介
借助网络政策实施功能,您可以在集群中创建 Kubernetes 网络政策。网络政策会创建 Pod 级层防火墙规则,以确定哪些 Pod 和 Service 可以在您的集群内相互访问。
定义网络政策可帮助您在集群服务于多级应用时启用深度防御等功能。例如,您可以创建网络政策,以确保应用中受侵的前端服务无法直接与低了几个级层的结算或记账服务进行通信。
网络政策还可以使您的应用更容易同时托管来自多个用户的数据。例如,您可以通过定义每个命名空间一个租户的模型来提供安全的多租户服务。在此类模型中,网络政策规则可确保给定命名空间中的 Pod 和服务无法访问其他命名空间中的其他 Pod 或服务。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行
gcloud components update
以获取最新版本。
要求和限制
以下要求和限制适用于 Autopilot 集群和 Standard 集群:- 您必须允许出站流量流向元数据服务器。
- 如果您在已启用 GKE Dataplane V2 的集群的网络政策中指定
endPort
字段,则从 GKE 1.22 版开始,该字段可能不会生效。如需了解详情,请参阅网络政策端口范围未生效。对于 Autopilot 集群,GKE Dataplane V2 始终处于启用状态。
- 如果您将网络政策与适用于 GKE 的工作负载身份联合搭配使用,则必须允许出站流量流向元数据服务器。
- 启用网络政策实施功能会使
kube-system
进程的内存占用量增加大约 128 MB,并且需要大约 300 millicore 的 CPU。这意味着,如果您为现有集群启用网络政策,则可能需要增加集群的大小以继续运行计划的工作负载。 - 启用网络政策强制执行功能需要重新创建节点。如果您的集群具备有效的维护窗口,则在下一个维护窗口之前不会自动重新创建节点。如果您愿意,可以随时手动升级集群。
- 运行网络政策实施功能的建议集群大小下限是三个
e2-medium
实例。 - 由于资源要求太高,因此节点为
f1-micro
或g1-small
实例的集群不支持网络政策。
如需详细了解节点机器类型和可分配资源,请参阅标准集群架构 - 节点。
启用网络政策实施功能
默认情况下,Autopilot 集群会启用网络政策实施功能,因此您可以跳至创建网络政策。
您可以使用 gcloud CLI、Google Cloud 控制台或 GKE API 在 Standard 中启用网络政策实施功能。
网络政策实施功能内置于 GKE Dataplane V2 中。您不需要在使用 GKE Dataplane V2 的集群中启用网络政策实施功能。
gcloud
-
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
如需在创建新集群时启用网络政策强制执行功能,请运行以下命令:
gcloud container clusters create CLUSTER_NAME --enable-network-policy
将
CLUSTER_NAME
替换为新集群的名称。如需为现有集群启用网络政策强制执行功能,请执行以下任务:
运行以下命令以启用该插件:
gcloud container clusters update CLUSTER_NAME --update-addons=NetworkPolicy=ENABLED
将
CLUSTER_NAME
替换为您的集群的名称。运行以下命令以在您的集群上启用网络政策强制执行功能,之后系统会为集群重新创建启用了网络政策强制执行功能的节点池:
gcloud container clusters update CLUSTER_NAME --enable-network-policy
控制台
如需在创建新集群时启用网络政策强制执行功能,请执行以下操作:
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击 add_box 创建。
在创建集群对话框中,点击 GKE Standard 对应的配置。
根据您的选择配置集群。
在导航窗格的集群下,点击网络。
选中启用网络政策复选框。
点击创建。
如需为现有集群启用网络政策强制执行功能,请执行以下操作:
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
在集群列表中,点击您要修改的集群的名称。
在网络下的网络政策字段中,点击 edit 修改网络政策。
选中启用主节点的网络政策复选框,然后点击保存更改。
等待更改应用,然后再次点击 edit 修改网络政策。
选中启用节点的网络政策复选框。
点击保存更改。
API
如需启用网络政策强制执行功能,请执行以下操作:
在您提供给 projects.zones.clusters.create 或 projects.zones.clusters.update 的
cluster
对象中指定networkPolicy
对象。networkPolicy
对象需要一个用于指定要使用的网络政策提供者的枚举值,以及一个指定是否启用网络政策的布尔值。如果启用网络政策但未设置提供者,则create
和update
命令将返回错误。
在 Standard 集群中停用网络政策实施功能
您可以使用 gcloud CLI、Google Cloud 控制台或 GKE API 停用网络政策实施功能。您无法在 Autopilot 集群或使用 GKE Dataplane V2 的集群中停用网络政策实施功能。
gcloud
-
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
如需停用网络政策强制执行功能,请执行以下任务:
- 在集群上停用网络政策强制执行功能:
gcloud container clusters update CLUSTER_NAME --no-enable-network-policy
将
CLUSTER_NAME
替换为您的集群的名称。运行此命令后,GKE 会为集群重新创建停用了网络政策强制执行功能的节点池。
验证是否已重新创建所有节点:
kubectl get nodes -l projectcalico.org/ds-ready=true
如果操作成功,则输出类似于以下内容:
No resources found
但如果输出类似于以下内容,则必须等待 GKE 完成节点池更新:
NAME STATUS ROLES AGE VERSION gke-calico-cluster2-default-pool-bd997d68-pgqn Ready,SchedulingDisabled <none> 15m v1.22.10-gke.600 gke-calico-cluster2-np2-c4331149-2mmz Ready <none> 6m58s v1.22.10-gke.600
停用网络政策强制执行功能后,如果您的集群配置了维护期或排除项,GKE 可能不会立即更新节点。如需了解详情,请参阅集群更新缓慢。
重新创建所有节点后,停用插件:
gcloud container clusters update CLUSTER_NAME --update-addons=NetworkPolicy=DISABLED
控制台
如需为现有集群停用网络政策强制执行功能,请执行以下操作:
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
在集群列表中,点击您要修改的集群的名称。
在网络下的网络政策字段中,点击 edit 修改网络政策。
清除启用节点的网络政策复选框,然后点击保存更改。
等待更改应用,然后再次点击 edit 修改网络政策。
清除启用主节点的网络政策复选框。
点击保存更改。
API
如需为现有集群停用网络政策强制执行功能,请执行以下操作:
通过
setNetworkPolicy
API 将集群更新为使用networkPolicy.enabled: false
。验证已使用 gcloud CLI 重新创建了所有节点:
kubectl get nodes -l projectcalico.org/ds-ready=true
如果操作成功,则输出类似于以下内容:
No resources found
但如果输出类似于以下内容,则必须等待 GKE 完成节点池更新:
NAME STATUS ROLES AGE VERSION gke-calico-cluster2-default-pool-bd997d68-pgqn Ready,SchedulingDisabled <none> 15m v1.22.10-gke.600 gke-calico-cluster2-np2-c4331149-2mmz Ready <none> 6m58s v1.22.10-gke.600
停用网络政策强制执行功能后,如果您的集群配置了维护期或排除项,GKE 可能不会立即更新节点。如需了解详情,请参阅集群更新缓慢。
通过
updateCluster
API 更新集群以使用update.desiredAddonsConfig.NetworkPolicyConfig.disabled: true
。
创建网络政策
您可以使用 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 地址和端口,则在自动升级期间可能会遇到中断。
从 Calico 迁移到 GKE Dataplane V2
如果您将网络政策从 Calico 迁移到 GKE Dataplane V2,请考虑以下限制:
您不能在
NetworkPolicy
清单的ipBlock.cidr
字段中使用 Pod 或 Service IP 地址。您必须使用标签来引用工作负载。例如,以下配置无效:- ipBlock: cidr: 10.8.0.6/32
不得在
NetworkPolicy
清单中指定空的ports.port
字段。如果指定了协议,则还必须指定端口。例如,以下配置无效:ingress: - ports: - protocol: TCP
使用应用负载均衡器
将 Ingress 应用于 Service 以构建应用负载均衡器时,您必须配置应用于该 Service 背后的 Pod 的网络政策,以允许适当的应用负载均衡器健康检查 IP 范围。如果您使用的是内部应用负载均衡器,则还必须配置网络政策以允许代理专用子网。
如果您没有对网络端点组使用容器原生负载均衡,则 Service 的节点端口可能会将连接转发到其他节点上的 Pod,除非通过在 Service 定义中将 externalTrafficPolicy
设置为 Local
来阻止它们这样做。如果 externalTrafficPolicy
未设置为 Local
,则网络政策还必须允许从集群中的其他节点 IP 进行连接。
在 ipBlock 规则中包含 Pod IP 地址范围
如需控制特定 Pod 的流量,请始终使用 NetworkPolicy 入站流量或出站流量规则中的 namespaceSelector
和 podSelector
字段按命名空间或 Pod 标签选择 Pod。请勿使用 ipBlock.cidr
字段有意选择 Pod IP 地址范围(此范围本质上是临时的)。Kubernetes 项目包含 Pod IP 地址范围时,不会明确定义 ipBlock.cidr
字段的行为。在此字段中指定宽泛的 CIDR 范围(例如 0.0.0.0/0
[包括 Pod IP 地址范围])在 NetworkPolicy 的不同实现中可能会产生意外结果。
GKE Dataplane V2 中的 ipBlock 行为
使用 NetworkPolicy 的 GKE Dataplane V2 实现时,ipBlock
规则绝不会涵盖 Pod 流量。因此,即使您定义了宽泛的规则(例如 cidr: '0.0.0.0/0'
),它也不会包含 Pod 流量。这非常有用,例如,您可以允许命名空间中的 Pod 接收来自互联网的流量,但不允许来自 Pod 的流量。如需同时添加 Pod 流量,请在 NetworkPolicy 的入站流量或出站流量规则定义中使用其他 Pod 或命名空间选择器明确选择 Pod。
Calico 的 ipBlock 行为
对于 NetworkPolicy 的 Calico 实现,ipBlock
规则确实涵盖 Pod 流量。使用此实现时,如需配置广泛的 CIDR 范围而不允许 Pod 流量,请明确排除集群的 Pod CIDR 范围,如以下示例所示:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-non-pod-traffic
spec:
ingress:
- from:
- ipBlock:
cidr: '0.0.0.0/0'
except: ['POD_IP_RANGE']
在此示例中,POD_IP_RANGE
是您的集群的 Pod IPv4 地址范围,例如 10.95.0.0/17
。如果您有多个 IP 地址范围,可单独将其包含在数组中,例如 ['10.95.0.0/17', '10.108.128.0/17']
。
问题排查
Pod 无法与使用 Private Service Connect 的集群上的控制平面通信
如果出站流量网络政策限制使用 Private Service Connect 的 GKE 集群上的 Pod 到控制平面的内部 IP 地址的出站流量,则 Pod 可能会遇到与控制平面的通信问题。
为了缓解这一问题:
查看您的集群是否使用 Private Service Connect。如需了解详情,请参阅使用 Private Service Connect 的公共集群。在使用 Private Service Connect 的集群上,每个控制平面都分配有集群节点子网中的内部 IP 地址。
配置集群的出站流量政策以允许发送到控制平面的内部 IP 地址的流量。
如需查找控制平面的内部 IP 地址,请执行以下操作:
gcloud
如需查找
privateEndpoint
,请运行以下命令:gcloud container clusters describe CLUSTER_NAME
将
CLUSTER_NAME
替换为您的集群的名称。此命令会检索指定集群的
privateEndpoint
。控制台
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
在导航窗格的集群下,点击要查找内部 IP 地址的集群。
在集群基本信息下,找到列出内部 IP 地址的
Internal endpoint
。
在找到
privateEndpoint
或Internal endpoint
后,请配置集群的出站流量政策以允许发送到控制平面的内部 IP 地址的流量。如需了解详情,请参阅创建网络政策。
集群更新缓慢
在现有集群上启用或停用网络政策强制执行功能时,如果集群配置了维护期或排除项,则 GKE 可能不会立即更新节点。
您可以通过将--cluster-version
标志设置为控制平面运行的同一 GKE 版本来手动升级节点池。您必须使用 Google Cloud CLI 执行此操作。如需了解详情,请参阅维护窗口的注意事项。
取消安排手动部署的 Pod
在现有集群的控制平面上启用网络政策强制执行功能后,GKE 会取消安排任何手动部署的 ip-masquerade-agent 或 calico 节点 Pod。
在集群节点上启用网络政策强制执行功能并重新创建节点之前,GKE 不会重新安排这些 Pod。
如果您配置了维护时段或排除项,这可能会导致中断时间变长。
为了最大限度地减少中断的时长,您可以手动为集群节点分配以下标签:
node.kubernetes.io/masq-agent-ds-ready=true
projectcalico.org/ds-ready=true
网络政策未生效
如果 NetworkPolicy 未生效,则可以按照以下步骤进行问题排查:
确认已启用网络政策实施功能。使用的命令取决于您的集群是否已启用 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
如果输出为空,则表明未启用网络政策实施功能。
检查 Pod 标签:
kubectl describe pod POD_NAME
将
POD_NAME
替换为 Pod 的名称。输出内容类似如下:
Labels: app=store pod-template-hash=64d9d4f554 version=v1
确认政策上的标签与 Pod 上的标签匹配:
kubectl describe networkpolicy
输出内容类似如下:
PodSelector: app=store
在此输出中,
app=store
标签与上一步中的app=store
标签匹配。检查是否有任何网络政策选择您的工作负载:
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
已知问题
使用 Calico 终止 StatefulSet Pod
启用了 Calico 网络政策的 GKE 集群可能会遇到以下问题:删除 StatefulSet pod 时,该 pod 会丢弃现有连接。在 pod 进入 Terminating
状态后,将不会再遵循 pod 规范中的 terminationGracePeriodSeconds
配置,并且会导致当前与 StatefulSet pod 连接的其他应用中断。如需详细了解此问题,请参阅 Calico 问题 #4710。
此问题会影响以下 GKE 版本:
- 1.18
- 1.19 至 1.19.16-gke.99
- 1.20 至 1.20.11-gke.1299
- 1.21 至 1.21.4-gke.1499
为了缓解这一问题,请将 GKE 控制平面升级到以下版本之一:
- 1.19.16-gke.100 或更高版本
- 1.20.11-gke.1300 或更高版本
- 1.21.4-gke.1500 或更高版本
Pod 卡滞在 containerCreating
状态
在某些情况下,启用了 Calico 网络政策的 GKE 集群可能会遇到 Pod 卡滞在 containerCreating
状态的问题。
在 Pod 事件标签页下,您会看到类似于以下内容的消息:
plugin type="calico" failed (add): ipAddrs is not compatible with
configured IPAM: host-local
为了缓解这一问题,请在 GKE 集群中使用 Calico 的 host-local ipam 而不是 calico-ipam。