容器启动顺序的坑:把依赖检查放进 liveness 是最贵的一种误用

举报
yd_274788088 发表于 2026/11/07 00:59:59 2026/11/07
【摘要】 liveness 与 readiness 的职责划分、startupProbe 兜住慢启动,以及健康端点里该做与不该做的事。

一、问题的形态

本地开发一切正常,把同一份代码部署到服务器上,第一次请求却报「表不存在」或「连接超时」。这类问题几乎都不是代码写错了,而是「应用认为已经就绪」和「依赖项实际就绪」之间存在时间差。

典型场景有三种:

  • 容器编排里应用容器和数据库容器同时启动,应用只等了几秒就弃疗退出,然后被重启,形成循环;
  • 宿主机重启后数据库自己还在做崩溃恢复,应用这边已经开始对外提供服务;
  • 多副本滚动更新时,新副本先接到流量,但连接池尚未建立,前几个请求全部失败。

这几种情况的共同点是:健康检查只问了「进程还在吗」,没有问「依赖能通吗」。

二、两层探针要分开

Kubernetes 里 liveness 和 readiness 是最容易被混用的两个探针。它们回答的是两个不同的问题:

  • liveness:进程是否还活着、是否死锁。失败时 kubelet 会重启容器。它绝不能去检查数据库——数据库抖动一下,全部应用容器被连环重启,故障反而放大。
  • readiness:现在能不能接流量。失败时只是把该副本从 Service 的 Endpoints 里摘掉,不会重启。数据库没连上、缓存不可用、迁移未完成,都应该在这里体现。

结论很直接:依赖检查放 readiness,liveness 只探自己。 把数据库检查塞进 liveness 是这套机制里最常见、代价最大的一种误用。

三、启动顺序不该靠 sleep 猜

「先 sleep 十秒再启动」是最朴素也最脆的做法:机器慢一点就失败,机器快一点就白等。更稳的做法是把「依赖是否可用」变成应用自己能回答的问题。

# readiness 探针指向一个真实做依赖检查的端点
readinessProbe:
  httpGet:
    path: /healthz/ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5
  failureThreshold: 3
livenessProbe:
  httpGet:
    path: /healthz/live
    port: 8080
  periodSeconds: 10
  failureThreshold: 5
startupProbe:
  httpGet:
    path: /healthz/live
    port: 8080
  failureThreshold: 30
  periodSeconds: 2

startupProbe 是很多人漏掉的第三个探针:应用启动慢时它先兜住,等启动完成才把 liveness 交出去,避免「启动慢被当成挂掉」。三个探针各管一段,比把 initialDelaySeconds 调到 60 要精确得多。

四、健康端点里该做什么、不该做什么

一个可用的 readiness 端点至少应该检查:数据库能否建连并执行一条最轻的查询(例如 SELECT 1)、必须的缓存是否可达、本地初始化是否完成。三点都过才返回 200,任何一条不过返回 503 并带上失败原因。

不该做的也很明确:不要在健康端点里跑聚合查询或大表扫描。健康检查是每几秒一次的调用,一旦被监控系统放大成每秒几十次,慢查询会直接把数据库压垮——这属于典型的「监控把系统监控死」。

另一个细节:健康端点本身要带超时。依赖不通时若一直阻塞等待,探针会等到自己的超时,随后被判失败,日志里却只有一行「probe failed」,看不出到底是数据库还是缓存。给每个依赖检查单独设一个短超时(如 500ms),并在响应体里写明失败项,排障成本能降一个量级。

五、验证方式

部署完之后要做一次人为破坏测试,而不是只看 Pod 状态是 Running。做法是:把数据库临时停掉,观察副本是否从 Endpoints 中摘除、Service 是否仍有健康副本可服务;恢复数据库后再看副本是否自动回到 Endpoints。整个过程不应出现容器重启计数上涨。

如果这一步看到重启计数上涨,说明依赖检查被误放进了 liveness,回到第二节改配置即可。这个测试花五分钟,能提前发现绝大多数「上生产才发现」的循环重启。

六、小结

启动顺序问题本质上是一个「谁来判断就绪」的责任划分问题。把判断权交给应用自己的 readiness 端点、把依赖检查从 liveness 里剥离、用 startupProbe 兜住慢启动,三件事做完,sleep 就可以从启动脚本里删掉了。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。