使用Argo CD在EKS部署K8s时如何实现Pod就绪后再终止旧Pod
你观察到的行为和Argo CD没有直接关联,Argo CD只负责把声明的Kubernetes资源配置同步到EKS集群,新旧Pod替换的滚动更新逻辑是Kubernetes原生工作负载控制器的默认机制:默认配置下只要容器进入Running状态(即主进程被kubelet拉起),控制器就会推进滚动更新流程,不会校验业务是否真的完成初始化、可以正常承接流量。
所有实现方案的核心逻辑,都是给Kubernetes控制器传递明确的「新Pod业务已正常就绪」信号,控制器只有收到信号后才会继续推进滚动更新、终止旧版本Pod,具体可落地的方式如下:
这是最原生、改造成本最低的方案,也是Kubernetes滚动更新逻辑依赖的核心判断依据。
注意:Pod进入Running状态仅代表容器进程已启动,完全不等价于业务可正常处理请求。只有当Pod内所有容器的就绪探针连续通过配置的校验次数后,Kubernetes才会将Pod标记为就绪状态:
- 就绪的Pod才会被加入对应Service的后端端点列表,正式承接流量
- 滚动更新流程中,只有新就绪的Pod数量达到滚动策略要求的副本数后,控制器才会开始终止旧版本Pod
普通HTTP服务的探针配置示例:
containers: - name: business-app image: your-app-image:v2.1.0 ports: - containerPort: 8080 readinessProbe: httpGet: # 业务自行实现的就绪检查接口:确认缓存加载完成、数据库/消息队列等下游依赖连接正常、初始化逻辑全部跑完才返回200状态码 path: /internal/health/ready port: 8080 initialDelaySeconds: 15 # 容器启动后等待多久发起第一次检查,根据业务实际启动耗时调整 periodSeconds: 5 # 检查间隔 failureThreshold: 3 # 连续3次检查失败判定为未就绪 successThreshold: 1 # 连续1次检查通过即判定为就绪
如果业务没有HTTP接口,可以换用tcpSocket探测业务监听端口是否正常,或者用exec字段执行自定义校验脚本判断内部状态。
这里要避开一个常见坑:不要把就绪探针和存活探针(livenessProbe)搞混,存活探针检查失败会直接重启容器,就绪探针检查失败只会临时把Pod移出流量后端、暂停滚动更新,不会重启容器,两者的检查逻辑和用途完全不同,不要配成一样的。
配合就绪探针使用,把滚动更新的不可用副本阈值设为0,强制控制器必须等新Pod完全就绪后再删除旧Pod,避免更新过程中提前终止旧Pod导致业务容量缩水:
spec: strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 # 更新过程中不允许提前终止任何正常运行的旧Pod,直到对应数量的新Pod就绪 maxSurge: 1 # 更新时最多可以比期望副本数多启动1个新Pod,集群资源充足的话也可以按比例设为25%等值
这个配置加上正确的就绪探针,就可以完全实现「新Pod完全就绪承接流量→再终止旧Pod」的逻辑,能满足90%以上普通业务的发布需求。
如果你的业务启动流程很长(比如加载大模型、预热全量本地缓存、同步全量基础数据),通用的HTTP/TCP探针覆盖不了所有就绪条件,可以用exec类型的就绪探针执行自定义校验脚本:比如检查本地缓存文件是否生成、数据库连接池是否初始化完成、预热任务接口是否返回成功,脚本退出码为0时判定为就绪,非0则继续等待,不要提前推进发布流程。
如果需要更细粒度的发布控制(比如新Pod就绪后还要观察几分钟业务指标、确认错误率/延迟符合预期再下线旧Pod,或者要做金丝雀灰度、蓝绿发布),可以部署Argo Rollouts组件替换原生Deployment控制器,它和Argo CD原生兼容,支持自定义更严格的就绪门槛:比如配置新Pod就绪后维持5分钟观察期,期间接口错误率低于0.1%再自动下线旧版本,出现异常自动暂停发布、回滚,适合核心业务的发布场景。
注意:不要为了省事把就绪探针配置为永远返回成功,比如直接探测站点根路径、写个永远返回0的空校验脚本,这种配置等价于没有就绪检查,会直接回到默认的「Pod进入Running就终止旧Pod」的逻辑,完全失去发布保护作用。
内容的提问来源于stack exchange,提问作者Junseok Lee

