spring boot应用设置k8s探针的误区

最近发现有些spring boot项目在k8设置的探针存在问题,在实际运行过程中,存在突发的重启现象。借这个机会总结一下相关用法,作为后续项目参考。

k8s探针的概念

配置存活、就绪和启动探测器

上面的链接是官网的资料,可以看到三个主要的探针作用分别是:

  • kubelet 使用存活探测器来知道什么时候要重启容器。 例如,存活探测器可以捕捉到死锁(应用程序在运行,但是无法继续执行后面的步骤)。 这样的情况下重启容器有助于让应用程序在有问题的情况下更可用。
  • kubelet 使用就绪探测器可以知道容器什么时候准备好了并可以开始接受请求流量, 当一个 Pod 内的所有容器都准备好了,才能把这个 Pod 看作就绪了。 这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。 在 Pod 还没有准备好的时候,会从 Service 的负载均衡器中被剔除的。
  • kubelet 使用启动探测器可以知道应用程序容器什么时候启动了。 如果配置了这类探测器,就可以控制容器在启动成功后再进行存活性和就绪检查, 确保这些存活、就绪探测器不会影响应用程序的启动。 这可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉。

探针设置的原则

我们这里主要关注就绪探针和存活探针。可看到存活探针对应用的影响非常大。

之前有不少应用是基于Spring Boot Actuator来设置探针的。例如用健康检查health这个路径来处理。

经历了生产故障之后,维护反馈要不要随意重启,会有很多问题,希望区别对待。后来在讨论中也经常提到,由人来控制什么时候重启比较好。结论就是希望提供两个路径,一个作为探针,不要检查数据库之类,一个作为监控平台的健康检查。

后来想想,health作为存活探针也的确不合适,因为:

  • 基本上health会检查依赖的中间件,检查的内容多了之后,有时候可能会容易超时。
  • 如果真的是某些依赖的中间件有问题,重启也没办法解决问题,某些情况还可能因为大面积重启造成中间件的连接风暴。
  • 很多时候,只要依赖的中间件恢复了,应用自动就恢复,不需要重启才能恢复。

所以,应用的存活探针主要关注应用自身的情况,典型的情况,例如业务线程是否正常(程序有没有hung住)。

就绪探针影响就小多了,由于它会在检测失败的时候从Service中摘除,一定程度上这是一个保护机制,让应用可能恢复正常。所以就绪探针可以敏感一些,快速隔离,快速恢复。

这样看的话,就需要至少两套检测路径,一套用于就绪探针,比较敏感,关注必要的核心组件,检测到不可用后可能触发隔离,看看是否可以自动恢复。一套用于存活探针,没那么敏感,只关注应用自身,非极端情况不触发。可能还有第三套,用于全面监控,例如部分不可用(但不影响业务)的情况也可以感知到,最敏感,内容最详细,用于监控告警,便于提前介入。

spring boot的探针支持

原本是打算定制一套,还好发现spring boot2.3已经内置了一套标准做法。无论是就绪探针,还是存活探针,都可以选择包括哪些模块的检测,非常方便。

顺手找了几个参考材料。