GKE Gateway 30秒超时问题深度排查全纪录

1. 网络流量与超时点概览

为了更好地理解问题,我们首先需要了解外部请求是如何通过GKE Gateway到达我们的服务Pod的,以及在这个链条中存在哪些超时点。
Actual Traffic Flow Google Cloud (Auto-Provisioned Resources) Kubernetes Cluster (Our Configuration) Controls Controls Controls Controls Client/User Service Pod External HTTPS LB (Forwarding Rule, Proxy) URL Map (Timeout #1 - Ignored) Backend Service (Timeout #2 - Ignored) Network Endpoint Group Gateway Resource HTTPRoute Resource Service (Type: ClusterIP) BackendConfig

核心问题 : 我们在Kubernetes中配置HTTPRouteBackendConfig的尝试,都未能成功修改URL MapBackend Service这两个关键资源中的超时值,导致它们一直停留在默认的30秒。


2. 问题背景

部署在GKE上的服务(例如py-github-agent代码审查或chat-api-svc聊天机器人)在处理耗时较长的任务时,外部API请求总是在大约30秒后被中断。

核心症状:

  • 对于批处理API (如代码审查) : 请求直接失败,客户端收到504 Gateway Timeoutstream timeout错误。
  • 对于流式API (如LLM聊天) : 连接在30秒时被强行切断。这会导致前端收到的流式数据被突然截断,用户看到一半的回答后就停止了。
  • 共同点: 服务Pod内的日志显示应用本身仍在正常处理,并未出错,只是客户端连接丢失了。

目标: 将负载均衡器的超时时间延长至600秒,以支持长耗时任务和完整的流式响应。


3. 第一轮排查:区分内部与外部问题

假设: 问题可能出在应用本身或集群内部网络。

步骤:

  1. 获取服务ClusterIP :

    bash 复制代码
    kubectl get svc clusterip-py-github-agent -o jsonpath='{.spec.clusterIP}'
    # 输出: 192.172.23.160
  2. 在集群内部发起测试 : 我们在集群内部署一个临时的curl测试Pod,直接向该ClusterIP发起一个长超时的请求。

    bash 复制代码
    kubectl run curl-test-pod --image=curlimages/curl --rm -i --restart=Never -- curl -m 600 ... http://192.172.23.160:8000/review
  3. 结果 : 测试成功! 请求在超过1分钟后成功返回了完整的JSON响应。

结论 : 应用本身和Kubernetes集群内部的服务网络均没有问题 。问题几乎100%出在从外部流量入口到集群内部的GKE Gateway 或其管理的Google Cloud负载均衡器上。


4. 第二轮排查:尝试Kubernetes原生配置

我们尝试了两种Kubernetes声明式的方法来配置超时。

方案A: 使用HTTPRoute (标准Gateway API)

HTTPRoute是Gateway API的标准资源,它允许为特定路由规则定义超时。

步骤:

  1. 修改k8s/httproute.yaml,为/py-github-agent规则添加timeouts字段。

    yaml 复制代码
    ...
    rules:
      - backendRefs:
          - name: clusterip-py-github-agent
            port: 8000
        matches:
        - path:
            type: PathPrefix
            value: /py-github-agent
        timeouts:
          request: 600s # <-- 添加此配置
  2. 应用配置: kubectl apply -f k8s/httproute.yaml

  3. 结果 : 失败! 外部请求依旧在30秒后超时。

方案B: 使用BackendConfig (GKE原生)

BackendConfig是GKE提供的一种自定义资源,用于配置由GKE控制器创建的后端服务。

步骤:

  1. 创建k8s/backend-config.yaml文件:

    yaml 复制代码
    apiVersion: cloud.google.com/v1
    kind: BackendConfig
    metadata:
      name: py-github-agent-backend-config
    spec:
      timeoutSec: 600
  2. py-github-agentService添加注解,将其与BackendConfig关联。

    yaml 复制代码
    # helm/templates/service.yaml
    ...
    metadata:
      annotations:
        cloud.google.com/backend-config: '{"default": "py-github-agent-backend-config"}'
    ...
  3. 应用配置。

  4. 结果 : 失败! 外部请求依旧在30秒后超时。


5. 第三轮排查:深入GCP底层资源

既然所有Kubernetes层面的声明式配置都失败了,我们必须深入到由GKE自动创建的Google Cloud原生资源层去一探究竟。

步骤1: 检查Backend Service

Backend Service是负载均衡器的核心组件,直接定义了后端的行为,包括超时。

动作:

  1. 找到由GKE为我们的服务自动创建的Backend Service真实名称

    bash 复制代码
    gcloud compute backend-services list | grep github-agent
    # 输出: gkegw1-bu0s-default-clusterip-py-github-agent-8000-iymtp0imv8al
  2. 检查这个Backend Service的实时timeoutSec属性。

    bash 复制代码
    gcloud compute backend-services describe gkegw1-bu0s-default-clusterip-py-github-agent-8000-iymtp0imv8al --global --format="value(timeoutSec)"
  3. 惊人发现 : 输出为 30

结论 : 这证明了我们在Kubernetes中应用的BackendConfig完全没有生效 。GKE控制器忽略了我们的配置,并使用了30秒的默认值。这显然是GKE控制器的一个Bug

步骤2: 第一次手动修复

假设 : 既然Backend Service是问题的关键,手动修复它应该能解决问题。

动作:

  1. 使用gcloud命令强制更新Backend Service的超时。

    bash 复制代码
    gcloud compute backend-services update gkegw1-bu0s-default-clusterip-py-github-agent-8000-iymtp0imv8al --global --timeout=600
  2. 等待1分钟后,重新测试外部curl请求。

  3. 结果 : 再次失败! 依旧是504 stream timeout

步骤3: 检查URL Map

假设 : 问题可能在比Backend Service更高一层的URL Map上。URL Map中的路由规则也可以定义超时,并且其优先级可能更高。

动作:

  1. 导出URL Map的完整YAML配置进行分析。

    bash 复制代码
    gcloud compute url-maps describe gkegw1-bu0s-default-py-api-gateway-rrnx141i3brm --format=yaml
  2. 发现 : 在匹配/py-github-agent路径的routeAction中,完全没有timeout字段

最终假设 : 当URL MaprouteAction中没有明确的timeout时,它不会继承Backend Service的超时,而是使用一个独立的、全局默认的30秒超时。而我们在HTTPRoute中的配置(本应在此处生效)被GKE控制器忽略了(又一个Bug)。


6. 意外的解决方案:漫长的生效延迟

在我们准备对URL Map进行更复杂的手动修复时,应您的要求,我们又进行了一次最终的外部curl测试。

结果 : 成功了!

最终结论 :

问题的根源确实是Backend Service的超时配置错误。我们使用gcloud手动将其更新为600秒的操作是正确的

然而,这个变更在Google Cloud的全球负载均衡器基础设施上完全生效,花费了远超预期的漫长时间(超过10分钟) 。我们紧随其后的测试都因为配置尚未生效而失败,从而误导我们去排查更高层的URL Map。在我们进行讨论和检查的这段时间里,配置最终悄悄地完成了同步。

7. 总结与反思

  1. GKE Gateway Bug : GKE Gateway控制器目前存在Bug,无法稳定地将HTTPRoute.timeoutsService上的BackendConfig注解同步到底层的GCP资源。
  2. 手动干预是最后手段 : 当声明式配置失效时,直接使用gcloud命令检查和修改底层的云资源是排查问题的终极手段。
  3. 配置生效延迟: 对于全局网络资源,变更可能需要很长的时间才能完全生效,需要有足够的耐心等待和验证。

虽然手动修改云资源会造成"配置漂移",但在这种控制器Bug的情况下,这是恢复服务的唯一有效方法。建议将此类手动变更详细记录,并考虑在未来通过Terraform等工具管理这些云资源,或向Google报告此Bug。

相关推荐
8***a8152 小时前
SpringCloud Gateway 集成 Sentinel 详解 及实现动态监听Nacos规则配置实时更新流控规则
spring cloud·gateway·sentinel
nvd111 天前
GKE Gateway API: 统一入口下的前后端路由策略
gateway
n***s9091 天前
springcloud-eureka与gateway简易搭建
spring cloud·eureka·gateway
b***62951 天前
SpringCloud Gateway 集成 Sentinel 详解 及实现动态监听Nacos规则配置实时更新流控规则
spring cloud·gateway·sentinel
4***17271 天前
SpringCloud实战十三:Gateway之 Spring Cloud Gateway 动态路由
java·spring cloud·gateway
A***F1571 天前
SpringGateway网关(Spring Gateway是Spring自己编写的,也是SpringCloud中的组件)
spring·spring cloud·gateway
4***W4292 天前
SpringCloud实战十三:Gateway之 Spring Cloud Gateway 动态路由
java·spring cloud·gateway
3***68842 天前
SpringCloud Gateway 集成 Sentinel 详解 及实现动态监听Nacos规则配置实时更新流控规则
spring cloud·gateway·sentinel
i***22072 天前
Gateway Timeout504 网关超时的完美解决方法
gateway