Spring Boot 自定义 Kubernetes 就绪探针

Hum*_*mus 8 spring-boot kubernetes kubernetes-health-check

我想实现自定义逻辑来确定我的 Pod 的准备情况,我回顾了这一点: https: //docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.kubernetes -probes.external-state他们提到了一个示例属性: management.endpoint.health.group.readiness.include=readinessState,customCheck

问题是 - 我如何覆盖customCheck?就我而言,我想使用 HTTP 探针,因此 yaml 如下所示:

readinessProbe:
  initialDelaySeconds: 10
  periodSeconds: 10
  httpGet:
    path: /actuator/health
    port: 12345
Run Code Online (Sandbox Code Playgroud)

那么话又说回来 - 我应该在哪里以及如何应用逻辑来确定应用程序何时准备就绪(就像上面的链接一样,我想依赖外部服务才能使其准备就绪)

izo*_*fif 7

扩展 KrzysztofS 的答案:

首先,创建一个自定义健康指示器,如下所示:

import java.util.concurrent.atomic.AtomicBoolean;
import org.springframework.boot.actuate.availability.ReadinessStateHealthIndicator;
import org.springframework.boot.availability.ApplicationAvailability;
import org.springframework.boot.availability.AvailabilityState;
import org.springframework.boot.availability.ReadinessState;
import org.springframework.stereotype.Component;

@Component
public class MyCustomReadinessIndicator extends ReadinessStateHealthIndicator {
  private final AtomicBoolean ready = new AtomicBoolean();

  public MyCustomReadinessIndicator(ApplicationAvailability availability) {
    super(availability);
  }

  @Override
  protected AvailabilityState getState(ApplicationAvailability applicationAvailability) {
    return ready.get()
        ? ReadinessState.ACCEPTING_TRAFFIC
        : ReadinessState.REFUSING_TRAFFIC;
  }

  public void markAsReady() {
    if (ready.get()) {
      throw new IllegalStateException("Already initialized");
    }
    ready.set(true);
  }
}

Run Code Online (Sandbox Code Playgroud)

这必须是一个 bean,否则 Spring 将无法发现它。

@Autowire您的组件连接到您的服务或另一个组件,并markAsReady()在该指示器应切换到“就绪”状态时调用其函数。

接下来,将 bean 1的名称添加到 application.yaml 文件中“readiness”组的“include”块中(如果您使用的是 application.properties,请自行计算)。

management:
  endpoint:
    health:
      group:
        readiness:
          include: readinessState, myCustomReadinessIndicator
      show-components: always
      show-details: always
      probes:
        enabled: true

Run Code Online (Sandbox Code Playgroud)

接下来,尝试运行您的应用程序并打开各种 Actuator 端点。

端点 ready
指标的状态
HTTP 响应
代码
JSON 响应
/actuator/health false 503 {
"status": "OUT_OF_SERVICE",
"components":
{
"myCustomReadinessIndicator":
{
"status": "OUT_OF_SERVICE"
},
"livenessState":
{
"status": "UP"
},
"readinessState":
{
"status": "UP"
}
},
"groups": ["liveness", "readiness"]
}
/actuator/health/liveness false 200 {"status":"UP"}
/actuator/health/readiness false 503 {
"status": "OUT_OF_SERVICE",
"components":
{
"myCustomReadinessIndicator":
{
"status": "OUT_OF_SERVICE"
},
"readinessState":
{
"status": "UP"
}
}
}
/actuator/health true 200 {
"status": "UP",
"components":
{
"myCustomReadinessIndicator":
{
"status": "UP"
},
"livenessState":
{
"status": "UP"
},
"readinessState":
{
"status": "UP"
}
},
"groups": ["liveness", "readiness"]
}
/actuator/health/liveness true 200 {"status":"UP"}
/actuator/health/readiness true 200 {
"status": "UP",
"components":
{
"myCustomReadinessIndicator":
{
"status": "UP"
},
"readinessState":
{
"status": "UP"
}
}
}

现在,您需要设置/actuator/health/readiness就绪探针的路径

readinessProbe:
  initialDelaySeconds: 10
  periodSeconds: 10
  httpGet:
    path: /actuator/health/readiness
    port: 12345
Run Code Online (Sandbox Code Playgroud)

相关:将 liveness 探针的路径设置为/actuator/health/livenessnot to /actuator/health,因为/actuator/health如果您的指标尚未准备好,即使livenessState是“UP”,也会返回 503。


1 Bean 名称通常是类的驼峰式名称,以小写字母开头,但您可以通过在组件注释中提供名称来覆盖它:@Component("overriddenName")


小智 5

customCheck 是您的自定义 HealthIndicator 的关键。给定 HealthIndicator 的键是不带 HealthIndicator 后缀的 bean 名称

您可以阅读: https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.health.writing-custom-health-indicators

您正在定义 readinessProbe,因此点击 /actuator/health/readiness 可能是更好的选择。

public class CustomCheckHealthIndicator extends AvailabilityStateHealthIndicator {

    private final YourService yourService;

    public CustomCheckHealthIndicator(ApplicationAvailability availability, YourService yourService) {
        super(availability, ReadinessState.class, (statusMappings) -> {
            statusMappings.add(ReadinessState.ACCEPTING_TRAFFIC, Status.UP);
            statusMappings.add(ReadinessState.REFUSING_TRAFFIC, Status.OUT_OF_SERVICE);
        });
        this.yourService = yourService;
    }

    @Override
    protected AvailabilityState getState(ApplicationAvailability applicationAvailability) {
        if (yourService.isInitCompleted()) {
            return ReadinessState.ACCEPTING_TRAFFIC;
        } else {
            return ReadinessState.REFUSING_TRAFFIC;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)