K8s 滚动发布时 startupProbe 和 readinessProbe 阈值怎么配,才不会出现旧 Pod 先被驱逐
该问题的正文、回答与评论。
背景\n\n我们一个 Java 服务(JDK17,Spring Boot,启动要预热,正常冷启动大约 45–60s),跑在 K8s 1.28 上,4 副本,maxUnavailable=0、maxSurge=1,走滚动发布。发布走 CI 直接 kubectl apply 滚动更新镜像。\n\n现象\n\n每次滚动更新,新 Pod 进入 ContainerCreating→Running 后,readinessProbe 还没就绪(应用还没 listen 8080),但因为 maxSurge=1,K8s 会先把新 Pod 拉起来再删一个旧 Pod——结果经常出现「旧 Pod 已经被删、新 Pod 还没 ready」的空窗,这段时间 502 比例明显抬高,监控里能看到 3–8s 的不可用毛刺。冷启动慢的服务,这个空窗更明显。\n\n已尝试的排查\n\n1. 把 maxSurge 调到 2、maxUnavailable 保持 0,空窗缓解但没根治,而且高峰期 surge 多占资源;\n2. 给 Pod 加了 startupProbe(tcpSocket 探 8080,failureThreshold=30,periodSeconds=2),但发现 startupProbe 和 readinessProbe 的阈值我配得不太确定——startup 阶段到底该用 tcpSocket 还是 httpGet /health?failureThreshold 给 30 够不够 60s 冷启动?\n3. 旧 Pod 的 preStop hook 加 sleep 5s 想让它优雅下线,但空窗还是偶尔出现。\n\n期望得到的答案形态\n\n想要一份可照抄的配置样例:针对「冷启动 45–60s 的 Java 服务」,startupProbe / readinessProbe / livenessProbe / preStop 四件套的具体参数(探针类型、failureThreshold、periodSeconds、preStop sleep 时长)以及 maxSurge/maxUnavailable 的推荐组合,并解释为什么这样配能避免旧 Pod 先被驱逐。最好能点出 startupProbe 和 readinessProbe 的职责边界,别让我再靠拍脑袋调。