
在 Kubernetes 的实际运维中,你是否遇到过容器进程仍在运行,但应用已经无法正常提供服务的情况?此时,Kubernetes 的存活探测(Liveness Probe)机制就显得至关重要。它能准确判断容器中的应用是否仍然存活并正常运行,通过定义合理的探测规则,可以显著提升 Pod 的稳定性、可用性和自愈能力。
本文将以解决问题为导向,系统讲解 K8s 中存活探测的原理、配置方法与避坑指南,并结合大量示例,帮助你在生产环境中正确实施 Liveness Probe。
本文将涵盖以下内容:
- 什么是 Kubernetes 存活探测(Liveness Probe)
- Kubernetes 中还有哪些探测机制
- 如何定义 Kubernetes 存活探测
- Liveness Probe 的常见配置示例
- 如何验证存活探测是否生效
- 存活探测失败的排查思路
- Liveness Probe 的最佳实践
什么是 Kubernetes 存活探测(Liveness Probe)?
Kubernetes 存活探测是一种用于判断容器是否仍在正常运行的机制。它的核心作用是“监工”,一旦发现应用“偷懒”或“假死”,便会采取行动。
当存活探测连续失败时,Kubernetes 会认定该容器已处于不可恢复的异常状态,并自动重启该容器,尝试恢复服务,而非等待人工干预。
Liveness Probe 通常用于检测那些进程未退出但应用已“罢工”的场景:
- 应用进入死锁状态,无法继续处理请求。
- 进程假死(如内存泄漏导致线程池耗尽),不再响应任何外部调用。
- 内部逻辑出现严重异常,但进程本身没有退出,无法自愈。
其探测方式灵活多样,可以通过以下三种途径实现:
- 执行容器内的一条特定命令。
- 向容器内的某个 HTTP 接口发送请求。
- 尝试连接容器的某个 TCP 端口。
简单来说,它的存在确保了当应用内部“卡住”时,Kubernetes 能够主动介入并重启容器,从而将单点故障的影响降到最低,提升整个系统的可靠性。
存活探测在 Kubernetes 中的作用
在 Kubernetes 集群中,具体负责执行存活探测的是运行在每个节点上的 kubelet 组件。它会根据你定义的探测规则,定期对容器进行“健康检查”,并根据结果做出决策:
- 如果探测成功:万事大吉,kubelet 不会执行任何操作,也不会产生额外的事件日志。
- 如果探测失败:kubelet 会记录一个警告事件,并根据 Pod 中定义的
restartPolicy(如 Always)策略,杀死并重启这个不健康的容器。
什么时候应该使用存活探测?
一个核心判断原则是:当 Pod 看起来“还在运行”(进程未退出),但应用实际上已经无法正常完成其本职工作时,就非常适合启用 Liveness Probe。
例如:
- 一个 Web 应用发生死锁,HTTP 服务进程还在,但所有请求都挂起无响应。
- 一个后端服务的监听端口仍然开放,但其核心业务接口返回 500 错误或完全超时。
- 应用内部某个关键线程阻塞,导致无法继续处理队列中的任务。
在这些情况下,容器不会自动退出,但已经丧失了服务能力。存活探测就像一位哨兵,能够及时发现并触发恢复机制。
什么时候不需要存活探测?
并非所有应用都需要它。如果你的应用在出现致命错误时,会主动退出进程,那么 kubelet 会根据 Pod 的 restartPolicy 自动重启容器,此时配置 Liveness Probe 的必要性就降低了。
典型的例子是 NGINX:
- 启动速度极快。
- 遇到无法加载配置等致命错误时,主进程会直接退出。
- Kubernetes 能够很自然地捕获到进程退出信号并重启它。
存活探测的三种类型
Kubernetes 提供了三种存活探测方式,以适应不同技术栈的应用场景:
1️⃣ HTTP GET 探测
向容器内指定的 HTTP(S) 接口(如 /health)发送 GET 请求。
- 成功:返回状态码为 2xx (成功) 或 3xx (重定向)。
- 失败:返回其他状态码(如4xx, 5xx)或请求超时/无法连接。
- 适用:绝大多数 Web 服务、RESTful API。
2️⃣ TCP Socket 探测
尝试与容器指定的 TCP 端口建立连接。
- 成功:端口可达,连接能够建立。
- 失败:连接被拒绝或超时。
- 适用:数据库(MySQL, Redis)、消息队列(RabbitMQ)、或其他非 HTTP 协议的中间件服务。
3️⃣ Exec(命令)探测
在容器内部执行你自定义的一条 Shell 命令。
- 成功:命令执行成功,返回码为 0。
- 失败:命令执行失败,返回码非 0。
- 适用:需要复杂自定义检测逻辑的场景,例如检查某个特定文件是否存在、内部状态是否正常等。
Kubernetes 中还有哪些探测机制?
除了存活探测,Kubernetes 还提供了另外两种探测机制,三者共同构成了应用生命周期管理的“铁三角”:
- Liveness Probe(存活探测):判断容器是否“活着”(进程健康),不健康则重启。
- Readiness Probe(就绪探测):判断应用是否已准备好接收流量。
- Startup Probe(启动探测):判断应用是否已完成启动。
本文重点讨论 Liveness Probe,但理解另外两者的区别至关重要。
Readiness Probe(就绪探测)
它的目标是流量控制,而非容器生命周期管理。
- 探测失败:Pod 会被从关联的 Service 的 Endpoints 列表中移除,负载均衡器(如 kube-proxy 或 Ingress Controller)将不再把新流量路由到该 Pod。
- 探测成功:Pod 被重新加入 Endpoints,开始接收请求。
- 关键区别:Readiness Probe 失败不会重启容器。
- 适用场景:
- 应用启动后需要连接外部数据库或加载大量配置,在完成前不能服务。
- 服务暂时过载,需要主动摘流以进行自我保护。
Startup Probe(启动探测)
专门为启动慢的应用设计,解决 Liveness Probe 误杀“慢热型”服务的问题。
- 一旦配置了 Startup Probe,在它首次成功之前,Liveness 和 Readiness 探测都会被禁用。
- 这给了应用充足的启动时间,避免了因启动时间过长而被 Liveness Probe 误判为异常并重启的死循环。
- 非常适合:Java 应用(Spring Boot)、大型单体应用等启动时需要初始化大量资源的服务。
Kubernetes 探测是如何工作的?
所有的探测动作都由节点上的 kubelet 执行。你的应用需要以某种方式“暴露”一个可供探测的端点,对应 kubelet 的几种处理方式:
- ExecAction:在容器内执行命令。
- TCPSocketAction:检测 TCP 端口连通性。
- HTTPGetAction:发起 HTTP 请求进行检测。
- gRPC 探测(Kubernetes v1.24+ 后稳定支持):用于 gRPC 服务。
每次探测会得到一个明确的结果:
- Success(成功)
- Failure(失败)
- Unknown(未知,通常意味着探测本身未能完成,按失败处理)
Liveness Probe 与 Readiness Probe 的核心区别
| 探测类型 |
失败后的核心行为 |
| Liveness |
重启容器,试图恢复应用本身。 |
| Readiness |
停止向该 Pod 发送流量,但不重启容器,等待应用自行恢复。 |
一个经典的实践是结合使用两者:
- Readiness Probe 负责“流量闸门”,确保只有健康的 Pod 才对外服务。
- Liveness Probe 负责“进程卫兵”,对无法自愈的 Pod 进行重启。
如何定义 Kubernetes 存活探测
存活探测在 Pod 或 Deployment 等资源的 YAML 定义中,通过 livenessProbe 字段进行配置。
示例:HTTP GET 探测
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: example-container
image: myapp:latest
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
参数解析:
initialDelaySeconds: 容器启动后,等待 3 秒才开始第一次探测。这是为了避免在应用还在初始化时就进行探测。
periodSeconds: 之后每隔 5 秒执行一次存活探测。
示例:Exec(命令)探测
livenessProbe:
exec:
command: ["cat", "/tmp/healthy"]
initialDelaySeconds: 5
periodSeconds: 10
这个例子中,kubelet 会每10秒尝试执行一次 cat /tmp/healthy 命令。如果文件存在且命令成功执行(返回码0),则探测成功;否则失败。
常见 Liveness Probe 配置参数详解
除了上面提到的,还有几个关键参数控制着探测的敏感度和鲁棒性:
timeoutSeconds:单次探测的超时时间(默认1秒)。如果探测超过此时间未返回,则判定为失败。
successThreshold:从失败状态转为成功状态所需的最小连续成功次数(默认1)。
failureThreshold:从成功状态转为失败状态所需的最小连续失败次数(默认3)。连续失败这么多次后,kubelet 才会认为容器不健康。
配置前,务必充分评估应用的启动时间、响应特性和业务峰值,避免因参数不合理导致频繁重启或响应迟钝。
如何验证存活探测是否生效?
配置好后,可以通过以下几种方式验证其工作状态:
1、查看 Pod 的详细事件,这里会记录探测失败和重启的历史。
kubectl describe pod <pod-name>
留意输出中 Events: 部分是否有 Liveness probe failed 和 Killing container 的记录。
2、查看容器日志,有时应用日志会记录健康检查的访问。
kubectl logs <pod-name>
3、观察 Pod 状态,如果频繁重启,RESTARTS 计数会不断增长。
kubectl get pods
4、手动模拟探测,进入Pod网络命名空间或通过端口转发,手动访问探测接口,验证其可访问性和返回内容。
curl http://<pod-ip>:<port>/health
存活探测失败的常见原因与排查思路
当发现 Pod 因 Liveness Probe 失败而频繁重启时,可以按以下思路进行排查:
1️⃣ 应用启动时间过长
现象:容器刚启动不久就被重启。
解决方案:
- 适当增加
initialDelaySeconds,给应用留足启动时间。
- 更优解:为慢启动应用配置
startupProbe,替代初始延迟。
2️⃣ 探测路径或端口配置错误
现象:手动访问健康接口正常,但探测日志显示失败。
解决方案:
- 确认
httpGet.path 或 exec.command 在容器内确实存在且可访问。
- 确认
port 与容器内应用实际监听的端口号完全一致。
- 检查应用健康接口的逻辑是否正确(始终返回2xx)。
3️⃣ 资源不足导致探测超时
现象:在业务高峰时Pod频繁重启。
解决方案:
- 适当增加
timeoutSeconds,给应用更长的响应时间。
- 检查并合理设置容器的 CPU / 内存的
requests 和 limits,避免因资源竞争导致应用响应变慢。
Liveness Probe 最佳实践
为了在生产环境中稳定有效地使用存活探测,请遵循以下准则:
- 探测逻辑要简单、轻量:健康检查接口应避免包含复杂的数据库查询或下游服务调用,只做最核心的存活判断,防止探测本身成为性能瓶颈或故障源。
- 与 Readiness Probe 区分使用:明确二者职责,通常 Readiness Probe 的失败阈值可以比 Liveness Probe 设置得更低、更敏感,以便快速摘流。
- 避免探测接口依赖核心业务:健康检查端点应独立于核心业务逻辑,即使业务模块故障,只要主进程健康,探测就应成功,否则可能陷入“业务故障->探测失败->重启->业务仍故障”的循环。
- 设置合理的失败阈值:利用
failureThreshold 和 periodSeconds 设置一个合理的“宽限期”,例如允许连续2次、每次间隔10秒的失败,避免因网络瞬时抖动导致不必要的重启。
- 定期审查和调整配置:随着应用迭代和部署环境变化,重新评估探测参数是否依然合适。
- 配合监控与告警:对 Pod 重启次数 (
kube_pod_container_status_restarts_total) 和探测失败事件设置监控告警,便于及时发现潜在问题。
总结
在 Kubernetes 中,合理运用 Liveness Probe、Readiness Probe 和 Startup Probe 这套组合拳,是构建高韧性应用架构的关键一步。它们能显著提升 Pod 乃至整个服务的稳定性和可用性。
然而,关键不在于“是否配置了探测”,而在于你是否真正理解自己应用的特性,并为它量身定制了合适的探测策略。一个考虑周到的探测配置,能够平滑应对各种异常;而一个粗暴的配置,反而可能成为系统不稳定的推手。
只有深入业务,设计出贴合实际的健康检查机制,才能真正释放 Kubernetes 强大的自愈能力,让你的应用在云原生时代稳如磐石。如果你在实践中遇到了更多有趣的案例或挑战,欢迎到 云栈社区 与众多开发者一起交流探讨。