Skip to main content

Command Palette

Search for a command to run...

Kubernetes 存活检测的危险性

Updated
1 min read

原文:LIVENESS PROBES ARE DANGEROUS

Kubernetes 的 livenessProbe 是有一定危险性的。建议在用例清晰,并且理解足够深刻的情况下才使用这个功能。本文会涉及到存活检测以及就绪检测,并做出一些应该或者不该的建议。

我的同事 Sandor 最近说了一下他看到的问题,其中包括了错误的存活检测和就绪检测的内容:

  • 没有就绪检测

  • 错误的就绪检测

  • 混淆了就绪检测和存活检测

  • 不优雅的退出

  • 不够优雅的优雅关闭,最好使用生命周期 Hook

  • Fork 模式

错误的存活检测过程可能加重负载问题(雪崩式故障加上延长容器应用启动时间的风险),会引发其他负面问题,例如破坏依赖(参见我另一篇关于 K3s 和 ACME 速率限制的文章)。存活检测和外部数据健康检查的依赖是最差的情况:数据库的一点小问题会重启你的所有应用

在喊出“不要使用存活检测”口号之前,还是先看看存活检测和就绪检测的用途。

注意下文很多来自 Zalando 的内部文档。

就绪和存活检测

Kubernetes 提供了两个很棒的功能,分别是就绪检测和存活检测。这两个功能会周期性的执行一个动作(比如说发出 HTTP 请求,打开一个 TCP 连接或者在容器中运行一个命令),从而确认你的应用正在如常运行。

Kubernetes 使用就绪检测来探测容器是否准备好开始接收流量。如果 Pod 中所有的容器都准备就绪,这个 Pod 就被当做是就绪状态。这种信号的一个用途就是来控制 Kubernetes 服务的后端 Pod(尤其是 Ingress)。

Kubernetes 使用存活检测来确定是否需要重启容器。例如存活检测能够检查到运行中应用的死锁,这种应用正在运行,但是不会有任何进展。重启这种容器能够在有 Bug 的情况下提高应用的可用性,然而也可能会引起级联故障(见后)。

如果一个应用的存活或者就绪检测失败了,在尝试对其进行更新时,滚动更新的过程可能会挂死——K8s 会想要等待你的 Pod 进入就绪状态。

举个栗子

就绪检测会使用 HTTP 协议,检查 /health 路径(缺省行为:10 秒钟间隔、1 秒钟超时、成功阈值 1,失败阈值:3):

...
podTemplate:
  spec:
    containers:
    - name: my-container
      # ...
      readinessProbe:
        httpGet:
          path: /health
          port: 8080
...

建议

  • 对于使用 HTTP 端点提供服务(尤其是 REST 服务)的微服务来说,严重建议定义一个就绪检测,用来检测你的应用(Pod)是否准备好接收请求。

  • 确认你的就绪检测设置覆盖了 Web 服务器的真实端口。

    • 如果你的就绪检测中使用了管理员端口(比如说 9090),如果主要 HTTP 端口(例如 8080)准备就绪,务必要确认该端点仅返回 OK。

    • 为就绪检测使用专属端口可能在主端口线程池的拥塞时报告错误的状态(主服务池已满,然而健康检测依然能够通过)。

  • 确保就绪检测包含了数据库的初始化和迁移过程。

    • 最简单的方式就是仅在初始化完成之后才打开 HTTP 端口,也就是说,不设置健康状态,只是不启动 Web 服务器,直到数据库迁移完成。
  • 使用 http Get 访问知名的健康检查端点(例如 /health)来完成就绪检测。

  • 理解缺省行为(缺省行为:10 秒钟间隔、1 秒钟超时、成功阈值 1,失败阈值 3):

    • 在大概 30 秒(3 次失败的检测)后,这个 Pod 会成为未就绪状态。
  • 如果你的技术栈(例如 Java/Spring)允许的话,可以使用不同的管理端口,把监控、检测端口和业务流量分开。

    • 注意前面提到的线程问题。
  • 可以使用就绪检测来对应用进行缓存和预热,在容器完成预热之前,返回 503.

反对

  • 不要依赖外部因素,以免发生雪崩

    • 例如有个有状态的 REST 服务,其中包含了 10 个依赖一个 Postgres 数据库的 Pod:如果数据库和网络不稳定,会导致 10 个 Pod 关闭,很显然这种反应会让结果变得更差。

    • Spring Data 的缺省行为是检查数据库连接。

    • 这里所说的外部因素,还包含本集群中的其它 Pod,也就是说你的检测过程不应该依赖其它 Pod 的状态,以防止雪崩:

      • 对于具有分布式状态的应用(例如跨 Pod 的内存缓存),可能会有所不同。
  • 在清楚为什么要使用存活检测,了解其后果之前,不用使用存活检测

    • 存活检测能够帮助你恢复“卡死”的容器,但是如果你的应用够成熟,是不应该出现这种情况的——更好的对策是有目的地崩溃,以恢复正常状态。

    • 失败的存活检测会导致容器重启,可能会让性能问题更加恶化:容器重启是有停机时间的(损失时间至少是你的应用的启动时间,例如 30 秒),这样就会造成更多错误,让其它容器承受更多压力,可能引起更多容器的崩溃。

  • 如果使用存活检测,不要让存活检测和就绪检测使用同样的条件

    • 可以让存活检测使用同样的健康检测方法,但是设置更高的 failureThreshold(例如 3 次失败之后设置为未就绪,10 次失败后才让存活检测失败)
  • 不要使用 exec 检测:这是一个已知问题,会导致僵尸进程。

总结

  • 在 Web App 中使用就绪检测来确定该 Pod 可以接受流量。

  • 仅在的确需要时候使用存活检测。

  • 不恰当的检测方法可能会损失可用性甚至有引发雪崩的危险。

More from this blog

龙虾恐慌:AIOps 又要改名了?

ChatGPT 开始,把 AI 拉近到普罗大众的面前,让无数人感受到 AI 的亲民魅力。而龙虾,则把大模型驱动的自动化能力,突然间变得水灵灵、活泼泼地走进千家万户。它不只是“风口上的猪”,而是风口本身。热度高到让 Mac mini 一度断货,不知道这在不在库克的预料之内。 每代人都有每代人的鸡蛋,春节期间,我就领了我的鸡蛋。翻出古老的 MacBook Air M1,充值各种大模型。当然了,这个工具

Mar 9, 20261 min read

再见 2025

我猜不少人以为这个号废了吧?并没有,只是今年变化有点大,一直有种抄起键盘,无从说起的感觉,所以一直偷懒到今天,2025 的最后一天。 今年是我的第四个本命年,去年末一期播客里,大内说本命年不是灾年,是变化年,有危也有机。可是讲真啊,只看到危,没看到机。 各种因缘际会,从鹅厂跳槽到前东家,已经接近四年,第一个合同期已经进入尾声。除了前两年还在云原生领域嗷嗷叫,后两年基本都是些鸡零狗碎的东西了,用老东家的术语说是——偏离主航道,可谓是前景暗淡了。 一旦确定要滚蛋,反倒心思轻松起来,每天骑着我的小红车...

Jan 5, 20261 min read

辅助编程?dora 说:我知道你很急可是请你别急

从 OpenGPT 把大模型的火烧旺了之后,这三年来,相信很多组织或摩拳擦掌、或躬身入局,希望借助聪明能干的大模型,或想偿还技术宅,或想降本增效,或想弯道超车。一时间,沉寂许久的 AIxx 又活过来了,LLM Ops、Vibe Coding、中医大模型、GPT 算命等等,全都老树发新芽,焕发了勃勃生机。那么视角拉回从业者最关注的饭碗相关的领域之一——AI 辅助开发,产生了什么触动,应该如何拥抱呢? DORA 的年度报告中给出了很有意思的结论——强者恒强。 执行摘要部分总结了几个有趣的点: 问题...

Oct 6, 20251 min read

[译]dora:ai 辅助软件开发状态报告

执行摘要 在 2025 年,科技领导者面临的核心问题已不再是“是否要采用 AI”,而是“如何实现其价值”。 DORA 的研究基于超过 100 小时的定性访谈和来自全球近 5,000 名技术专业人士的问卷调查。研究揭示了一个关键事实:AI 在软件开发中的主要角色是“放大器”。它会放大高效能组织的优势,也会凸显组织的缺陷。 关键结论:AI 是放大器 AI 投资的最大回报并非来自工具本身,而是来自组织底层系统的战略性建设: 高质量的内部平台 清晰的工作流 团队的协同能力 缺少这些基础,AI ...

Oct 2, 202514 min read

僭越了,有人在用 Rust 写 Kubernetes

一个新语言问世,最爱做的事情之一,就是重写存量软件了。 云原生喝酒 SIG 重点扶持项目——rk8s(https://github.com/rk8s-dev/rk8s) 也可以归在这个范畴里,只不过这个项目重写的东西比较大,是 Kubernetes。 从 2025 年 1 月第一个 Commit 开始,到现在有了 200 多次 Commit,十几万行代码。当然距离 Kubernetes 的几百万行代码还差得远——老马就是喜欢整这种大无畏项目。 另外该项目也是国内第一个脱离 Cargo 转向使用 ...

Sep 27, 20253 min read

【伪】架构师

342 posts