本页面介绍了如何为 Google Kubernetes Engine (GKE) 集群启用 GKE Dataplane V2。
新的 Autopilot 集群在 1.22.7-gke.1500 版及更高版本和 1.23.4-gke.1500 版及更高版本中启用了 GKE Dataplane V2。 如果您在使用 GKE Dataplane V2 时遇到问题,请跳到问题排查。
使用 GKE Dataplane V2 创建 GKE 集群
您可以在创建具有 GKE 1.20.6-gke.700 版及更高版本的新集群时使用 gcloud CLI 或 Kubernetes Engine AP 来启用 GKE Dataplane V2。您还可以在创建具有 GKE 1.17.9 版及更高版本的新集群时启用预览版 GKE Dataplane V2
控制台
如需使用 GKE Dataplane V2 创建新集群,请执行以下任务:
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击 add_box 创建。
点击配置以配置标准集群。
在“网络”部分中,选中启用 Dataplane V2复选框。当您选择“启用 Dataplane V2”时,“启用 Kubernetes 网络政策”选项会停用,因为网络政策强制执行功能内置于 GKE Dataplane V2 中。
点击创建。
gcloud
如需使用 GKE Dataplane V2 创建新集群,请使用以下命令:
gcloud container clusters create CLUSTER_NAME \
--enable-dataplane-v2 \
--enable-ip-alias \
--release-channel CHANNEL_NAME \
--location COMPUTE_LOCATION
替换以下内容:
CLUSTER_NAME
:新集群的名称。CHANNEL_NAME
:包含 GKE 1.20.6-gke.700 版或更高版本的发布渠道。如果您不想使用发布渠道,还可以使用--cluster-version
标志而不是--release-channel
,从而指定 1.20.6-gke.700 或更高版本。COMPUTE_LOCATION
:新集群的 Compute Engine 位置。
API
如需使用 GKE Dataplane V2 创建新集群,请在集群 create
请求中指定 networkConfig
对象的 datapathProvider
字段。
以下 JSON 代码段显示了启用 GKE Dataplane V2 所需的配置:
"cluster":{
"initialClusterVersion":"VERSION",
"ipAllocationPolicy":{
"useIpAliases":true
},
"networkConfig":{
"datapathProvider":"ADVANCED_DATAPATH"
},
"releaseChannel":{
"channel":"CHANNEL_NAME"
}
}
替换以下内容:
- VERSION:您的集群版本,必须为 GKE 1.20.6-gke.700 或更高版本。
- CHANNEL_NAME:包含 GKE 1.20.6-gke.700 版或更高版本的发布渠道。
GKE Dataplane V2 问题排查
本部分介绍如何调查和解决 GKE Dataplane V2 的问题。
确认已启用 GKE Dataplane V2:
kubectl -n kube-system get pods -l k8s-app=cilium -o wide
如果 GKE Dataplane V2 正在运行,则输出包含前缀为
anetd-
的 Pod。anetd 是 GKE Dataplane V2 的网络控制器。如果问题在于服务或网络政策强制执行方式,请检查
anetd
Pod 日志。在 Cloud Logging 中使用以下日志选择器:resource.type="k8s_container" labels."k8s-pod/k8s-app"="cilium" resource.labels.cluster_name="CLUSTER_NAME"
如果 Pod 创建失败,请检查 kubelet 日志以获取相关线索。在 Cloud Logging 中使用以下日志选择器:
resource.type="k8s_node" log_name=~".*/logs/kubelet" resource.labels.cluster_name="CLUSTER_NAME"
将
CLUSTER_NAME
替换为集群的名称,或将其完全移除以查看所有集群的日志。
已知问题
网络政策端口范围不生效
如果您在已启用 GKE Dataplane V2 的集群的网络政策中指定 endPort
字段,则该字段将不会生效。
从 GKE 1.22 开始,Kubernetes Network Policy API 允许您指定强制执行网络政策的端口范围。具有 Calico 网络政策的集群支持此 API,但具有 GKE Dataplane V2 的集群不支持此 API。
如需验证 NetworkPolicy
对象的行为,您可以在将它们写入 API 服务器后重新读取这些对象。如果对象仍包含 endPort
字段,则系统会强制执行该功能。如果缺少 endPort
字段,则不会强制执行该功能。在所有情况下,存储在 API 服务器中的对象都是网络政策的可靠来源。
如需了解详情,请参阅 KEP-2079:支持端口范围的网络政策。
Pod 显示 failed to allocate for range 0: no IP addresses available in range set
错误消息
受影响的 GKE 版本:1.22 至 1.25
运行使用 containerd 并启用了 GKE Dataplane V2 的节点池的 GKE 集群可能会遇到 IP 地址泄漏问题,并耗尽节点上的所有 Pod IP 地址。受影响的节点上安排的 Pod 会显示类似于以下内容的错误消息:
failed to allocate for range 0: no IP addresses available in range set: 10.48.131.1-10.48.131.62
如需详细了解该问题,请参阅 containerd 问题 #5768。
固定版本
如需解决此问题,请将集群升级到以下某个 GKE 版本:
- 1.22.17-gke.3100 或更高版本。
- 1.23.16-gke.200 或更高版本。
- 1.24.9-gke.3200 或更高版本。
- 1.25.6-gke.200 或更高版本。
标准 GKE 集群的解决方法
您可以通过删除节点的泄漏 Pod IP 地址来缓解此问题。
如需删除泄漏的 Pod IP 地址,请获取集群的身份验证凭据并执行以下步骤来清理单个节点(如果您知道其名称)。
将以下 shell 脚本保存到名为
cleanup.sh
的文件中:for hash in $(sudo find /var/lib/cni/networks/gke-pod-network -iregex '/var/lib/cni/networks/gke-pod-network/[0-9].*' -exec head -n1 {} \;); do hash="${hash%%[[:space:]]}"; if [ -z $(sudo ctr -n k8s.io c ls | grep $hash | awk '{print $1}') ]; then sudo grep -ilr $hash /var/lib/cni/networks/gke-pod-network; fi; done | sudo xargs -r rm
在集群节点上运行脚本:
gcloud compute ssh --zone "ZONE" --project "PROJECT" NODE_NAME --command "$(cat cleanup.sh)"
将
NODE_NAME
替换为该节点的名称。
您还可以运行此脚本的 DaemonSet 版本以同时在所有节点上并行运行:
将以下清单保存到名为
cleanup-ips.yaml
的文件中:apiVersion: apps/v1 kind: DaemonSet metadata: name: cleanup-ipam-dir namespace: kube-system spec: selector: matchLabels: name: cleanup-ipam template: metadata: labels: name: cleanup-ipam spec: hostNetwork: true securityContext: runAsUser: 0 runAsGroup: 0 containers: - name: cleanup-ipam image: gcr.io/gke-networking-test-images/ubuntu-test:2022 command: - /bin/bash - -c - | while true; do for hash in $(find /hostipam -iregex '/hostipam/[0-9].*' -mmin +10 -exec head -n1 {} \; ); do hash="${hash%%[[:space:]]}" if [ -z $(ctr -n k8s.io c ls | grep $hash | awk '{print $1}') ]; then grep -ilr $hash /hostipam fi done | xargs -r rm echo "Done cleaning up /var/lib/cni/networks/gke-pod-network at $(date)" sleep 120s done volumeMounts: - name: host-ipam mountPath: /hostipam - name: host-ctr mountPath: /run/containerd volumes: - name: host-ipam hostPath: path: /var/lib/cni/networks/gke-pod-network - name: host-ctr hostPath: path: /run/containerd
在集群上运行 daemonset:
kubectl apply -f cleanup-ips.yaml
您必须具有集群管理员的 kubectl 访问权限才能运行此命令。
检查正在运行的 DaemonSet 的日志:
kubectl -n kube-system logs -l name=cleanup-ipam
由于连接跟踪查找不正确,网络政策丢弃了连接
当客户端 Pod 通过 Service 或内部直通式网络负载均衡器的虚拟 IP 地址连接到自身时,由于数据平面中不正确的 conntrack 查找,回复数据包不会被识别为现有连接的一部分。这意味着限制 pod 入口流量的网络政策未在数据包上正确施行。
此问题的影响取决于为 Service 配置的 Pod 数量。比方说,如果 Service 有 1 个后端 Pod,则连接始终失败。如果 Service 有 2 个后端 Pod,则连接失败几率为 50%。
固定版本
如需解决此问题,请将集群升级到以下某个 GKE 版本:
- 1.28.3-gke.1090000 或更高版本。
解决方法
要缓解此问题,您可以将 Service 清单中的 port
和 containerPort
配置为相同的值。
“发卡”(hairpin) 连接流的数据包丢弃
当 Pod 使用 Service 创建与其自身的 TCP 连接时,Pod 同时是连接的来源和目的地时,GKE Dataplane V2 eBPF 连接跟踪会错误地跟踪连接状态,从而导致 conntrack 条目泄露。
当连接元组(协议、源/目标 IP 和源/目标端口)泄露时,使用同一连接元组的新连接可能会导致返回数据包丢弃。
固定版本
如需解决此问题,请将集群升级到以下某个 GKE 版本:
- 1.28.3-gke.1090000 或更高版本
- 1.27.11-gke.1097000 或更高版本
解决方法
请使用下列解决方法之一:
为可能使用 Service 与自己通信的 Pod 中运行的应用启用 TCP 重复使用 (keep-alive)。这可以防止发出 TCP FIN 标志,并避免泄露 conntrack 条目。
使用短期连接时,请使用代理负载均衡器(例如网关)公开 Pod,以公开 Service。这会导致连接请求的目的地设置为负载均衡器 IP 地址,从而阻止 GKE Dataplane V2 对环回 IP 地址执行 SNAT。
后续步骤
- 使用网络政策日志记录功能记录集群网络政策允许或拒绝与 Pod 连接的时间。
- 了解 GKE Dataplane V2 的工作原理。