排查 Cloud NAT 问题

本指南可帮助您诊断工作负载(Pod 或虚拟机)为何无法使用 Cloud NAT 访问外部网络。作为开发者,您主要与 CloudNatGateway 资源互动。此资源的状态是您进行调试的主要可信来源。

准备工作

如需排查 Cloud NAT 配置问题,您必须具备以下条件:

  • 必要的身份和访问权限角色。请让您的项目 IAM 管理员授予您以下一个或两个角色:
    • Cloud NAT 查看者 (cloud-nat-viewer) :此角色提供对 Cloud NAT 资源的只读访问权限。此角色可帮助您开始诊断问题。
    • Cloud NAT 开发者 (cloud-nat-developer) :此角色为应用运维人员提供了在分配的项目中创建、读取、更新和删除 (CRUD) Cloud NAT 对象所需的权限。借助此角色,您可以执行本页面中所述的许多修复操作。
    • 对于某些特定的诊断措施和修复,可能需要其他角色。

初始诊断

在深入了解错误代码之前,请确保基本资源存在且可访问。

命令

kubectl get cloudnatgateway GATEWAY_NAME -n PROJECT_NAMESPACE -o yaml

替换以下内容:

  • GATEWAY_NAMECloudNatGateway 资源的名称。
  • PROJECT_NAMESPACE:项目的命名空间。

检查状态条件: 运行正常的网关必须将所有 以下条件设置为 True

  • Ready:全局运行状况。
  • SubnetsReady:IP 池配置有效。
  • PerimeterConfigurationReady:上游网络基础架构已配置。
  • EgressRoutesReady:Pod 的路由政策处于活跃状态。

如果其中任何一个为 False,请检查状态输出中的 reasonmessage 字段,并参阅以下部分中的表格。

错误代码参考和补救措施

kubectl get cloudnatgateway 返回的错误代码分为三个主要类别。

子网错误(SubnetsReady 为 False)

此条件表示分配给网关的 IP 地址池存在问题。

错误代码 具体含义 补救步骤
CloudNATSelectorFieldOverlapsCode 配置冲突。此网关的 workloadSelector 与项目中另一个网关的工作负载匹配。流量无法确定性地路由。
  1. 列出项目中的所有 Cloud NAT 网关:kubectl get cloudnatgateway
  2. 将此网关的 workloadSelector 与其他网关进行比较。
  3. 修改标签,以便没有单个 Pod/虚拟机被多个网关选中。
CloudNATSubnetRefsFieldInvalidCode

子网无效。subnetRefs 中指定的子网不可用。常见原因:

  • 子网不存在。
  • 子网未处于 Ready 状态。
  • 子网的类型不是 Leaf
  1. 验证子网是否存在:kubectl get subnet <SUBNET_NAME>
  2. 检查子网状态是否为 Ready
  3. 确保子网 typeLeaf(Cloud NAT 无法使用根子网或环回子网)。
CloudNATSubnetAlreadyInUseCode 子网冲突。您请求的子网已由另一个 Cloud NAT 网关“拥有”。一个子网一次只能附加到一个网关。
  1. 为此网关选择其他子网。
  2. 或者,先从另一个网关中移除该子网。
UNETAPIServerErrorCode 系统错误。控制器无法与 API 服务器通信以验证子网。 操作: 这可能是暂时性的平台问题。如果问题仍然存在,请与您的平台管理员联系。

边界配置错误(PerimeterConfigurationReady 为 False)

此条件反映了边界网关的状态。

错误代码 具体含义 补救步骤
NET-E0305 配置冲突。(同上)。选择器重叠会阻止系统计算正确的路由组。
  1. 列出项目中的所有 Cloud NAT 网关:kubectl get cloudnatgateway
  2. 将此网关的 workloadSelector 与其他网关进行比较。
  3. 修改标签,以便没有单个 Pod/虚拟机被多个网关选中。
NET-E0301 资源耗尽 / 节点失败。系统创建了配置,但无法将出站 IP 分配给运行正常的物理节点。这通常意味着子网的 IP 已用完,或者网关节点已关闭。
  1. 检查您的 [子网](/distributed-cloud/hosted/docs/latest/gdcag/platform/pa-user/subnets-overview)用量。是否已满?
  2. 如果子网有空闲 IP 且处于 Ready 状态,则表示平台端基础架构失败(例如,没有可用的运行正常的网关节点)。操作:与平台管理员联系。
NET-E0001 系统错误。控制器通信失败。 操作: 与平台管理员联系。

出站路由错误(EgressRoutesReady 为 False)

此条件反映了集群内路由政策的状态。

错误代码 具体含义 补救步骤
NET-E0305 配置冲突。(同上)。
  1. 列出项目中的所有 Cloud NAT 网关:kubectl get cloudnatgateway
  2. 将此网关的 workloadSelector 与其他网关进行比较。
  3. 修改标签,以便没有单个 Pod/虚拟机被多个网关选中。
NET-E0304 编程失败。系统无法为您的特定网关 IP 编程路由规则 (BPF)。

操作: 这是内部编程错误或状态不一致。

  1. 尝试对网关进行微不足道的更新(例如,修改标签)以触发协调。
  2. 如果问题仍然存在,请与平台管理员联系。

其他常见问题

如果网关状态为 Ready: True,但流量仍然失败,请检查以下常见的错误配置:

缺少项目级权限

您的项目必须明确获得出站流量授权。

  • 检查: 您的项目资源是否具有标签 networking.gdc.goog/enable-default-egress-allow-to-outside-the-org: "true"
  • 修复: 请让您的项目管理员应用此标签。

缺少虚拟机注解(仅限虚拟机)

虚拟机绕过标准 Pod 出站路径,需要明确说明才能使用 Cloud NAT。

  • 检查: 您的虚拟机 的 VirtualMachineExternalAccess (VMEA) 对象是否具有注解 egress.networking.gke.io/use-cloud-nat: "true"
  • 修复: 将注解添加到 VMEA 对象。

Standard 集群节点出站流量

如果您运行的是 Standard 集群,则节点本身需要出站流量权限。

  • 检查Cluster 对象是否具有标签 cluster.gdc.goog/enable-node-egress-to-outside-the-org: "true"
  • 修复: 请让您的平台管理员为 Cluster 对象添加标签。

默认出站 NAT 与 Cloud NAT 冲突

当工作负载配置为使用旧版默认出站 NAT 机制,同时被 Cloud NAT 网关选中时,会发生常见的配置错误。这种组合会导致数据平面收到冲突的路由说明,从而导致丟包或不确定的路由行为。

诊断 Pod 冲突

对于 Pod,通常通过添加特定标签来启用默认出站 NAT。Pod 不能同时具有此标签,也不能同时被 Cloud NAT 网关作为目标。

  1. 确定目标 Pod: 获取遇到连接问题的 Pod 的标签。

    kubectl get pod <POD_NAME> -n <NAMESPACE> --show-labels
    
  2. 检查是否存在冲突的标签

    • Cloud NAT 选择: Pod 的标签是否与命名空间中任何 CloudNatGatewayworkloadSelector 匹配?
    • 默认出站标签: Pod 是否具有标签 egress.networking.gke.io/enabled: "true"

    条件: 如果两者都为 true,则表示存在冲突。

  3. 解决方案: 从 Pod(或其父级 Deployment/StatefulSet)中移除旧版默认出站标签,以允许 Cloud NAT 接管独占控制权。

诊断虚拟机冲突

对于虚拟机,机制有所不同。具有 VirtualMachineExternalAccess (VMEA) 对象的虚拟机通常配置为默认访问。如需使用 Cloud NAT,它们必须通过添加注解来明确选择停用默认路径并启用 Cloud NAT 路径。

  1. 确定 VMEA: 找到与虚拟机关联的 VirtualMachineExternalAccess 对象。

    kubectl get vmea -n <NAMESPACE>
    
  2. 检查是否缺少注解

    • Cloud NAT 选择: 虚拟机的标签是否与 CloudNatGateway 匹配?
    • 选择启用注解: 检查 VMEA 是否具有注解 egress.networking.gke.io/use-cloud-nat: "true"

    条件: 如果虚拟机与网关匹配,但缺少此注解, 则流量将与默认出站系统冲突。

  3. 解决方案: 将注解添加到 VMEA 对象。

    kubectl annotate vmea <VMEA_NAME> -n <NAMESPACE> egress.networking.gke.io/use-cloud-nat="true"