Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 4 Min.

Health Checks und Kubernetes

In Kubernetes entscheidet ein Health Check nicht nur über Sichtbarkeit im Monitoring, sondern auch darüber, ob Traffic fließt oder ein Container neu startet. Hier zeigen wir, warum saubere Grenzen zwischen Liveness und Readiness in produktiven ASP.NET-Anwendungen so wichtig sind.
Healthcheck4.jpg
© EMGenie

In containerisierten Umgebungen, speziell unter Kubernetes, werden Health Checks primär von Liveness- und Readiness-Probes konsumiert. Zur Erinnerung: Die Readiness-Probe beantwortet die Frage: „Kann dieser Pod aktuell sinnvoll Traffic verarbeiten?“ Schlägt die Prüfung fehl, wird der Pod aus dem Load-Balancing genommen, aber nicht neu gestartet. Die Liveness-Probe beantwortet die Frage: „Ist der Prozess in einem derart kaputten Zustand, dass ein Neustart sinnvoll ist?“ Schlägt diese Prüfung wiederholt fehl, startet Kubernetes den Container neu.

Best Practice ist, diese beiden Aspekte sauber zu trennen und im Code entsprechende Endpunkte bereitzustellen. ASP.NET Core unterstützt dafür Tagged Health Checks: Checks lassen sich mit Tags ausstatten, und so können Endpunkte definiert werden, die jeweils nur eine Teilmenge ausführen, wie Listing 1 zeigt.

Listing 1: Konfiguration von Readiness und Liveness
builder.Services.AddHealthChecks()
    // Datenbank betrifft die Readiness
    .AddSqlServer(
        connectionString: builder.Configuration.GetConnectionString("DefaultConnection")!,
        name: "database",
        tags: new[] { "ready" })
    // Speicherprüfung betrifft die Liveness
    .AddCheck("memory", () =>
    {
        var allocated = GC.GetTotalMemory(false);
        var threshold = 1L * 1024L * 1024L * 1024L; // 1 GB
        return allocated < threshold
            ? HealthCheckResult.Healthy($"Speicher: {allocated / 1024 / 1024} MB")
            : HealthCheckResult.Unhealthy($"Speicherlimit überschritten: {allocated / 1024 / 1024} MB");
    }, tags: new[] { "live" });
var app = builder.Build();
// Liveness-Endpunkt
app.MapHealthChecks("/health/live", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("live")
});
// Readiness-Endpunkt
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("ready")
}); 

Die Liveness-Probe ruft dann nur schnelle Checks auf, im Beispiel self, während die Readiness-Probe die kompletten Abhängigkeiten prüft. Damit lässt sich verhindern, dass eine langsam reagierende Datenbank die Liveness-Probe triggert und Pods unnötig neu startet. In der Kubernetes-Deployment-Definition sehen die Probes typischerweise aus wie in Listing 2 gezeigt:

Listing 2: Beispiel für eine Kubernetes-Deployment-Definition
livenessProbe:
  httpGet:
    path: /health/live
    port: 80
  initialDelaySeconds: 10
  periodSeconds: 15
  timeoutSeconds: 5
  failureThreshold: 3
readinessProbe:
  httpGet:
    path: /health/ready
    port: 80
  initialDelaySeconds: 5
  periodSeconds: 30
  timeoutSeconds: 5
  failureThreshold: 5 

Die Parameter sollten zu Startzeit, typischer Latenz und Fehlermustern des konkreten Service passen. Zu aggressive Probes führen sonst dazu, dass Kubernetes Pods aus dem Verkehr zieht, obwohl sie sich gerade nur von einem kurzen Datenbank-Glitch erholen.

Management-Port und Sicherheit

In manchen Umgebungen werden Health-Endpunkte auf einen separaten Management-Port gelegt. Über RequireHost lässt sich der Endpunkt auf eine bestimmte Portkonfiguration beschränken. Dabei lässt sich der Management-Port beispielsweise per Umgebungsvariable setzen. Die beiden folgenden Code-Snippets zeigen die Konfiguration für eine konkrete Domain oder für alle Hosts, aber auf einem bestimmten Port:

 

app.MapHealthChecks("/health")
    .RequireHost("www.example.net:5005");
app.MapHealthChecks("/health")
    .RequireHost("*:5005");

Health-Check-Bibliotheken verteilen

Größere Projekte entwickeln in der Regel eigene Health Checks in Form von Bibliotheken, beispielsweise für Warteschlangen, Message-Broker oder Cloud-Speicherdienste. Die Microsoft-Dokumentation empfiehlt, die IHealthCheck-Implementierung kapselbar zu halten und eine Extension-Methode zur Registrierung zu veröffentlichen. So lassen sich komplexe Prüfungen leicht in andere Services integrieren.

Für produktiven Code haben sich folgende Best Practices etabliert:

  • Kurz angebundene Proben: Es ist sinnvoll, Time-outs für HTTP-Aufrufe, Datenbankverbindungen und Dateizugriffe zu vergeben, um blockierende Checks zu vermeiden.
  • Degradierte Zustände: HealthStatus.Degraded bietet sich an, wenn der Dienst zwar verfügbar, aber nicht performant ist, zum Beispiel durch eine hohe Latenz bei einem API. Dies ermöglicht feineres Routing.
  • Ausführliche Log-Meldungen: Bei Fehlern ist ein detailliertes Log mit Ausnahmen und Kontext zu schreiben, um die Ursachen schnell zu finden.
  • CI-Integration: Health Checks bieten sich für Continuous-Integration-Pipelines an. Ein einfacher Curl-Aufruf gegen den /health-Endpunkt kann einen Build fehlschlagen lassen, wenn ein Service nicht läuft.
  • Überwachungstools: Es ist sinnvoll, Health Checks mit Monitoring-Tools wie beispielsweise Prometheus, Grafana oder OneUptime zu kombinieren. Die JSON-Antwort lässt sich in Dashboards visualisieren, damit Teams frühzeitig Engpässe erkennen können.

Fazit

Health Checks sind ein zentrales Element für zuverlässige ASP.NET-Core-Anwendungen im Cloud-Umfeld. Durch die Kombination aus integrierten Checks (SQL, Redis), selbst erstellten Prüfungen (externe APIs, Speicherplatz) und Kubernetes-Probes lässt sich eine umfassende Sicht auf die Systemgesundheit erstellen. Eine saubere Strukturierung über Tags, klare Fehlerstatus und detaillierte JSON-Antworten ermöglichen es, Probleme schneller zu erkennen und zu beheben.

Neueste Beiträge

KI in Anwendungen mit Microsoft Graph - Connected Apps mit .NET, Teil 4
Eine .NET-App verbindet Microsoft-365-Daten mit semantischer Suche und einem Sprachmodell und erzeugt daraus kontextbezogene Antworten.
9 Minuten
Vom vagen Ticket zum präzisen Prompt - Projektanforderungen an Entwickler in Zeiten von KI, Teil 2
Ein Jira-Ticket sagt: „Bewertungssystem implementieren.“ Ein Mensch liest und denkt den Kontext mit. Ein Agent nicht. Fünf Prompt-Patterns zeigen, wie der Weg vom Ticket zum funktionierenden Code kürzer wird, wenn man lernt, in Kontext statt in Code zu denken.
8 Minuten
22. Okt 2026
Legacy-Modernisierung mit Augenmaß gestalten
Legacy-Systeme durch radikale Ablösungen zu modernisieren, kann schnell nach hinten losgehen. Mehr und mehr setzen sich deshalb Ansätze durch, die Funktionen schrittweise ersetzen, Schnittstellen kontrolliert migrieren und die neue Architektur sukzessive aufbauen.
8 Minuten
26. Okt 2026

Das könnte Dich auch interessieren

Browser-Apps mit Avalonia entwickeln - Avalonia
Klassische UI-Frameworks finden ihren Weg in den Browser
5 Minuten
11. Aug 2025
Grundlagen von Health Checks - Health Checks in ASP.NET richtig nutzen, Teil 1
Ein einfacher Statuscode sagt wenig darüber aus, ob eine Anwendung wirklich betriebsbereit ist. ASP.NET bietet dafür mehr Möglichkeiten, als viele /health-Endpunkte vermuten lassen. Genau dort beginnt der Unterschied zwischen Erreichbarkeit und echter Diagnose.
4 Minuten
Datenbanken und externe Dienste - Health Checks in ASP.NET richtig nutzen, Teil 2
Erst bei Datenbanken, Caches und externen APIs zeigt sich, wie belastbar ein Health Check wirklich ist. Von einfachen Statusmeldungen ausgehend erweitern wir die Möglichkeiten bis hin zu Prüfungen, die Abhängigkeiten sichtbar machen und damit helfen, Ausfälle besser einzuordnen.
3 Minuten
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige