You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Kubernetes负载均衡器中标记Pod离线以避免部署流量超时?

解决Kubernetes滚动更新时流量超时的问题

咱们先来拆解下你遇到的核心问题:Kubernetes在滚动更新时,旧Pod还没被负载均衡器(实际是Kubernetes Service关联的Endpoint列表)标记为离线,就进入了销毁流程,导致部分请求发到正在终止的旧Pod上超时。虽然你已经配置了就绪探针,但默认的Pod终止流程和探针逻辑没配合好,才会出现这个问题。下面给出几个针对性的解决方案:

1. 配置Pod的preStop钩子与终止宽限期

这是解决这类问题最关键的一步。Kubernetes在销毁Pod时,会先发送SIGTERM信号,然后等待terminationGracePeriodSeconds(默认30秒)后发送SIGKILL。但在这个过程中,如果没有让应用先停止接收新请求,或者给Kubernetes足够时间把Pod从Endpoint列表中移除,流量还是会打进来。

你可以给Pod添加preStop钩子,完成两个关键动作:

  • 先等待几秒,让Kubernetes完成Endpoint的更新(确保负载均衡器不再发新流量到这个Pod)
  • 通知应用优雅停止,不再接收新请求,同时处理完现有请求

示例配置:

spec:
  containers:
  - name: your-app-container
    # ... 其他容器配置
    lifecycle:
      preStop:
        exec:
          # 先等5秒给Endpoint同步时间,再调用应用的 shutdown 接口
          command: ["sh", "-c", "sleep 5; curl -X POST http://localhost:8080/shutdown"]
    terminationGracePeriodSeconds: 30 # 可根据应用处理请求的耗时调整

同时要确保你的应用收到shutdown请求后,会停止监听端口,并且让就绪探针的/ready接口返回非200状态码(比如503),这样Kubernetes会立刻把Pod从Service的Endpoint中移除,彻底切断流量。

2. 调整Deployment的滚动更新策略

默认的滚动更新策略(maxSurge: 25%maxUnavailable: 25%)允许更新过程中有部分Pod不可用,这可能导致旧Pod还没完全就绪就被替换。你可以把maxUnavailable设为0,确保只有新Pod完全就绪后,才会销毁旧Pod:

spec:
  strategy:
    rollingUpdate:
      maxSurge: 1 # 每次最多启动1个新Pod
      maxUnavailable: 0 # 更新过程中可用Pod数不低于期望副本数
    type: RollingUpdate

这个配置能保证更新期间始终有足够的可用Pod处理流量,旧Pod只有在新Pod通过就绪探针后才会被终止,从根源上避免流量打到正在销毁的Pod上。

3. 优化就绪探针的逻辑

你当前的就绪探针配置参数是没问题的,但要确保/ready接口的逻辑能正确反映Pod的流量接收状态:

  • 当Pod正常运行时返回200
  • 当Pod收到终止信号(或进入停止流程)时,立刻返回非200状态码

这样Kubernetes会在第一时间把Pod从Endpoint列表中移除,负载均衡器也就不会再发流量过来了。

为什么你的当前配置没解决问题?

你设置了1秒的periodSeconds,但默认情况下,Kubernetes在销毁Pod时,并不会立刻让就绪探针失败——除非应用主动改变/ready的返回状态。而且负载均衡器的Endpoint列表更新需要一点同步时间,如果旧Pod在同步完成前就开始终止,还是会有流量进来。加上preStop钩子和调整滚动更新策略,就能补上这个时间差。

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

火山引擎 最新活动