微服务应用设置容器健康检查探针的最佳实践
应用现状
Kubernetes的健康检查探针包括了启动探针、就绪探针、存活探针。其中在微服务场景中使用较为常用且易错的是存活探针。该探针主要用于检测容器本身的崩溃和挂起,当检测失败后重启容器,以达到自动检测和恢复的效果。其重点在于检测容器本身而不是容器的外部依赖。
参考Spring官方的开发文档,存活探针(liveness)不应该基于外部检查,例如spring-boot-starter-actuator提供的/actuator/health接口,或者其他框架提供、自己实现的类似效果的接口(后称health check接口)。Health check接口会从业务进程出发,检查所有的外部组件的健康状态,有任何一点异常,接口总体都会返回异常。如果这么配置了,任何一个外部检查的失败可能误触发大面积的业务容器的重启进而引发整个平台的故障。
排查方案
检查是否在容器的健康检查的存活探针设置了health check接口。例如Spring原生的/actuator/health接口,或者该接口修改url后的地址,或者自行实现的会依赖三方组件状态的检查接口。对于使用CCE部署的业务,可以在下图位置找到,一个工作负载可能有多个容器,需要每个容器都检查一下。
不建议在存活探针配置health check的原因有:
- 外部依赖,部分存在降级,并不是全部业务在单个三方件故障时都无法提供服务。例如缓存故障可以读数据库,数据库故障影响写业务,但是读通过缓存实现;消费者在消息队列异常时仍能提供HTTP接口服务;注册中心异常时可以通过内存里的缓存数据调用其他服务。
- 本Pod的重启,对外部组件的异常恢复没有意义。
- 外部依赖的异常往往会同时作用于所有的Pod,会造成大面积的重启。
- Pod重启后的启动阶段,往往会对外部依赖进行强校验,此时如果外部依赖处于异常状态,会导致Pod启动失败,进而导致业务在外部依赖恢复前完全无法提供服务。
解决方案
- 【首推方案】在充分理解容器探针的机制的情况下,结合自身业务实质,自行实现最为准确的存活、就绪检查接口。在无法实现时可参考2通过SpringBoot默认实现。
- 【SpringBoot默认实现】Spring官方专门为Kubernetes的就绪探针、存活探针提供了默认实现,分别为“/actuator/health/readiness”和“/actuator/health/liveness”,该实现需要依赖spring-boot-starter-actuator。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
一般来说,较新的SpringBoot版本在检测到自己运行在Kubernetes中时,会自动打开这两个接口。在其他非Kubernetes环境下,或者SpringBoot版本较老的情况下,需要设置management.endpoint.health.probes.enabled = true 来手动开启这两个接口。
参数名在不同版本的SpringBoot下可能不同,具体请参考业务代码使用的版本的Spring官方文档。
- 当1和2都存在开发或者验证测试的工作量。对于生产环境已经在存活探针(liveness)设置了health check接口,建议尽早在生产环境删除该配置,错误的配置比不配置带来的危险更大。等到1和2验证完成后,再重新做正确的配置。
修改探针会造成容器的重启,建议在业务低峰期或者变更窗口进行删除、修改的操作。