Eigene Health Checks für Magento bauen
AI generated
M2
di.xml
Magento 2 · Observability · Health Checks · Kubernetes
Eigene Health Checks für Magento bauen
mehr als nur ein 200er Status Code

Ein Health Check, der nur prüft, ob der Webserver antwortet, meldet einen Shop als gesund, obwohl die Datenbank blockiert, die Suche down ist oder die Message Queue voll läuft. Ein durchdachter Health Check Endpoint prüft echte Abhängigkeiten und verhindert, dass ein Load Balancer weiter Traffic auf einen defekten Node schickt.

17 Min. Lesezeit Liveness · Readiness · Dependency Checks · Kubernetes Probes Magento 2.4.x · PHP 8.3

1. Warum ein Health Check mehr als ein Ping sein muss

Viele Magento Installationen verlassen sich auf einen einfachen HTTP-Aufruf auf die Startseite, um zu entscheiden, ob ein Node gesund ist. Das Problem: Die Startseite kann durch den Full Page Cache ausgeliefert werden, selbst wenn die Datenbank dahinter längst nicht mehr erreichbar ist. Ein solcher Health Check meldet dauerhaft grün, während der Checkout, der nicht gecacht wird, für echte Kunden bereits fehlschlägt.

Ein durchdachter Health Check prüft stattdessen gezielt die Abhängigkeiten, von denen der Betrieb tatsächlich abhängt: die Datenbankverbindung, den Redis-Cache, die Suchmaschine und die Message-Queue-Verbindung. Erst wenn diese Prüfungen erfolgreich sind, meldet der Health Check Endpoint den Node als bereit für Traffic. Diese Präzision ist der Unterschied zwischen einem Monitoring, das echte Ausfälle erkennt, und einem, das nur Schein-Sicherheit vermittelt.

Für produktive Magento Shops mit mehreren Application-Servern hinter einem Load Balancer ist ein eigener Health Check keine Kür, sondern Grundvoraussetzung für sauberes Rolling-Deployment und automatisches Failover. Ohne ihn bleibt jedem Operator nur die Wahl zwischen blindem Vertrauen und manuellem Eingriff bei jedem Vorfall.

2. Liveness und Readiness: zwei unterschiedliche Fragen

Ein zentrales Missverständnis bei Health Checks ist, Liveness und Readiness als dasselbe zu behandeln. Liveness beantwortet die Frage, ob der Prozess überhaupt noch läuft und reagiert, unabhängig davon, ob er gerade Anfragen sinnvoll bedienen kann. Readiness beantwortet die Frage, ob der Node aktuell bereit ist, Traffic zu empfangen, weil alle notwendigen Abhängigkeiten erreichbar sind.

Der Unterschied wird konkret, wenn die Datenbank kurzzeitig nicht erreichbar ist: Der PHP-Prozess selbst läuft weiterhin einwandfrei, Liveness bleibt also grün. Readiness dagegen muss auf rot springen, damit der Load Balancer keinen neuen Traffic mehr auf diesen Node schickt, während bestehende Verbindungen kontrolliert auslaufen. Ein Health Check Endpoint, der beide Konzepte vermischt, riskiert entweder unnötige Neustarts bei Liveness-Fehlern oder blindes Weiterleiten von Traffic bei Readiness-Problemen.

3. Einen eigenen Health Check Controller in Magento bauen

Magento bringt bereits einen einfachen health_check.php mit, der aber nur grundlegende Verfügbarkeit prüft. Für einen aussagekräftigen Health Check lohnt sich ein eigener Controller, der über eine dedizierte Route erreichbar ist und strukturiert JSON mit dem Status jeder einzelnen Abhängigkeit zurückgibt. Dieser Ansatz macht Probleme sofort diagnostizierbar, statt nur einen binären Status zu liefern.

Wichtig ist, den Controller unabhängig vom regulären Frontend-Layout zu halten, damit ein Ausfall im Layout-System selbst den Health Check nicht mit in den Abgrund reißt. Eine direkte Antwort ohne Block-Rendering und ohne Template-Engine reduziert die Angriffsfläche für Fehler im Health Check selbst erheblich.


<?php
declare(strict_types=1);

namespace Mironsoft\Observability\Controller\Health;

use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\JsonFactory;
use Mironsoft\Observability\Model\HealthCheck\CheckPool;

/**
 * Runs all registered dependency checks and returns a structured JSON result.
 */
class Index implements HttpGetActionInterface
{
    /**
     * @param JsonFactory $resultJsonFactory Factory for building JSON responses.
     * @param CheckPool   $checkPool         Pool of registered dependency checks.
     */
    public function __construct(
        private readonly JsonFactory $resultJsonFactory,
        private readonly CheckPool $checkPool,
    ) {
    }

    /**
     * Executes every registered check and returns the aggregated status.
     *
     * @return ResponseInterface
     */
    public function execute(): ResponseInterface
    {
        $results = [];
        $healthy = true;

        foreach ($this->checkPool->getChecks() as $name => $check) {
            $result = $check->run();
            $results[$name] = $result->toArray();
            $healthy = $healthy && $result->isHealthy();
        }

        $resultJson = $this->resultJsonFactory->create();
        $resultJson->setHttpResponseCode($healthy ? 200 : 503);

        return $resultJson->setData(['status' => $healthy ? 'ok' : 'degraded', 'checks' => $results]);
    }
}

4. Datenbank und Redis in den Check einbeziehen

Die Datenbankprüfung sollte nicht nur eine offene Verbindung testen, sondern eine minimal aussagekräftige Abfrage ausführen, etwa das Auslesen des Store-Konfigurationswerts. Eine reine Verbindungsprüfung übersieht Situationen, in denen die Verbindung besteht, aber die Datenbank durch Locks oder Replikationsverzögerung faktisch nicht arbeitsfähig ist. Der Health Check für die Datenbank misst zusätzlich die Antwortzeit und markiert den Node bereits bei deutlich erhöhter Latenz als degradiert, nicht erst beim vollständigen Timeout.

Für Redis gilt ein ähnliches Prinzip: Ein PING-Befehl allein reicht nicht aus, wenn Redis als Session-Storage konfiguriert ist und der verwendete Datenbank-Index nicht erreichbar ist. Der Health Check sollte denselben Redis-Client und dieselbe Konfiguration nutzen wie die produktive Session-Verwaltung, damit ein Konfigurationsfehler, der nur einen bestimmten Cache-Bereich betrifft, auch tatsächlich erkannt wird.


<?php
declare(strict_types=1);

namespace Mironsoft\Observability\Model\HealthCheck;

use Magento\Framework\App\ResourceConnection;

/**
 * Verifies the database connection by running a lightweight, real query
 * instead of just checking whether a connection object exists.
 */
class DatabaseCheck implements CheckInterface
{
    private const SLOW_THRESHOLD_MS = 200;

    /**
     * @param ResourceConnection $resourceConnection Magento's DB connection resolver.
     */
    public function __construct(private readonly ResourceConnection $resourceConnection)
    {
    }

    /**
     * Runs a minimal read query and measures its latency.
     *
     * @return CheckResult
     */
    public function run(): CheckResult
    {
        $start = microtime(true);

        try {
            $connection = $this->resourceConnection->getConnection();
            $connection->fetchOne('SELECT 1');
        } catch (\Throwable $exception) {
            return CheckResult::failed('database', $exception->getMessage());
        }

        $elapsedMs = (microtime(true) - $start) * 1000;

        return $elapsedMs > self::SLOW_THRESHOLD_MS
            ? CheckResult::degraded('database', sprintf('slow response: %.1fms', $elapsedMs))
            : CheckResult::healthy('database');
    }
}

5. Suche und Message Queue prüfen, ohne den Shop zu belasten

Elasticsearch oder OpenSearch lassen sich über den Cluster-Health-Endpunkt prüfen, der ohnehin für genau diesen Zweck existiert und keine teure Suchanfrage erfordert. Ein Health Check, der stattdessen eine echte Produktsuche ausführt, erzeugt unnötige Last auf dem Suchindex und verzögert die Antwort des gesamten Checks unnötig, gerade bei großen Katalogen.

Die Message Queue, meist RabbitMQ, lässt sich über die Management-API prüfen, ob die relevanten Queues existieren und keine übermäßige Anzahl unverarbeiteter Nachrichten aufweisen. Ein Health Check, der nur die TCP-Verbindung zu RabbitMQ testet, übersieht das häufigste reale Problem: einen hängenden Consumer, der Nachrichten empfängt, aber nicht mehr verarbeitet, während sich die Warteschlange füllt.

6. Health Checks in Kubernetes Probes einbinden

In einer Kubernetes-Umgebung übersetzen sich Liveness und Readiness direkt in die entsprechenden Probe-Typen. Die Liveness Probe sollte bewusst schlank bleiben und nur prüfen, ob PHP-FPM antwortet, damit ein temporärer Datenbankausfall nicht zu einem Neustart des gesamten Pods führt, der das Problem gar nicht lösen würde. Die Readiness Probe dagegen ruft den vollständigen Health Check Endpoint mit allen Abhängigkeitsprüfungen auf.

Wichtig ist die Konfiguration von initialDelaySeconds, damit ein frisch gestarteter Pod nicht sofort als fehlgeschlagen markiert wird, während Magento noch den OPcache aufwärmt. Ein zu aggressives Probe-Intervall in Kombination mit einem teuren Health Check kann zudem selbst zur Lastquelle werden, weshalb Frequenz und Prüfungstiefe bewusst gegeneinander abgewogen werden müssen.


# Kubernetes deployment snippet for Magento application pods
livenessProbe:
  httpGet:
    path: /health_check.php
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 3
readinessProbe:
  httpGet:
    path: /rest/V1/mironsoft-observability/health
    port: 8080
  initialDelaySeconds: 45
  periodSeconds: 15
  timeoutSeconds: 5
  failureThreshold: 2

7. Sicherheit: Health Check Endpoint absichern

Ein Health Check Endpoint, der Details über interne Systemzustände preisgibt, etwa Datenbank-Hostnamen oder Fehlermeldungen aus Exceptions, ist ein Informationsleck für Angreifer. Die öffentliche Variante des Endpunkts sollte nur einen aggregierten Status zurückgeben, während detaillierte Diagnosedaten nur über eine interne Route oder mit gültiger Authentifizierung sichtbar sind.

Zusätzlich sollte der Health Check nicht über die reguläre Magento-Middleware mit vollständiger Session-Initialisierung laufen, weil das unnötige Last erzeugt und potenziell Angriffsfläche über Session-Handling eröffnet. Eine schlanke, dedizierte Route außerhalb der normalen Store-View-Auflösung ist hier die robustere Wahl.

8. Timeouts, Caching und Kaskadeneffekte vermeiden

Jeder einzelne Check innerhalb des Health Check Endpoints braucht ein eigenes, kurzes Timeout. Ohne diese Begrenzung kann eine hängende Abhängigkeit, etwa eine Datenbank, die auf einen Lock wartet, den gesamten Health-Check-Aufruf blockieren und damit den Load Balancer glauben lassen, der gesamte Node sei tot, obwohl nur ein einzelner Teilcheck hängt.

Ein weiterer wichtiger Aspekt ist ein kurzes Caching der Ergebnisse, etwa für zwei bis fünf Sekunden, damit ein aggressiv pollender Load Balancer nicht bei jeder Anfrage erneut alle Abhängigkeiten prüft und damit selbst zur Lastquelle für die Datenbank wird. Der Health Check darf niemals selbst zum Performance-Problem werden, das er eigentlich aufdecken soll.

9. Health-Check-Strategien im Vergleich

Es gibt mehrere Reifegrade, wie ein Health Check für Magento umgesetzt werden kann. Die folgende Tabelle ordnet die gängigen Varianten nach Aussagekraft und Aufwand ein.

Strategie Aussagekraft Risiko Empfehlung
Startseite per HTTP prüfen Sehr gering, oft gecacht Verdeckt Datenbank- und Suchausfälle Nicht als alleiniger Check nutzen
Nur TCP-Port-Check Gering Erkennt hängende Prozesse nicht Nur als Liveness, nicht als Readiness
Eigener aggregierter Endpoint Hoch, prüft echte Abhängigkeiten Muss selbst gegen Timeouts abgesichert werden Empfohlener Standard für Magento
Synthetische Transaktion (echter Checkout) Sehr hoch, End-to-End Erzeugt echte Bestellungen ohne Sorgfalt Nur mit Testkonten und niedriger Frequenz

Die pragmatische Empfehlung für die meisten Magento Betriebe ist der eigene aggregierte Endpoint, ergänzt um eine seltene synthetische Transaktion mit dedizierten Testkonten, um echte End-to-End-Funktionsfähigkeit regelmäßig, aber ohne operativen Overhead zu verifizieren.

Mironsoft

Magento Observability, Health Checks und Betriebsstabilität

Ein Health Check, dem euer Load Balancer wirklich trauen kann?

Wir bauen einen eigenen Health Check Endpoint für euren Magento Shop, der Datenbank, Cache, Suche und Message Queue prüft, sauber in Kubernetes Probes einbindet und selbst nicht zur Fehlerquelle wird.

Dependency Checks

Datenbank, Redis, Suche und Message Queue einzeln geprüft

Kubernetes-Integration

Liveness und Readiness Probes korrekt getrennt konfiguriert

Absicherung

Timeouts, Caching und Zugriffskontrolle für den Endpoint selbst

10. Zusammenfassung

Ein aussagekräftiger Health Check für Magento prüft echte Abhängigkeiten statt nur die Erreichbarkeit des Webservers. Datenbank, Redis, Suche und Message Queue müssen einzeln bewertet werden, mit eigenen Timeouts, damit ein einzelner hängender Teilcheck nicht den gesamten Node fälschlich als tot markiert. Die klare Trennung von Liveness und Readiness verhindert unnötige Neustarts bei temporären Abhängigkeitsproblemen.

In Kubernetes-Umgebungen übersetzt sich diese Struktur direkt in zwei unterschiedlich konfigurierte Probes, während der Health Check Endpoint selbst durch Caching und Zugriffskontrolle vor Missbrauch und übermäßiger Last geschützt werden muss. Wer diesen Aufwand einmal investiert, gewinnt zuverlässiges Rolling-Deployment und automatisches Failover, ohne blind auf einen einfachen Ping zu vertrauen.

Eigene Health Checks für Magento — Das Wichtigste auf einen Blick

Liveness vs. Readiness

Liveness prüft, ob der Prozess läuft. Readiness prüft, ob alle Abhängigkeiten erreichbar sind. Nie vermischen.

Echte Abhängigkeiten prüfen

Datenbank mit echter Query, Redis mit produktivem Client, Suche über Cluster-Health, Queue über Management-API.

Timeouts pro Check

Jede Einzelprüfung braucht ein kurzes eigenes Timeout, sonst blockiert eine hängende Abhängigkeit den gesamten Check.

Absicherung

Keine internen Details in der öffentlichen Antwort, kurzes Ergebnis-Caching gegen aggressive Poller.

11. FAQ: Eigene Health Checks für Magento bauen

1Reicht ein HTTP-Ping auf die Startseite?
Nein, die Seite wird meist gecacht und antwortet auch bei ausgefallener Datenbank oder Suche fälschlich grün.
2Unterschied Liveness und Readiness?
Liveness prüft den Prozess selbst, Readiness prüft, ob alle Abhängigkeiten aktuell erreichbar sind.
3Welche Abhängigkeiten prüfen?
Mindestens Datenbank, Redis, Suchmaschine und Message Queue, jeweils mit echter Mini-Operation.
4Reicht eine reine Verbindungsprüfung?
Nein, eine offene Verbindung sagt nichts über Locks oder Replikationsverzögerung aus. Eine echte Query mit Zeitmessung ist nötig.
5Suche prüfen, ohne Last zu erzeugen?
Über den Cluster-Health-Endpunkt von Elasticsearch oder OpenSearch statt einer echten Produktsuche.
6Häufigster Fehler bei Message-Queue-Checks?
Nur die TCP-Verbindung zu prüfen statt Warteschlangenlänge und Consumer-Aktivität über die Management-API.
7Kubernetes Probes richtig konfigurieren?
Liveness schlank halten, Readiness ruft den vollständigen Check auf, mit ausreichendem initialDelaySeconds.
8Sicherheitsrisiken beim Endpoint?
Detaillierte Fehlermeldungen liefern Angreifern Informationen. Öffentliche Antwort nur aggregiert halten.
9Warum Ergebnisse kurz cachen?
Sonst wird der Health Check bei aggressivem Polling selbst zur Lastquelle für die Datenbank.
10Lohnt sich eine synthetische Transaktion?
Ja, mit dedizierten Testkonten und niedriger Frequenz als Ergänzung, nicht als Ersatz für den regulären Check.