<p>I have built a ASP.NET Core <a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-5.0&amp;tabs=visual-studio" rel="noreferrer">Worker Service</a> (it processes messages off a queue) that is running on kubernetes. Since it is a background service, it currently does not have any HTTP endpoints. Now I would like to add a health/liveness endpoint for k8s to it - ideally leveraging the <a href="https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks" rel="noreferrer">.NET Core standard health checks</a>.</p>
<p>So my question is: Is there a way to expose those health checks without adding the overhead of HTTP endpoints in a way that k8s can use them (<a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes" rel="noreferrer">TCP or generic command</a>)? Any pointers to examples would be great! thanks!</p>

<p>Thanks to the pointers of @pinkfloydx33 I was able to build this solution:</p>
<p>Program.cs</p>
<pre><code>public static IHostBuilder CreateHostBuilder(string[] args) =&gt;
    Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =&gt;
    {
        services.AddHealthChecks() // Register some real health check here ==&gt;
            .AddCheck(&quot;test&quot;, () =&gt; DateTime.UtcNow.Minute % 2 == 0 ? HealthCheckResult.Healthy() : HealthCheckResult.Unhealthy());
        services.AddSingleton&lt;IHealthCheckPublisher, HealthCheckPublisher&gt;();
        services.Configure&lt;HealthCheckPublisherOptions&gt;(options =&gt;
        {
            options.Delay = TimeSpan.FromSeconds(5);
            options.Period = TimeSpan.FromSeconds(20);
        });

        // Register the actual message processor service
        services.AddHostedService&lt;QueueProcessorService&gt;();
    })
</code></pre>
<p>HealthCheckPublisher.cs</p>
<pre><code>public class HealthCheckPublisher : IHealthCheckPublisher
{
    private readonly string _fileName;
    private HealthStatus _prevStatus = HealthStatus.Unhealthy;

    public HealthCheckPublisher()
    {
        _fileName = Environment.GetEnvironmentVariable(&quot;DOCKER_HEALTHCHECK_FILEPATH&quot;) ??
                    Path.GetTempFileName();
    }

    /// &lt;summary&gt;
    /// Creates / touches a file on the file system to indicate &quot;healtyh&quot; (liveness) state of the pod
    /// Deletes the files to indicate &quot;unhealthy&quot;
    /// The file will then be checked by k8s livenessProbe
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;report&quot;&gt;&lt;/param&gt;
    /// &lt;param name=&quot;cancellationToken&quot;&gt;&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
    {
        var fileExists = _prevStatus == HealthStatus.Healthy;

        if (report.Status == HealthStatus.Healthy)
        {
            using var _ = File.Create(_fileName);
        }
        else if (fileExists)
        {
            File.Delete(_fileName);
        }

        _prevStatus = report.Status;

        return Task.CompletedTask;
    }
}
</code></pre>
<p>k8s deployment.yaml (Original Source: <a href="https://medium.com/spire-labs/utilizing-kubernetes-liveness-and-readiness-probes-to-automatically-recover-from-failure-2fe0314f2b2e" rel="nofollow noreferrer">https://medium.com/spire-labs/utilizing-kubernetes-liveness-and-readiness-probes-to-automatically-recover-from-failure-2fe0314f2b2e</a>)</p>
<p>And thank to @zimbres for pointing out a flaw in the liveness probe. This is now an updated version:</p>
<pre class="lang-yaml prettyprint-override"><code>livenessProbe:
  exec:
    command:
    - /bin/sh
    - -c
    - '[ $(find /tmp/healthy -mmin -1 | wc -l) -eq 1 ] || false'
  initialDelaySeconds: 5
  periodSeconds: 10
</code></pre>
