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

GKE环境Node.js应用readinessProbe失败排查与零停机配置方案

问题根因

探测频率不符合配置预期的原因

你观测到的每秒3次探测请求,并非全部来自kubelet的readinessProbe,实际是三类健康检查流量叠加的结果:

  • kubelet本身的探针重试机制:探针请求失败后不会等待下一个periodSeconds周期,会立刻发起重试,直到达到failureThreshold阈值才会更新就绪状态
  • GKE Service层自带的健康检查:kube-proxy会对每个后端Pod端口做周期性连通性校验
  • GKE Ingress控制器独立的健康检查:默认以1秒/次的频率探测后端Pod,和kubelet探针完全独立,不会使用你在Pod配置里定义的探测参数
    三类流量叠加后,实际到达Pod的探测请求频率远高于配置的3秒1次。

偶发连接拒绝、流量被阻断的原因

故障本质不是应用层限流导致,是多层问题叠加触发的误摘除:

  1. Node.js单线程事件循环在运行过程中会出现偶发的短暂阻塞:比如老生代GC停顿、大响应体序列化、节点CPU被同节点其他负载抢占、瞬时IO打满,阻塞时长一旦超过探针配置的3秒超时时间,内核层面的TCP连接队列就会被堆积的探测请求打满,新到的探针请求会被内核直接返回connection refused,根本到不了Express应用层,所以你排除Express限流规则后故障依然会复现。
  2. 原配置中readinessProbe的failureThreshold使用默认值3,超时时间仅3秒,只要连续3次探测(算上重试实际仅需数秒)失败,kubelet就会把Pod从Service Endpoints列表中摘除,Ingress也会同步停止转发流量,导致业务完全中断。
  3. 最初观测到的429报错,是阻塞时间较短时请求能到达Express层、触发限流规则的表现,和后续的连接拒绝是同一个根因的不同阶段表现。
零停机部署最佳配置方案

代码层调整

  • 拆分健康检查端口:在业务端口(3003)之外,单独启动一个极简HTTP服务监听独立端口(比如3004),不接入任何Express业务中间件,所有请求直接返回200状态码,完全不受业务逻辑阻塞影响,专门用于kubelet和Ingress的运行时健康检查。
  • 启动检查逻辑保留在业务端口:/health/startup路径仅在服务启动阶段校验DB、缓存等强依赖连接状态,服务启动完成后不再执行重依赖校验,避免运行时DB抖动导致Pod被误摘。
  • 启动HTTP服务时调整TCP backlog参数,将默认的128调整为511,避免突发探测请求打满内核连接队列,示例:
// 业务服务
app.listen(3003, '0.0.0.0', 511, () => {
  console.log('Business server running on 3003')
})
// 独立健康检查服务
const healthServer = require('http').createServer((req, res) => res.end('ok'))
healthServer.listen(3004, '0.0.0.0', 511)

K8s资源配置调整

  • 探针配置参考如下,兼顾启动灵活性和运行时稳定性:
startupProbe:
                httpGet:
                  path: /health/startup
                  port: 3003
                initialDelaySeconds: 0
                periodSeconds: 2
                timeoutSeconds: 2
                failureThreshold: 30 # 最长容忍60秒启动时间,适配冷启动、慢DB连接场景
                successThreshold: 1
              readinessProbe:
                httpGet:
                  path: /
                  port: 3004
                initialDelaySeconds: 0
                periodSeconds: 5
                timeoutSeconds: 2
                failureThreshold: 5 # 连续10秒探测失败才摘除流量,过滤偶发卡顿
                successThreshold: 1
              livenessProbe:
                httpGet:
                  path: /
                  port: 3004
                initialDelaySeconds: 10 # startupProbe成功后再启动存活检查
                periodSeconds: 10
                timeoutSeconds: 2
                failureThreshold: 6 # 连续1分钟无响应才重启进程,避免误重启
                successThreshold: 1
              lifecycle:
                preStop:
                  exec:
                    command: ["/bin/sh", "-c", "sleep 3; kill -TERM 1"] # 等待3秒让流量规则同步完成再终止进程
  • 为Pod配置匹配实际负载的CPU、内存requests值,避免节点资源超卖时业务进程被抢占CPU导致事件循环阻塞。
  • 若使用GCE原生Ingress,手动将Ingress后端健康检查的探测间隔调整为5秒、超时2秒、不健康阈值5次,探测路径指向3004健康检查端口,和Pod侧探针规则对齐,避免Ingress侧提前摘除流量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 02:27:28