spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.23k stars 40.7k forks source link

readiness liveness probe issue with springboot 2.2.x #21748

Closed shivrajjadhav733 closed 4 years ago

shivrajjadhav733 commented 4 years ago

What I have:

Windows 10 Springboot 2.2.1 docker desktop installed - docker and kubernetes running openjdk 11

application.yaml in my springboot application

server:
  port: 8443
  servlet:
    context-path: /api
management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-details: always
      group:
        readiness:
          include: '*'
          show-details: always
        liveness:
          include: '*'
          show-details: always

On my local when I start springboot application: To access health, I go to page - http://localhost:8443/api/actuator/health This works fine.

But, when I try to access https://localhost:8443/api/actuator/health/readiness or http://localhost:8443/api/actuator/health/liveness I get error

This localhost page can’t be found. No webpage was found for the web address: http://localhost:8443/api/actuator/health/readiness HTTP ERROR 404

Question - Is this an expected behaviour? readiness or liveness probe can not be tested with just springboot without deploying springboot application to kubernetes?

bclozel commented 4 years ago

Liveness and Readiness support is a new feature in Spring Boot 2.3, see https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#liveness-and-readiness-probes This is not supported in Spring Boot 2.2.x.

Thanks!

shivrajjadhav733 commented 4 years ago

@bclozel About springboot 2.3.0 : Will it automatically add two endpoints? Does it mean we don't need to add those endpoints in application.yaml as management:endpoint:health:group ? Does it mean we don't need to configure that in kubernetes deployment.yaml under container specs if we want to deploy springboot app to kubernetes cluster?

philwebb commented 4 years ago

@shivrajjadhav733 You can read about the new features in the reference docs:

We prefer to use the issue tracker just for bugs, if you have any further questions please ask on gitter.im or stackoverflow.com.

shivrajjadhav733 commented 4 years ago

@bclozel @philwebb Well, I did below things. I upgraded springboot version from 2.1 to 2.3. With that I started seeing default endpoints like /actuator/health/readiness and /actuator/health/liveness I see both are those are UP.

I wanted to add these two restrictions to my application:

  1. Liveness probe should not include backend setup checks like DB. Only want to restart when app is unhealthy.
  2. Readiness probe should include backend setup like DB. I updated my application yaml like below
management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-components: always
      group:
        readiness:
          include:
          - db
        liveness:
          exclude:
          - db

With this change, when I deploy to kubernetes, I can see readiness endpoint shows: /actuator/health/readiness

{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "components": {
        "readDataSource": {
          "status": "UP"
        },
        "writeDataSource": {
          "status": "UP"
        }
      }
    }
  }
}

but for liveness endpoing: /actuator/health/liveness

I get error like 404 not found.

is it something I am making error in application.yaml

philwebb commented 4 years ago

You've defined a liveness group that contains no elements. You either need to include the specific indicators you want (or use "*") or remove it entirely and let the auto-configured "liveness" group get created.

shivrajjadhav733 commented 4 years ago

@philwebb That's what I did with liveness. I just excluded db.

Do I have to do something like

      group:
        readiness:
          include:
          - db
        liveness:
          include: '*'
          exclude:
          - db  

All I am looking for is

I don't want to touch any other default stuff readiness or liveness is doing.

philwebb commented 4 years ago

I think that should do what you want. You need the include: '*'. I've raise #22053 to see if we can't improve that in the future.

shivrajjadhav733 commented 4 years ago

@philwebb Please correct me if I am wrong.

When I exclusively want to include everything along with something specific then I use something like:

management:
  endpoint:
    health:
      group:
        rediness:
          include:
          - db

or should that be:

management:
  endpoint:
    health:
      group:
        rediness:
          include: '*'
          - db

But when I want to exclusively exclude something then I should do

management:
  endpoint:
    health:
      group:
        liveness:
          include: '*'
          exclude:
          - db  
philwebb commented 4 years ago

The "include" property can contain a list of elements or "*" to include them all. The "exclude" property can be used to exclude items that would otherwise be included.

So in your case, if you want readiness to have only "db" and liveness to have everything except "db" you should write:

group:
  readiness:
    include: "db"
  liveness:
    include: "*"
    exclude: "db"
shivrajjadhav733 commented 4 years ago

@philwebb Thank you. This below config worked for me


      group:
        readiness:
          include:
          - db
        liveness:
          include: '*'
          exclude:
          - db  
shivrajjadhav733 commented 4 years ago

@philwebb I was looking at one more additional scenario:

Lets say health end point is /actuator/health and liveness end point is /actuator/health/liveness

  1. liveness - we want to restart when app is unhealthy.
  2. health - we want to mark down when app is unhealthy

Can these scenrio be handled thru application.yaml config OR these are specific for deployment.yaml

bclozel commented 4 years ago

@shivrajjadhav733 I'm sorry but your last comment doesn't really make sense. Did you check the links Phil provided here?

/actuator/health will provide the health information for all indicators. /actuator/health/liveness and /actuator/health/readiness will provide the health information for the liveness and readiness health groups. Now it's up to you to configure those groups to select the indicators which should contribute to the health group status.

  1. As mentioned in our docs, liveness is about whether the internal state of the application is broken or not. If it is broken, this means that the application cannot be fixed automatically and that a full restart of this instance is required. Typically, this happens when an internal state (i.e. not an external service) is broken and cannot be recovered.

  2. the readiness is about whether you'd like to route traffic to your application. Again, it's up to you to decide what qualifies as health indicators for this. An application that is "unready" doesn't necessarily it's unhealthy - it might just be busy handling a lot of requests or tasks.

So your Spring Boot application configuration should reflect how you'd like to express liveness and readiness concepts for this application (including using the application.yml config properties). The deployment.yml is a k8s concept and this is more about how you'd like your infrastructure to check/react to the state of the application.

For further questions about the docs and features in general, feel free to use StackOverflow as it's a better format for Q&A. Thanks!