Spring 启动应用 + Kubernetes liveness/readiness 检查

Spring Boot app + Kubernetes liveness/readiness checks

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

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

准备就绪后,我认为如果数据库关闭,可能会导致可用应用程序池为 0。如果数据库出现故障,应用程序本身很可能不会很有用,但我想某些部分可能仍然可以工作。

对于这类事情有推荐的最佳实践吗?

我们已经使用 Spring boot Actuator 自定义健康检查来检查 Liveness 和 Readiness。您可以使用自定义逻辑来确定您是否能够满足请求。如果您能够为请求提供服务,则让 pod 保持活动状态或重新启动它。对于数据库连接问题,重启只会在您的连接卡住且未释放时有所帮助。

我们正在使用标准的 /actuator/health 端点来衡量活跃度和就绪性,并且已经使用了将近一年。这样做的积极方面是应用程序不会被标记为可以使用,除非它的所有连接都已启动并且 运行。缺点是由于某些情况下的错误连接,导致 downtime/restarts。

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

ReadinessProbe - 应用是否准备好处理请求?

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

高负载?

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

LivenessProbe - 应用程序是否已死锁?

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

长时间未响应就绪

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

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

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

取决于其他服务

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

使用管理服务器端口

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

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

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

从 Spring Boot 2.3 开始,the Availability state of the application (including Liveness and Readiness) is supported in the core and can be exposed as Kubernetes Probes with Actuator

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

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

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

默认情况下,除非应用程序本身更改了该内部状态,否则活动问题将回复 "Success"。

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

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

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

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