【问题标题】:Spring Boot app + Kubernetes liveness/readiness checksSpring Boot 应用程序 + Kubernetes 活性/就绪性检查
【发布时间】:2019-06-13 12:46:49
【问题描述】:

我正在构建一些 Spring Boot 微服务,这些微服务将部署在 Kubernetes(特别是 AKS)集群中。我计划将 liveness & readiness 检查的 probePaths 设置为都指向执行器健康端点,但想知道这是否不是最佳选择。我最初的想法是检查路径会很有用(至少对于准备就绪),因此在 Spring 启动并能够处理请求之前不会将流量发送到它。由于这些服务使用数据库连接,如果无法建立连接,执行器健康指示器将报告状态为关闭,这不是一个好主意吗?

有了活性,我认为它可能会开始一遍又一遍地回收 pod/容器,即使(在数据库关闭的情况下)它可能无法解决任何问题。

准备就绪后,我认为如果数据库关闭,它可能会导致可用应用程序池为 0。如果数据库关闭,应用程序本身很可能不会很有用,但我想部分可能仍然有效。

对于这类事情有推荐的最佳做法吗?

【问题讨论】:

  • 我建议的第一件事是让应用程序在给定的时间间隔内多次尝试连接数据库,这样如果之前没有初始化数据库,它就不会中断......
  • 您能进一步解释一下吗?不太确定我明白。 IIRC,如果 Spring 无法创建初始连接,Spring 将在启动时存在该进程,或者您的意思是一旦它运行,然后 DB 就会关闭?
  • 这取决于你。我将同时为案例以及活跃度和就绪度探测实施“待定 DB conn”。但是对于一个有趣的问题 +1 我希望使用 spring + k8s 的人能进一步解释......

标签: spring-boot kubernetes spring-boot-actuator


【解决方案1】:

从 Spring Boot 2.3 开始,核心支持 the Availability state of the application(包括 Liveness 和 Readiness),can be exposed as Kubernetes Probes with Actuator

您的问题很准确,the Spring Boot issue for the Liveness/Readiness feature 对此进行了详细讨论。

/health 端点从未真正设计为公开应用程序状态并驱动云平台如何处理它的应用程序实例并将流量路由到它。由于 Spring Boot 在这里没有更好的功能,它已经被大量使用了。

Liveness 只有在应用程序的内部状态被破坏并且我们无法从中恢复时才会失败。正如您在问题中强调的那样,一旦外部系统不可用就在这里失败可能是危险的:平台可能会根据该外部系统回收所有应用程序实例(可能是所有应用程序实例?)并导致级联故障,因为其他系统可能也取决于该应用程序。

默认情况下,除非应用程序本身更改了该内部状态,否则活性问题将回复“成功”。

Readiness 探测实际上是关于应用程序服务流量的能力。正如您所提到的,一些健康检查可能会显示应用程序基本部分的状态,而另一些则不会。 Spring Boot 会将就绪状态与应用程序的生命周期同步(Web 应用程序已启动,已请求正常关闭,我们不应再路由流量等)。有一种方法可以配置“就绪”健康组,以包含针对您的特定用例的一组自定义健康检查。

我不同意收到赏金的答案中的一些陈述,特别是因为 Spring Boot 发生了很大变化,因为:

  1. 从 Spring Boot 2.3.0 起,您不应将 /actuator/health 用于 Liveness 或 Readiness 探测。
  2. 使用新的 Spring Boot 生命周期,您应该将所有长时间运行的启动任务移动为 ApplicationRunner bean - 它们将在 Liveness 为 Success 之后、Readiness 为 Success 之前执行。如果应用程序启动对于配置的探针来说仍然太慢,那么您应该使用具有更长超时时间的 StartupProbe 并将其指向 Liveness 端点。
  3. 使用管理端口可能很危险,因为它使用的是单独的 Web 基础架构。例如,暴露在管理端口上的探测器可能没问题,但主连接器(为客户端提供实际流量)可能不堪重负,无法提供更多流量。在某些情况下,为探测重用相同的服务器和 Web 基础设施可能更安全。

有关此新功能的更多信息,您可以阅读专门的 Kubernetes Liveness and Readiness Probes with Spring Boot 博客文章。

【讨论】:

  • 感谢您的回复,很高兴听到这个消息——我一定会进一步调查。我一目了然,只是为了确认一下,您是否认为数据库连接不应该包含在活动性/就绪性检查中?
  • 活跃度:可能不是;如果连接池可以在与数据库的连接备份后自行修复,那么一遍又一遍地重新启动应用程序是没有意义的。对于Readiness,它真的取决于应用程序:它是否有这个数据库的后备?这个相同的数据库实例是否在所有应用程序实例之间共享?对此没有统一的答案。
【解决方案2】:

ReadinessProbe - 应用准备好处理请求了吗?

使用运行状况检查来检查应用是否已准备好处理新请求。这可以在/actuator/health 中实现。另请参阅下面的 StartupProbe

在高负载下?

如果您的应用处于高负载下,它可能无法及时响应健康检查,导致ReadinessProbe 失败 .考虑使用Horizontal Pod Autoscaler 来获取更多副本来处理负载。

LivenessProbe - 应用程序是否死锁?

如果您的应用处于不可恢复状态,最好是它可以自行终止,例如使用java.lang.System.exit(1)。如果应用程序可能会死锁,无法继续,请考虑为LivenessProbe 实现一个端点,这可能ReadinessProbe 相同。

长时间未响应就绪状态

如果您的应用长时间没有响应 ReadinessProbe,例如很多分钟,可能有问题(除非您希望您的应用会发生这种情况),那么您可能还应该将 /actuator/health 作为您的 LivenessProbe,但使用更高的 failureThreshold initialDelaySeconds(例如几分钟)

StartupProbe - Kubernetes 1.16+ 上的更好替代方案

ReadinessProbe 在应用启动期间最有用,因为它可能需要加载,例如准备好接收请求之前的数据 - ReadinessProbe 在 pod 生命周期中定期执行。 StartupProbe is now a better alternativeLivenessProbe 结合使用时启动缓慢的应用程序,仅在 StartupProbe 之后才处于活动状态。您可能仍需要 ReadinessProbe 来通知 pod 已准备好处理请求。

取决于其他服务

如果您的应用依赖于其他服务,这些服务不健康 - 如果您的应用可以从这些情况中恢复更好,当支持服务再次启动时,例如重新连接。否则,如果您的服务链没有响应 ReadinessProbeLivenessProbe,这将是 多米诺连锁反应,因为最后一个应用程序在链条有问题。考虑提供降级服务,通知你没有完全服务,也许你的一些端点仍然工作正常。

使用管理服务器端口

发送探测请求的是同一节点上的kubelet。考虑使用Management Server Port 进行探测。您不需要将此端口暴露给Service,最好将一个端口用于http,另一个用于管理

云提供商负载均衡服务健康检查

如果您使用云提供商负载均衡器,它可能会对您的服务进行健康检查,您可能需要配置它发送健康检查的路径,例如Google Cloud Platform 默认为 /。这是对 Service 的健康检查,而不是对单个 Pod 的健康检查。

【讨论】:

    【解决方案3】:

    我们使用 Spring boot Actuator 自定义健康检查来进行 Liveness 和 Readiness 检查。您可以使用自定义逻辑来确定您是否能够满足请求。如果您能够处理请求,则保持 pod 处于活动状态,否则重新启动它。对于数据库连接问题,仅当您的连接被卡住且未释放时,重启才会有所帮助。

    【讨论】:

      【解决方案4】:

      我们正在使用标准的 /actuator/health 端点来进行活动和准备,并且已经使用了将近一年。积极的一面是,除非应用程序的所有连接都已启动并正在运行,否则该应用程序不会被标记为可以使用。不利的一面是由于某些错误的连接情况,这会导致停机/重新启动。

      在我看来,与其数据库(或其他重要基础设施)没有任何连接的应用程序是无用的。由于它可能无法正常运行,您不妨报告它不可用。因此,除非您遇到与数据库连接不良或其他问题的问题,否则我真的看不出使用 /actuator/health 对活跃性和就绪性的危害。此外,这是一种检查您的应用程序是否启动和运行的廉价方法,只需很少的手动设置即可。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-03
        • 2018-05-20
        • 2020-10-31
        • 2018-05-31
        • 2020-02-20
        • 1970-01-01
        • 2021-01-20
        • 2018-04-21
        相关资源
        最近更新 更多