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

Kubernetes零停机部署时出现连接拒绝,负载均衡异常

解决Kubernetes滚动更新时的连接拒绝问题

嘿,我看你在GKE上尝试零停机部署时碰到了连接拒绝的坑,结合你的配置和环境,我来帮你拆解下问题出在哪,以及怎么修复:

问题根源

你遇到的核心问题和两个配置强相关:

  • Service的externalTrafficPolicy: Local:这个设置是为了保留客户端源IP,但它会让LoadBalancer只把流量打给运行着myapp Pod的节点。如果某个节点上的旧Pod被删除,新Pod还没通过就绪探针,这个节点暂时没有可用Pod,而LoadBalancer的后端列表又没及时更新,流量打过来就会直接被拒绝。
  • 滚动更新的参数配合:你设置了maxUnavailable: 0,意味着更新时必须等新Pod就绪才会删旧Pod,但maxSurge:1只允许额外启动1个Pod,加上原有的3个总共4个。新Pod从启动到就绪需要5秒(initialDelaySeconds:5),这个窗口期里,要是LoadBalancer还把流量分到刚删完旧Pod、新Pod还没就绪的节点,就会出问题。

具体解决方案

方案一:快速解决(不需要保留客户端源IP)

如果你的业务不需要知道客户端真实IP,直接把Service的externalTrafficPolicy改成默认的Cluster就行。这样kube-proxy会帮你把流量转发到集群内任意可用的Pod,哪怕节点上没Pod,也会路由到其他有Pod的节点,不会出现连接拒绝:

apiVersion: v1
kind: Service
metadata:
  name: myapp-lb
  labels:
    app: myapp
spec:
  type: LoadBalancer
  externalTrafficPolicy: Cluster  # 这里改成Cluster
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp

方案二:保留源IP的优化方案

如果你必须保留客户端源IP,那需要做几个调整来缩小无可用Pod的窗口期:

  1. 调整滚动更新策略:把maxUnavailable设为1,maxSurge设为2,这样更新时会先启动更多新Pod,再逐步删除旧Pod,减少节点空窗期:
    strategy:
      type: RollingUpdate
      rollingUpdate:
        maxUnavailable: 1
        maxSurge: 2
    
  2. 优化就绪探针:hello-app启动速度很快,把initialDelaySeconds调短点,比如改成2秒,让新Pod更快进入就绪状态:
    readinessProbe:
      httpGet:
        path: /
        port: 8080
      initialDelaySeconds: 2
      periodSeconds: 3
      successThreshold: 1
    
  3. 检查GCP健康检查配置:GKE会自动给LoadBalancer配置健康检查,你可以去GCP控制台看看健康检查的失败阈值,把它调低,让LoadBalancer更快移除没有可用Pod的节点。

验证步骤

修改完配置后,重新部署:

kubectl apply -f your-deployment-file.yaml
kubectl apply -f your-service-file.yaml

然后再跑你的测试脚本:

while true; do curl 35.205.100.174; sleep 0.2; done

同时可以用kubectl get pods -w实时观察Pod的状态,确认新Pod就绪后旧Pod才会被删除。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:33:52