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.
© 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

Die Kunst der langen Aufgabenläufe - Kimi K3 – das Modell hinter dem Agenten, Teil 2
Ein guter Code-Generator löst eine klar umrissene Funktion. Ein Coding-Agent muss dagegen ein Repository erkunden, Hypothesen bilden, Werkzeuge auswählen, Tests auswerten und nach Fehlschlägen den Kurs ändern. Kimi K3 zielt auf diese zweite Klasse von Aufgaben.
8 Minuten
MessagePack: JSON als Binär-Image - Best of NuGet, Teil 10
Das Serialisierungsformat MessagePack wurde – anders als JSON – konsequent auf die Bedürfnisse von Maschinen und damit auch auf höchstmögliche Kompaktheit optimiert. Der Vorteil: Ein geringeres zu übertragendes Datenvolumen führt vor allem in IoT-nahen Anwendungen direkt zu geringeren Kosten.
6 Minuten
17. Aug 2026
Gebaut für lange Läufe - Kimi K3 – das Modell hinter dem Agenten, Teil 1
Kimi K3 kombiniert 2,8 Billionen Parameter, native Bildverarbeitung und ein Kontextfenster mit einer Million Token. Das sind tolle Zahlen. Seine Besonderheit liegt aber darin, dass Architektur, Training und Laufzeitumgebung auf Agenten zielen, die über viele Schritte handeln, Werkzeuge aufrufen und Ergebnisse prüfen.
6 Minuten

Das könnte Dich auch interessieren

Health Checks für Ressourcen - Health Checks in ASP.NET richtig nutzen, Teil 3
Wenn externe APIs stocken, Speicher knapp wird oder Ressourcen an Grenzen laufen, reicht ein grüner Gesamtstatus nicht mehr aus. Wie Health Checks näher an die tatsächlichen Betriebsrisiken heranrücken, ohne den Diagnose-Endpunkt unnötig aufzublähen.
4 Minuten
Die Chromium-Engine anbinden - Ein eigenes Steuerelement für Webinhalte, Teil 14
Das Browser-Control wird für den Einbau der Chromium-Engine vorbereitet.
10 Minuten
17. Okt 2022
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
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige