You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kubernetes Pod终止时出现ECONNREFUSED错误的排查求助

问题分析与解决方案

核心问题

搜索逻辑服务(search-api)在Pod缩容/滚动更新时,API网关调用频繁出现ECONNREFUSED错误,即使添加了preStop: sleep 60仍无法彻底解决,滚动更新时错误更频发。

可能的根因

  • Endpoint更新与Pod终止存在时间差:Kubernetes从Service的Endpoint列表移除Pod,和Pod实际停止接受请求的窗口没完全对齐,哪怕加了preStop延迟,仍可能有流量打到已标记为Terminating的Pod
  • Readiness探针未主动摘除流量:当前readiness probe仅检查/healthz,但Pod进入Terminating状态后,Kubernetes自动移除就绪状态的动作有延迟,网关可能还持有旧连接
  • 网关DNS缓存与连接复用问题:即便加了connection: close,网关侧DNS缓存可能保留旧Pod IP,或HTTP客户端连接池未及时清理失效连接
  • 滚动更新策略细节不合理:maxUnavailable: 0虽保证可用性,但maxSurge:2可能导致新Pod未就绪时旧Pod已开始终止,引发流量分发异常

针对性解决方案

1. 优化Readiness探针与Pod终止逻辑

在preStop钩子中先主动让readiness probe失败,彻底从Service Endpoint移除后再延迟终止。修改Deployment的相关配置:

containers:
  # ... 保留原有其他配置
  lifecycle:
    preStop:
      exec:
        command:
        - sh
        - -c
        - "touch /tmp/terminating && sleep 60"  # 创建标记文件触发就绪探针失败
  readinessProbe:
    exec:  # 替换原httpGet探针,结合健康检查与终止标记判断
      command:
      - sh
      - -c
      - "test ! -f /tmp/terminating && curl -f http://localhost:8080/healthz"
    initialDelaySeconds: 15
    periodSeconds: 5

这样Pod启动终止流程时,立刻让就绪探针失败,Kubernetes会快速将其从Endpoint列表剔除,sleep60秒再真正终止,确保流量完全切走。

2. 调整Pod生命周期时间配置

延长终止宽限期,给足Endpoint更新的时间;同时拉长新Pod的就绪等待时间,确保稳定后再接收流量:

spec:
  minReadySeconds: 10  # 原5秒,延长至10秒确保新Pod稳定
  terminationGracePeriodSeconds: 120  # 原90秒,延长至120秒覆盖preStop的60秒

3. 优化API网关的HTTP客户端配置

禁用长连接、清理DNS缓存、添加重试机制,避免失效连接和旧IP带来的问题。修改axios配置:

const http = require('http');
const https = require('https');
const axios = require('axios');
const axiosRetry = require('axios-retry');

// 创建axios实例,禁用长连接
const axiosInstance = axios.create({
  headers: {
    'Content-Type': 'application/json',
    Accept: 'application/json',
    'X-Request-Id': request_id
  },
  httpAgent: new http.Agent({
    keepAlive: false,
    maxSockets: 100,
    timeout: 5000
  }),
  httpsAgent: new https.Agent({
    keepAlive: false,
    maxSockets: 100,
    timeout: 5000
  }),
  timeout: 5000
});

// 针对连接错误添加重试
axiosRetry(axiosInstance, {
  retries: 2,
  retryDelay: (count) => count * 100,
  retryCondition: (err) => err.code === 'ECONNREFUSED' || err.code === 'ETIMEDOUT'
});

// 调用接口时使用该实例
await axiosInstance.post('http://search-api:80/logic/endpoint', payload);

4. 调整滚动更新策略

降低每次更新的Pod数量,确保新Pod完全就绪后再终止旧Pod:

strategy:
  rollingUpdate:
    maxSurge: 1  # 原2,改为每次仅新增1个Pod
    maxUnavailable: 0
  type: RollingUpdate

5. 启用GKE连接排空功能

借助GKE的BackendConfig实现连接排空,确保Pod终止前处理完现有连接,不再接收新流量:
首先创建BackendConfig资源:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: search-api-backend-config
spec:
  connectionDraining:
    drainingTimeoutSec: 60

然后给search-api的Deployment添加注解:

metadata:
  annotations:
    cloud.google.com/backend-config: '{"default": "search-api-backend-config"}'

验证步骤

  1. 应用所有配置后,执行滚动更新:kubectl rollout restart deployment search-api
  2. 监控网关错误日志,观察ECONNREFUSED错误是否消失
  3. 缩容Pod时,检查Endpoint列表:kubectl get endpoints search-api,确认Terminating状态的Pod被及时移除
  4. 查看Pod事件:kubectl describe pod <pod-name>,确认preStop触发后readiness probe立即失败

内容的提问来源于stack exchange,提问作者Wazbat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:49:55