Kubernetes零停机部署时出现连接拒绝,负载均衡异常
解决Kubernetes滚动更新时的连接拒绝问题
嘿,我看你在GKE上尝试零停机部署时碰到了连接拒绝的坑,结合你的配置和环境,我来帮你拆解下问题出在哪,以及怎么修复:
问题根源
你遇到的核心问题和两个配置强相关:
- Service的
externalTrafficPolicy: Local:这个设置是为了保留客户端源IP,但它会让LoadBalancer只把流量打给运行着myappPod的节点。如果某个节点上的旧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的窗口期:
- 调整滚动更新策略:把
maxUnavailable设为1,maxSurge设为2,这样更新时会先启动更多新Pod,再逐步删除旧Pod,减少节点空窗期:strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 2 - 优化就绪探针:hello-app启动速度很快,把
initialDelaySeconds调短点,比如改成2秒,让新Pod更快进入就绪状态:readinessProbe: httpGet: path: / port: 8080 initialDelaySeconds: 2 periodSeconds: 3 successThreshold: 1 - 检查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
相关产品推荐
相关产品推荐

