Add Kubernetes Liveness and Readiness Probes support
Prior to this commit and as of Spring Boot 2.2.0, we would advise developers to use the Actuator health groups to define custom "liveness" and "readiness" groups and configure them with subsets of existing health indicators. This commit addresses several limitations with that approach. First, `LivenessState` and `ReadinessState` are promoted to first class concepts in Spring Boot applications. These states should not only based on periodic health checks. Applications should be able to track changes (and adapt their behavior) or update states (when an error happens). The `ApplicationStateProvider` can be injected and used by applications components to get the current application state. Components can also track specific `ApplicationEvent` to be notified of changes, like `ReadinessStateChangedEvent` and `LivenessStateChangedEvent`. Components can also publish such events with an `ApplicationEventPublisher`. Spring Boot will track startup event and application context state to update the liveness and readiness state of the application. This infrastructure is available in the main spring-boot module. If Spring Boot Actuator is on the classpath, additional `HealthIndicator` will be contributed to the application: `"LivenessProveHealthIndicator"` and `"ReadinessProbeHealthIndicator"`. Also, "liveness" and "readiness" Health groups will be defined if they're not configured already. Closes gh-19593
This commit is contained in:
@@ -181,6 +181,11 @@ See the {spring-boot-module-api}/cloud/CloudFoundryVcapEnvironmentPostProcessor.
|
||||
|
||||
TIP: The https://github.com/pivotal-cf/java-cfenv/[Java CFEnv] project is a better fit for tasks such as configuring a DataSource.
|
||||
|
||||
[[cloud-deployment-kubernetes]]
|
||||
=== Kubernetes
|
||||
Spring Boot auto-detects Kubernetes deployment environments by checking the environment for `"*_SERVICE_HOST"` and `"*_SERVICE_PORT"` variables.
|
||||
|
||||
Spring Boot helps you to <<spring-boot-features.adoc#boot-features-kubernetes-application-state,manage the state of your application>> and export it with <<production-ready-features.adoc#production-ready-kubernetes-probes, HTTP Kubernetes Probes using Actuator>>.
|
||||
|
||||
|
||||
[[cloud-deployment-heroku]]
|
||||
@@ -254,10 +259,7 @@ For more details, refer to https://devcenter.heroku.com/articles/deploying-sprin
|
||||
|
||||
[[cloud-deployment-openshift]]
|
||||
=== OpenShift
|
||||
https://www.openshift.com/[OpenShift] is the Red Hat public (and enterprise) extension of the Kubernetes container orchestration platform.
|
||||
Similarly to Kubernetes, OpenShift has many options for installing Spring Boot based applications.
|
||||
|
||||
OpenShift has many resources describing how to deploy Spring Boot applications, including:
|
||||
https://www.openshift.com/[OpenShift] has many resources describing how to deploy Spring Boot applications, including:
|
||||
|
||||
* https://blog.openshift.com/using-openshift-enterprise-grade-spring-boot-deployments/[Using the S2I builder]
|
||||
* https://access.redhat.com/documentation/en-us/reference_architectures/2017/html-single/spring_boot_microservices_on_red_hat_openshift_container_platform_3/[Architecture guide]
|
||||
|
||||
@@ -647,7 +647,7 @@ If no `HealthIndicator` returns a status that is known to the `StatusAggregator`
|
||||
TIP: The `HealthContributorRegistry` can be used to register and unregister health indicators at runtime.
|
||||
|
||||
|
||||
|
||||
[[production-ready-health-indicators]]
|
||||
==== Auto-configured HealthIndicators
|
||||
The following `HealthIndicators` are auto-configured by Spring Boot when appropriate:
|
||||
|
||||
@@ -679,6 +679,12 @@ The following `HealthIndicators` are auto-configured by Spring Boot when appropr
|
||||
| {spring-boot-actuator-module-code}/jms/JmsHealthIndicator.java[`JmsHealthIndicator`]
|
||||
| Checks that a JMS broker is up.
|
||||
|
||||
| {spring-boot-actuator-module-code}/kubernetes/LivenessProbeHealthIndicator.java[`LivenessProbeHealthIndicator`]
|
||||
| Exposes the "Liveness" application state.
|
||||
|
||||
| {spring-boot-actuator-module-code}/kubernetes/ReadinessProbeHealthIndicator.java[`ReadinessProbeHealthIndicator`]
|
||||
| Exposes the "Readiness" application state.
|
||||
|
||||
| {spring-boot-actuator-module-code}/ldap/LdapHealthIndicator.java[`LdapHealthIndicator`]
|
||||
| Checks that an LDAP server is up.
|
||||
|
||||
@@ -835,10 +841,9 @@ TIP: If necessary, reactive indicators replace the regular ones.
|
||||
Also, any `HealthIndicator` that is not handled explicitly is wrapped automatically.
|
||||
|
||||
|
||||
|
||||
[[production-ready-health-groups]]
|
||||
==== Health Groups
|
||||
It's sometimes useful to organize health indicators into groups that can be used for different purposes.
|
||||
For example, if you deploy your application to Kubernetes, you may want one different sets of health indicators for your "`liveness`" and "`readiness`" probes.
|
||||
|
||||
To create a health indicator group you can use the `management.endpoint.health.group.<name>` property and specify a list of health indicator IDs to `include` or `exclude`.
|
||||
For example, to create a group that includes only database indicators you can define the following:
|
||||
@@ -865,6 +870,35 @@ It's also possible to override the `show-details` and `roles` properties if requ
|
||||
TIP: You can use `@Qualifier("groupname")` if you need to register custom `StatusAggregator` or `HttpCodeStatusMapper` beans for use with the group.
|
||||
|
||||
|
||||
[[production-ready-kubernetes-probes]]
|
||||
=== Kubernetes Probes
|
||||
Applications deployed on Kubernetes can provide information about their internal state with https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes[Container Probes].
|
||||
Depending on https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/[your Kubernetes configuration], the kubelet will call those probes and react to the result.
|
||||
|
||||
When deployed in a Kubernetes environment, Spring Boot will manage your <<spring-boot-features.adoc#boot-features-kubernetes-application-state,Kubernetes Application State>>.
|
||||
Spring Boot Actuator will gather the "Liveness" and "Readiness" information using <<production-ready-health-indicators,Health Indicators>>
|
||||
and expose them as HTTP Probes using <<production-ready-health-groups, Health Groups>>.
|
||||
You can then point your Kubernetes `"livenessProbe"` to `"/actuator/health/liveness"` and `"readinessProbe"` to `"/actuator/health/readiness"`.
|
||||
|
||||
If your application context startup can be longer than the configured `"livenessProbe"` timeout, configuring a `"startupProbe"` can solve startup issues.
|
||||
|
||||
TIP: Application should perform long-running startup tasks with `ApplicationRunners`; in this case, you don't necessarily need a `"startupProbe"` as such tasks are performed after the "Liveness" state is marked as successful.
|
||||
The application won't receive traffic until tasks are finished - only then the `"readinessProbe"` will be successful.
|
||||
|
||||
As explained in the <<spring-boot-features.adoc#boot-features-kubernetes-application-state,Kubernetes Application State section>>, depending on external systems for defining the "Liveness" state might result in cascading failures.
|
||||
In case your application needs to rely on a specific subset of health checks for "Liveness" or "Readiness", you should consider configuring <<production-ready-health-groups, Health Groups>> manually:
|
||||
|
||||
[source,properties,indent=0,configprops]
|
||||
----
|
||||
management.endpoint.health.group.readiness.include=readinessProbe,customCheck
|
||||
----
|
||||
|
||||
WARNING: If your Actuator endpoints are deployed on a separate management context, be aware that endpoints are then not using the same web infrastructure (port, connection pools, framework components) as the main application.
|
||||
In this case, a Probe check could be successful even if the main application does not work properly (for example, it cannot accept new connections).
|
||||
|
||||
You'll find more information in the <<deployment.adoc#cloud-deployment-kubernetes, deploying on Kubernetes>> section.
|
||||
|
||||
|
||||
|
||||
[[production-ready-application-info]]
|
||||
=== Application Information
|
||||
|
||||
@@ -6013,6 +6013,90 @@ For instance, it is possible to customize the name of the table for the JDBC sto
|
||||
For setting the timeout of the session you can use the configprop:spring.session.timeout[] property.
|
||||
If that property is not set, the auto-configuration falls back to the value of configprop:server.servlet.session.timeout[].
|
||||
|
||||
[[boot-features-kubernetes-application-state]]
|
||||
== Kubernetes Application State
|
||||
When deployed on Kubernetes, applications can provide information about their state to the platform using https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/[Kubernetes Probes].
|
||||
Spring Boot manages this application state with the `ApplicationStateProvider` and makes it available to application components and the cloud platform itself.
|
||||
This feature is only enabled when the application is running on Kubernetes.
|
||||
|
||||
TIP: The cloud platform detection relies on platform-specific environment variables, but you can override this detection with the configprop:spring.main.cloud-platform[] configuration property.
|
||||
|
||||
[[boot-features-kubernetes-liveness-state]]
|
||||
=== Liveness State
|
||||
The "Liveness" state of an application tells whether its internal state allows it to work correctly, or recover by itself if it's currently failing.
|
||||
An invalid "Liveness" state means that the application is in a broken state and cannot recover from it; the infrastructure should then restart the application to mitigate that problem.
|
||||
|
||||
NOTE: In general, the "Liveness" state should not be based external checks, such as <<production-ready-features.adoc#production-ready-health, Health checks>>.
|
||||
If it did, a failing external system (a database, a Web API, an external cache) would trigger massive restarts and cascading failures across the platform.
|
||||
|
||||
The internal state of Spring Boot applications is mostly represented by the Spring application context.
|
||||
If the application context has started successfully, Spring Boot assumes that the application is in a valid state.
|
||||
An application is considered live as soon as the `ApplicationStartedEvent` has been published, see <<boot-features-application-events-and-listeners, Spring Boot application lifecycle and related Application Events>>.
|
||||
|
||||
[[boot-features-kubernetes-readiness-state]]
|
||||
=== Readiness State
|
||||
The "Readiness" state of an application tells whether the application is ready to handle traffic.
|
||||
A failing "Readiness" state tells Kubernetes that it should not route traffic to the application for now.
|
||||
This typically happens during startup, while `CommandLineRunner` and `ApplicationRunner` components are being processed, or at any time if the application decides that it's too busy for additional traffic.
|
||||
|
||||
An application is considered live as soon as the `ApplicationReadyEvent` has been published, see <<boot-features-application-events-and-listeners, Spring Boot application lifecycle and related Application Events>>.
|
||||
|
||||
TIP: Tasks expected to run during startup should be executed by `CommandLineRunner` and `ApplicationRunner` components instead of using Spring component lifecycle callbacks such as `@PostConstruct`.
|
||||
|
||||
[[boot-features-kubernetes-managing-state]]
|
||||
=== Managing Kubernetes Application State
|
||||
Application components can retrieve the current application state at any time, by injecting the `ApplicationStateProvider` and calling methods on it.
|
||||
More often, applications will want to listen to state updates or update the state of the application.
|
||||
|
||||
For example, we can export the "Readiness" state of the application to a file so that a Kubernetes "exec Probe" can look at this file:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Component
|
||||
public class LivenessStateExporter implements ApplicationListener<LivenessStateChangedEvent> {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(LivenessStateChangedEvent event) {
|
||||
switch (event.getLivenessState().getStatus()) {
|
||||
case LIVE:
|
||||
// create file /tmp/healthy
|
||||
break;
|
||||
case BROKEN:
|
||||
// remove file /tmp/healthy
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
We can also update the state of the application, when the application breaks and cannot recover:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Component
|
||||
public class LocalCacheVerifier {
|
||||
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
public LocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
public void checkLocalCache() {
|
||||
try {
|
||||
//...
|
||||
}
|
||||
catch (CacheCompletelyBroken ex) {
|
||||
this.eventPublisher.publishEvent(LivenessStateChangedEvent.broken(ex));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
Spring Boot provides <<production-ready-features.adoc#production-ready-kubernetes-probes,Kubernetes HTTP probes for "Liveness" and "Readiness" with Actuator Health Endpoints>>.
|
||||
You can get more guidance about <<deployment.adoc#cloud-deployment-kubernetes,deploying Spring Boot applications on Kubernetes in the dedicated section>>.
|
||||
|
||||
|
||||
[[boot-features-jmx]]
|
||||
|
||||
Reference in New Issue
Block a user