慢启动不等于进程已死。readiness 与 liveness 分别决定普通 Service 流量是否应该进入这个 Pod,以及终止容器是否有助于恢复,两项决策相互独立。readiness 失败不会暂停 liveness;需要配置 startup 探针,才能在启动阶段抑制另外两种检查。只把接口分成两个名字,不能自动解决这个时序问题。
本文关注健康信号的选择与接线错误的诊断。关键是每次检查实际测到了什么,而不是 URL 名称。共用一个接口可以合理;共用会因下游抖动而失败的检查,并据此触发不必要的重启,却可能扩大故障。设计时应验证具体故障模式与预期恢复动作,不能假定有两个接口就天然安全,也不能把“还没准备好”直接解释成“需要杀死重来”。
Readiness 把流量挡在门外
连续 readiness 失败达到阈值,会让 Pod 失去普通 Service 路由资格,但 Pod 仍在运行,好让进程完成热身或自行恢复。端点条件与数据路径在失败、恢复两个方向都异步收敛;已有连接和 Pod 直连需要分别考虑。就绪失败不直接触发探针重启,却可能移除全部服务容量,不能无条件称为安全:缓存可以慢慢热,迁移可以跑完,下游依赖可以回来,全程不丢 Pod 的内存状态,也不付重启的代价。
就绪接口要围绕真正的可服务性设计,而不是进程存在性。检查那些决定这个 Pod 此刻能否正确回答的东西:结构迁移是否应用、必需的缓存是否装满、关键下游是否可达。只检查"服务能响应"的就绪探针,会把注定失败每个请求的 Pod 放进流量——比不检查还糟,因为负载均衡器是信任它的。但也别把所有依赖都塞进去:非关键的推荐服务挂了,就绪失败等于为一件装饰品扔掉主干流量。
Liveness 守护进程本身
liveness 探针连续失败达到阈值会终止容器,是否重启遵循重启策略,这是结束僵死状态的最后一招。它要处理的该是"进程卡死"这类问题,而不是容器只是暂时还没就绪。合格的目标很窄:死锁——此后任何请求都不会再成功;协程或线程泄漏到只有新进程能清;内存状态损坏到任何重试都救不回来。每种情况的共同点是不可逆:不重启就不可能恢复,而不只是恢复得慢。
这个门槛意味着很多服务应该只配极简的存活探针,甚至不配。把存活检查打到外部数据库上,每次数据库抖动都会变成全集群的重启风暴,还顺手毁掉本可以加速恢复的热缓存。优先用廉价的本地检查——主循环定时刷新的看门狗时间戳——不问进程之外的任何东西,只回答"这个进程是不是卡死了"。崩溃之后是否重启,取决于容器重启策略;存活探针则能在普通退出之前识别选定的不可恢复本地故障。
给探针留足余量
把 initialDelaySeconds 设到足够大,别把冷启动误判成崩溃;timeout 也要配合真实工作量。启动保护需要独立配置;readiness 本身不能阻止 liveness 触发终止。启动慢的容器最好再加一个启动探针:它成功之前,存活与就绪探针都保持关闭,于是需要预热大缓存的版本升级能拿到几分钟而不是几秒,稳态的存活检查强度一点不减。
失败阈值按观测到的行为调,别在服务之间抄整数。检查周期乘以失败次数只是规划估计,不是真实反应时间保证。探针所处周期、超时、调度、终止宽限与重启退避都会改变时间线;就绪端点变化与已有连接也并非在同一瞬间全部完成。量出冷启动的分位耗时、依赖恢复时间、最坏的回收停顿,再定每个数字:比告警快,比噪声慢。
坏掉的样子
标志性故障是依赖故障期的重启循环:数据库变慢,本来就绪探针就够了,但存活探针共用同一个失败的接口,全集群一波波重启。每次重启清空热缓存,下一波恢复更慢,系统无限振荡。诊断看重启时间戳与依赖事故是否对齐;修法是调整决策语义,让重启信号保持本地且确实有助于恢复。就绪检查关键依赖可能有用,但共享下游故障时撤掉全部副本,可能比提供降级响应更糟。
镜像故障是僵尸 Pod:服务能响应所以存活探针通过,但请求全卡在死锁的工作池后面。流量源源不断送进一个什么都不回答的 Pod。短超时申请工作槽无法区分死锁与健康但饱和的工作池,反而可能在过载时触发重启。应寻找关键工作机制停止推进的证据,容纳预期停顿与正常空闲,并验证重启确实能改善这类故障。暂时过载需要另行处理,不能用一次抢不到槽位就证明进程已无法自行恢复。
快速验证
检查探针接线与最近的杀戮记录:
kubectl get pod web-0 -o jsonpath='{.spec.containers[*].livenessProbe}{"\n"}{.spec.containers[*].readinessProbe}{"\n"}'
kubectl get events --field-selector reason=Unhealthy --sort-by=.lastTimestamp | tail -n 10
kubectl describe pod web-0 | grep -A3 -i 'liveness\|readiness'
这些未改动的诊断本轮没有重新执行。若语义适合两项决策,共用 URL 并不天然错误。Unhealthy 事件包含探针失败,不能证明发生了杀进程;需要关联具体 Pod、容器重启计数和终止原因。带期限的检查必须区分死锁、暂时负载及没有业务请求的正常空闲,不能用一次失败代替完整故障判断。
延伸阅读
来源
- Kubernetes 探针,liveness 与 readiness 官方文档,已核验 2026-10-15。
- 配置存活与就绪探针,探针配置任务指南,已核验 2026-10-15。