<p>I want to implement custom logic to determine readiness for my pod, and I went over this: <a href="https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.kubernetes-probes.external-state" rel="noreferrer">https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.kubernetes-probes.external-state</a> and they mention an example property:
<code>management.endpoint.health.group.readiness.include=readinessState,customCheck</code></p>
<p>Question is - how do I override <code>customCheck</code>?
In my case I want to use HTTP probes, so the yaml looks like:</p>
<pre><code>readinessProbe:
  initialDelaySeconds: 10
  periodSeconds: 10
  httpGet:
    path: /actuator/health
    port: 12345
</code></pre>
<p>So then again - where and how should I apply logic that would determine when the app is ready (just like the link above, i'd like to rely on an external service in order for it to be ready)</p>

Hummus
<p>To expand KrzysztofS's answer:</p>
<p>First, create a custom health indicator like this:</p>
<pre class="lang-java prettyprint-override"><code>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(&quot;Already initialized&quot;);
    }
    ready.set(true);
  }
}

</code></pre>
<p>This must be a bean, or Spring won't be able to discover it.</p>
<p><code>@Autowire</code> your component to your service or another component, and call its <code>markAsReady()</code> function when this indicator should switch into &quot;ready&quot; state.</p>
<p>Next, add the name of the bean<sup>1</sup> into &quot;include&quot; block for &quot;readiness&quot; group in your application.yaml file (if you're using application.properties, figure it out yourself).</p>
<pre class="lang-yaml prettyprint-override"><code>management:
  endpoint:
    health:
      group:
        readiness:
          include: readinessState, myCustomReadinessIndicator
      show-components: always
      show-details: always
      probes:
        enabled: true

</code></pre>
<p>Next, try running your application and opening various Actuator endpoints.</p>
<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>Endpoint</th>
<th><code>ready</code> state of<br />your indicator</th>
<th>HTTP response<br />code</th>
<th>JSON response</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>/actuator/health</code></td>
<td><code>false</code></td>
<td>503</td>
<td><code>{</code><br /><code>  &quot;status&quot;: &quot;OUT_OF_SERVICE&quot;,</code><br /><code>  &quot;components&quot;:</code><br /><code>  {</code><br /><code>    &quot;myCustomReadinessIndicator&quot;:</code><br /><code>    {</code><br /><code>      &quot;status&quot;: &quot;OUT_OF_SERVICE&quot;</code><br /><code>    },</code><br /><code>    &quot;livenessState&quot;:</code><br /><code>    {</code><br /><code>      &quot;status&quot;: &quot;UP&quot;</code><br /><code>    },</code><br /><code>    &quot;readinessState&quot;:</code><br /><code>    {</code><br /><code>      &quot;status&quot;: &quot;UP&quot;</code><br /><code>    }</code><br /><code>  },</code><br /><code>  &quot;groups&quot;: [&quot;liveness&quot;, &quot;readiness&quot;]</code><br /><code>}</code></td>
</tr>
<tr>
<td><code>/actuator/health/liveness</code></td>
<td><code>false</code></td>
<td>200</td>
<td><code>{&quot;status&quot;:&quot;UP&quot;}</code></td>
</tr>
<tr>
<td><code>/actuator/health/readiness</code></td>
<td><code>false</code></td>
<td>503</td>
<td><code>{</code><br /><code>  &quot;status&quot;: &quot;OUT_OF_SERVICE&quot;,</code><br /><code>  &quot;components&quot;:</code><br /><code>  {</code><br /><code>    &quot;myCustomReadinessIndicator&quot;:</code><br /><code>    {</code><br /><code>      &quot;status&quot;: &quot;OUT_OF_SERVICE&quot;</code><br /><code>    },</code><br /><code>    &quot;readinessState&quot;:</code><br /><code>    {</code><br /><code>      &quot;status&quot;: &quot;UP&quot;</code><br /><code>    }</code><br /><code>  }</code><br /><code>}</code></td>
</tr>
<tr>
<td><code>/actuator/health</code></td>
<td><code>true</code></td>
<td>200</td>
<td><code>{</code><br /><code>  &quot;status&quot;: &quot;UP&quot;,</code><br /><code>  &quot;components&quot;:</code><br /><code>  {</code><br /><code>    &quot;myCustomReadinessIndicator&quot;:</code><br /><code>    {</code><br /><code>      &quot;status&quot;: &quot;UP&quot;</code><br /><code>    },</code><br /><code>    &quot;livenessState&quot;:</code><br /><code>    {</code><br /><code>      &quot;status&quot;: &quot;UP&quot;</code><br /><code>    },</code><br /><code>    &quot;readinessState&quot;:</code><br /><code>    {</code><br /><code>      &quot;status&quot;: &quot;UP&quot;</code><br /><code>    }</code><br /><code>  },</code><br /><code>  &quot;groups&quot;: [&quot;liveness&quot;, &quot;readiness&quot;]</code><br /><code>}</code></td>
</tr>
<tr>
<td><code>/actuator/health/liveness</code></td>
<td><code>true</code></td>
<td>200</td>
<td><code>{&quot;status&quot;:&quot;UP&quot;}</code></td>
</tr>
<tr>
<td><code>/actuator/health/readiness</code></td>
<td><code>true</code></td>
<td>200</td>
<td><code>{</code><br /><code>  &quot;status&quot;: &quot;UP&quot;,</code><br /><code>  &quot;components&quot;:</code><br /><code>  {</code><br /><code>    &quot;myCustomReadinessIndicator&quot;:</code><br /><code>    {</code><br /><code>      &quot;status&quot;: &quot;UP&quot;</code><br /><code>    },</code><br /><code>    &quot;readinessState&quot;:</code><br /><code>    {</code><br /><code>      &quot;status&quot;: &quot;UP&quot;</code><br /><code>    }</code><br /><code>  }</code><br /><code>}</code></td>
</tr>
</tbody>
</table>
</div>
<p>Now, you need to set <code>/actuator/health/readiness</code> in your readiness probe's path</p>
<pre class="lang-yaml prettyprint-override"><code>readinessProbe:
  initialDelaySeconds: 10
  periodSeconds: 10
  httpGet:
    path: /actuator/health/readiness
    port: 12345
</code></pre>
<p>Related: set liveness probe's path to <code>/actuator/health/liveness</code> not to <code>/actuator/health</code>, since <code>/actuator/health</code> will return 503 if your indicator isn't ready yet, even though <code>livenessState</code> is &quot;UP&quot;.</p>
<hr />
<p><sup>1</sup> Bean name is usually camel-cased name of the class, starting with lowercase letter, but you can override it by providing name in component annotation: <code>@Component(&quot;overriddenName&quot;)</code></p>
