Kubernetes 健康检查端点为什么以 z 结尾:从 healthz 到 livez 与 readyz

1次阅读
没有评论

共计 2501 个字符,预计需要花费 7 分钟才能阅读完成。

第一次在 Kubernetes 的配置里看到 /healthz 这个路径的时候,我盯着结尾那个 z 愣了几秒。它不是拼写错误吗?健康检查明明是 health,怎么后面莫名其妙多了一个 z?后来又陆续遇到 /livez/readyz,才意识到这不是偶然,而是一整套命名惯例。带着好奇心去翻了一些资料,发现这个小小的字母背后,其实牵扯出一段从 Google 内部流传到整个云原生社区的工程文化。

这个 z 后缀并非什么技术缩写,也没有隐藏的语义含义,它纯粹是一种约定俗成的命名方式,源自 Google 内部工程实践中的 z-pages 命名惯例。理解了它的来龙去脉,你不仅能记住这几个端点,还能顺带看懂为什么整个 [[Kubernetes]] 生态里到处都是以 z 结尾的诊断路径。

z-pages 惯例的起源

要弄清楚这个 z 是从哪来的,得把时间拨回到 Google 内部的服务治理实践。Google 的服务长期使用一套内建的诊断端点,工程师们习惯在这些端点的名字末尾统一加上 z,于是就有了 /varz(暴露变量和指标)、/statusz(展示服务状态)、/rpcz(观察 RPC 调用情况)等一系列端点。这些以 z 结尾的诊断页面被统称为 z-pages,是 Google 内部观测服务运行状况的标准手段。

有意思的是这套惯例的传播路径。Kubernetes 的早期开发者中有相当一部分是前 Google 工程师,他们把自己熟悉的这套 z-pages 风格自然而然地带进了 Kubernetes 社区。不只是 Kubernetes,[[Prometheus]] 和 OpenCensus 这些同样诞生于 Google 血统的工具,它们的原作者也沿用了同样的命名方式。所以当你在云原生世界里反复看到 z 结尾的端点时,其实是在看同一批人把同一种工程审美复制到了不同的项目里。这也是为什么这个惯例能在社区里如此顽固地存活下来,它背后是一群有共同背景的人的集体习惯。

为什么要加个 z 而不是直接叫 health

如果 z 没有任何技术含义,那为什么不干脆用 /health 或者 /status 这种一目了然的名字呢?这个问题其实触及了命名设计里一个很现实的考量:减少与应用自身业务端点的命名冲突。

设想一下这样的场景。你的应用本身可能已经有了 /status/health 这样的路由,用来给前端展示业务状态、或者对外提供某种查询接口。这时候如果 Kubernetes 或者底层基础设施也想用同样的名字来做健康探测,两者就会撞车,产生歧义,甚至可能因为业务逻辑和探针逻辑混在一起而引发难以排查的问题。加上一个不常见的 z 后缀之后,/healthz/livez/readyz 这些端点就明显区别于普通的业务接口,任何人一看到这个奇怪的 z,几乎立刻就能意识到这是基础设施专用的探测端点,而不是给终端用户消费的业务 API。

从这个角度看,z 有点像一个视觉上的标签,它用一种略显笨拙但足够有效的方式,在命名空间里划出了一块专属区域。这种设计并不追求优雅,而是追求辨识度和安全隔离,这恰恰是大规模工程实践里非常务实的一种取舍。

healthz livez 与 readyz 的区别

Kubernetes 的 API 服务器本身就提供了 /healthz/livez/readyz 这三个端点,但它们的地位并不平等。事实上 /healthz 从 v1.16 版本起就已经被官方弃用了,现在更推荐使用语义更清晰的 /livez/readyz

弃用 /healthz 的原因也很好理解。它的语义太笼统了,一个笼统的健康检查,到底是在问服务还活着吗,还是在问服务准备好接收流量了吗?这两个问题在运维层面有着截然不同的处理逻辑,混在一个端点里只会让判断变得模糊。于是社区把这个含混的概念拆成了两个各司其职的端点,让每一个都只回答一个明确的问题。

下面这张表把三者的定位和失败时的处理方式放在一起对比,会看得更清楚:

端点用途失败时的处理
/healthz早期笼统的健康检查,已弃用语义不清,不建议新项目使用
/livez判断容器是否需要重启,对应存活探针返回失败码说明进程可能陷入死锁等不可恢复状态,Kubernetes 会重启容器
/readyz判断容器是否能接收流量,对应就绪探针返回失败码说明服务仍在初始化或暂时不可用,流量会被路由走

存活探针(Liveness Probe)关心的是这个进程是不是已经彻底卡死了。如果 /livez 持续返回失败,Kubernetes 会认为容器进入了某种无法自愈的状态,比如死锁,唯一的解决办法就是把它重启掉。就绪探针(Readiness Probe)关心的则是另一件事:这个服务此刻是否已经准备好对外提供服务了。如果 /readyz 返回失败,Kubernetes 不会去重启容器,而是暂时把流量从这个 Pod 上摘走,等它就绪之后再重新纳入负载均衡。一个负责生死,一个负责流量调度,两者的边界一旦分清楚,探针配置就不容易用反。

在实际使用中,把存活探针和就绪探针分开配置几乎是必须的。一个常见的坑是把耗时的依赖检查(比如数据库连接、缓存预热)放进存活探针里,结果服务在启动阶段还没准备好就被判定为死亡,被反复重启,陷入永远起不来的循环。正确的做法是让存活探针保持轻量,只检查进程本身是否响应,而把那些依赖是否就绪的判断交给就绪探针去做。

最后

绕了一大圈回到最初那个字母 z,答案其实很朴素:它就是一个历史遗留的品牌标记,用来标识这是 Google 风格的诊断和探测端点,跟具体的技术含义没有任何关系。你自己写服务的时候完全可以不加这个 z,健康检查端点叫什么名字并不会影响它的功能。但如果你遵循这个惯例,那些熟悉 [[Kubernetes]] 生态的人一眼就能看懂你的意图,这种无需解释的默契,本身就是命名约定存在的价值。

这件小事让我重新体会到一点,很多技术世界里看似随意的细节,往往都能追溯到某个具体的团队、某段具体的历史。z-pages 从 Google 内部的一个习惯,一路走到今天几乎所有云原生工程师都会打交道的端点命名,靠的不是什么强制规范,而是一群人把自己的工程审美带到哪里,就在哪里留下痕迹。下次再遇到某个让你摸不着头脑的命名,不妨多问一句它从哪来,答案里藏着的常常不只是技术,还有人。

正文完
 0
评论(没有评论)