Thanks to the pointers of @pinkfloydx33 I was able to build this solution:
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHealthChecks() // Register some real health check here ==>
.AddCheck("test", () => DateTime.UtcNow.Minute % 2 == 0 ? HealthCheckResult.Healthy() : HealthCheckResult.Unhealthy());
services.AddSingleton<IHealthCheckPublisher, HealthCheckPublisher>();
services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(5);
options.Period = TimeSpan.FromSeconds(20);
});
// Register the actual message processor service
services.AddHostedService<QueueProcessorService>();
})
HealthCheckPublisher.cs
public class HealthCheckPublisher : IHealthCheckPublisher
{
private readonly string _fileName;
private HealthStatus _prevStatus = HealthStatus.Unhealthy;
public HealthCheckPublisher()
{
_fileName = Environment.GetEnvironmentVariable("DOCKER_HEALTHCHECK_FILEPATH") ??
Path.GetTempFileName();
}
/// <summary>
/// Creates / touches a file on the file system to indicate "healtyh" (liveness) state of the pod
/// Deletes the files to indicate "unhealthy"
/// The file will then be checked by k8s livenessProbe
/// </summary>
/// <param name="report"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
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;
}
}
k8s deployment.yaml (Original Source: https://medium.com/spire-labs/utilizing-kubernetes-liveness-and-readiness-probes-to-automatically-recover-from-failure-2fe0314f2b2e)
And thank to @zimbres for pointing out a flaw in the liveness probe. This is now an updated version:
livenessProbe:
exec:
command:
- /bin/sh
- -c
- '[ $(find /tmp/healthy -mmin -1 | wc -l) -eq 1 ] || false'
initialDelaySeconds: 5
periodSeconds: 10