Wazuh Dashboard zeigt nur noch Daten eines Workers: Systematische Fehleranalyse für „Filebeat sendet, Indexer ingestiert nicht“

Einleitung

Wenn in einer Wazuh-Cluster-Architektur plötzlich nur noch Events von einem Worker im Dashboard auftauchen, wirkt es auf den ersten Blick wie ein Indexer-Problem. In der Praxis liegt die Ursache häufig an einer Kette aus Nebenwirkungen: ein kurzfristig voller Datenträger auf dem betroffenen Worker, ein danach „gesund“ wirkender Filebeat – und trotzdem keine ingestierten Dokumente. Dieser Beitrag zeigt, wie man die Pipeline sauber eingrenzt und welche Wazuh-/Indexer- und OpenSearch-Mechanismen genau dieses asymmetrische Verhalten (Worker #1 ok, Worker #2 „weg“) erklären.

Ausgangslage / Problemstellung

  • Wazuh-Cluster mit Master + Indexer + Dashboard auf einer Maschine, plus zwei Worker-Manager.
  • Worker #1: Events werden normal indexiert und im Dashboard angezeigt.
  • Worker #2: Agents/Syslog liefern Events, tcpdump bestätigt Traffic, /var/ossec/logs/alerts/alerts.json und archives.json wachsen – aber im Dashboard kommt nichts an.
  • Frühere Störung: Auf Worker #2 gab es „No space left on device“ (u. a. Filebeat-Log und rsyslog). Datenträger wurde erweitert.
  • Filebeat auf Worker #2 ist inzwischen active (running), TLS-Handshake zum Indexer ist ok (filebeat test output), Registry lädt erfolgreich, Harvesters starten.
  • Auf dem Indexer: Ingest-Pipeline-Stats zeigen Aktivität, failed: 0. Threadpools zeigen keine Rejections.

Kernfrage: Wie kann Filebeat „gesund“ aussehen, während ein Worker dauerhaft keine Dokumente im Indexer erzeugt – und das teils sogar intermittierend (kurzzeitig ok, dann wieder stop)?

Technische Analyse

1) „Connection OK“ ist nicht gleich „Indexing OK“

filebeat test output validiert Transport/TLS und die Erreichbarkeit des HTTP-Endpunkts (9200). Es beweist nicht, dass Bulk-Requests erfolgreich geschrieben werden. Typische Fälle, in denen alles „grün“ wirkt, aber trotzdem nichts ankommt:

  • Index ist read-only (z. B. durch Flood-Stage-Watermark) → Bulk wird mit 403 abgewiesen, Filebeat geht in Retry/Backoff.
  • Zielindex existiert nicht/ist blockiert, Template/ISM/Rollover-Probleme → Bulk-Fehler, aber nicht zwingend als ingest pipeline failure sichtbar.
  • Dokumente werden geschrieben, aber Dashboard filtert sie weg (Zeitstempel-/Timezone-Drift, falsches Index-Pattern, andere Dataset-Namen).
  • Filebeat liest zwar Dateien, veröffentlicht aber keine Events (Harvester an „falscher“ Stelle, starkes Backoff, Output-Retry-Schleife).

2) Die „No space left“-Phase kann mehr beschädigen als Logs

Der Voll-Lauf auf Worker #2 betraf /var/log und potenziell /var/lib. Selbst nach einer Disk-Erweiterung bleiben oft sekundäre Effekte:

  • Registry- bzw. State-Inkonsistenzen (bei dir bereits per Registry-Reset adressiert)
  • Wazuh-JSON-Dateien können bei abruptem Stop/IO-Fehler inkonsistente Zeilen enthalten (partial writes). Das führt nicht immer zu klaren Fehlermeldungen, kann aber Publisher/Parser ausbremsen oder zu stillen Drops führen – insbesondere bei Modul-/Pipeline-Parsing.
  • Indexerseitig bleibt ein Index auch nach wieder freiem Speicher manchmal auf index.blocks.read_only_allow_delete=true, wenn das Flag nicht aktiv zurückgesetzt wird. Das ist der Klassiker: Die Ursache ist weg, der „Schalter“ bleibt.

3) Warum Pipeline-Stats und Threadpools trotzdem „normal“ aussehen können

GET _nodes/stats/ingest zeigt Pipeline-Zähler clusterweit. Wenn Worker #1 weiter normal liefert, steigen Counts weiter – ohne dass Worker #2 wieder drin ist.
Threadpool-Views wie _cat/thread_pool/bulk sind Momentaufnahmen. Wenn Worker #2 in Backoff hängt oder Requests sofort abgelehnt werden (403), sieht man oft weder Queue-Aufbau noch Rejections im Bulk-Threadpool, weil die Ablehnung logisch/konfigurationsbedingt passiert (Index block, AuthZ, Template).

4) Asymmetrie (nur Worker #2 betroffen) ist ein starkes Indiz für „Routing/Index/Filter“

Wenn Output-Config wirklich identisch ist, bleiben als wahrscheinlichste Klassen:

  • Index-Pattern-/Routing-Abweichung durch Felder im Event (z. B. manager.name, cluster.node, Dataset/Module) → Worker #2 schreibt in einen anderen Index oder Data Stream, den das Dashboard nicht anzeigt.
  • Read-only/Block nur auf dem Zielindex, den Worker #2 trifft (z. B. anderer Daily-Index, anderer Namespace).
  • Zeitstempel-Drift auf Worker #2 → Dokumente landen außerhalb der Dashboard-Zeitfilter (wirkt wie „nicht ingestiert“).

Lösung / Best Practices

Schritt 1: Auf dem Indexer beweisen, ob Worker #2 überhaupt Dokumente erzeugt

Der schnellste Realitätscheck ist eine Query nach manager.name (in deinen Beispieldaten ist manager.name: worker2 vorhanden):

  • Suche im Indexer (Dev Tools) nach Worker #2 in einem engen Zeitfenster:
    • Query auf die üblichen Wazuh-Indizes (z. B. wazuh-alerts-*, wazuh-archives-*) und Filter manager.name:"worker2" plus @timestamp „last 15m“.

Ergebnis-Interpretation:

  • Treffer vorhanden: Problem ist sehr wahrscheinlich Dashboard-Index-Pattern, Zeitfilter, Data View, oder Mapping/Field-Namen.
  • Keine Treffer: Dann ist es wirklich ein Schreib-/Indexing-Problem (Block/Reject/Retry) oder Filebeat published nicht.

Schritt 2: Indexer auf „read-only“/Blocks prüfen und hart zurücksetzen

Nach Disk-Pressure bleibt das Flag oft stehen. Prüfe clusterweit:

  • Settings-Abfrage auf index.blocks.read_only_allow_delete (für alle Wazuh-Indizes relevant).
  • Falls gesetzt: Flag entfernen (Settings auf false/null setzen) – idealerweise für die betroffenen Wazuh-Indizes, nicht blind für _all in produktiven Umgebungen.

Das ist eine der wenigen Maßnahmen, die häufig „sofort“ Wirkung zeigt, ohne dass Filebeat oder Wazuh neu installiert werden muss.

Schritt 3: Unassigned Shards gezielt erklären (nicht nur zählen)

Du hattest unassigned shards im Umfeld. Auch wenn Shard-Limits nicht erreicht sind, können unassigned primaries Index-Schreibbarkeit indirekt beeinflussen (z. B. wenn ein neuer Tagesindex nicht korrekt allokiert). Vorgehen:

  • _cluster/health (Status, unassigned, active primaries)
  • _cat/indices wazuh-* (welche Indizes sind red/yellow?)
  • _cat/shards wazuh-* (welche shards sind UNASSIGNED?)
  • _cluster/allocation/explain für ein konkretes unassigned shard

Typische Fixes:

  • Replica-Anzahl an tatsächliche Node-Anzahl anpassen (z. B. bei Single-Node-Indexer Replicas auf 0).
  • Disk/Watermark-Allocation-Constraints aufheben, wenn sie nach der Erweiterung weiterhin greifen.
  • Node-Ausfall / attr-based allocation korrigieren.

Schritt 4: Filebeat wirklich beim Publizieren beobachten – inklusive HTTP-Responses

Du hast bereits -d "publish,output" gestartet und den Connect gesehen. Der entscheidende Teil ist: Bulk Response Codes und „events published“-Zähler.

Best Practice zur Eingrenzung:

  • Filebeat im Foreground mit Output-Debug laufen lassen und gezielt nach folgenden Mustern suchen:
    • 403/401 (Security/Index block/AuthZ)
    • 429 (Backpressure)
    • 400 (mapping/parsing errors)
    • „retrying bulk request“, „backoff“
    • Zähler wie „published events“, „acked events“

Wenn du hier 403 siehst, ist die Ursache fast immer Index-Block oder Rollen/Permissions (z. B. ein Zertifikat/User, der zwar connecten darf, aber nicht schreiben).

Schritt 5: Zeitstempel- und Dashboard-Sicht prüfen (der „es ist da, aber du siehst es nicht“-Fall)

Weil Worker #1 sichtbar ist, bleibt ein Dashboard-Filterproblem lange unbemerkt. Prüfe auf Worker #2:

  • Systemzeit/NTP-Sync (große Offsets führen zu Events „in der Zukunft“ oder „weit in der Vergangenheit“)
  • Ob der Dashboard-Data-View wirklich alle relevanten Indizes umfasst (nicht nur einen Teil)
  • Ob Worker #2 evtl. in einen anderen Index schreibt (z. B. durch abweichende Felder, dataset, pipeline routing)

Schritt 6: Wazuh-Cluster-Synchronisation nicht mit Indexing verwechseln

Du hast korrekt präzisiert: Alerts/Archives liegen auf dem Worker, nicht auf dem Master. Das ist bei Wazuh-Clustern nicht automatisch ein Fehler – entscheidend ist, dass Filebeat auf jedem Worker seine lokalen JSON-Dateien liest und direkt zum Indexer schreibt.
Trotzdem lohnt sich ein schneller Cluster-Check, weil Instabilität (Worker reconnects) zu Lücken führen kann: Worker-Verbindungen, Queue-Druck, event drops.

Lessons Learned / Best Practices

  • Nach „Disk voll“ immer zwei Ebenen heilen: Filesystem + Indexer-Write-Blocks (read-only flags) + ggf. Registry/State. Nur Disk erweitern reicht oft nicht.
  • Clusterweite Ingest-Stats sind kein Beweis pro Quelle: Wenn ein Worker noch liefert, wirken Pipelines „gesund“, obwohl eine Quelle komplett fehlt.
  • Unassigned Shards müssen erklärt werden, nicht nur gezählt: Allocation-Constraints, Replicas und Watermarks wirken oft indirekt auf neue Indizes.
  • Beweise zuerst, wo die Daten verschwinden: Indexer-Query nach manager.name ist der schnellste Truth-Test, bevor man weiter im Nebel debuggt.
  • Asymmetrische Ausfälle sind meist Routing/Filter/Block, nicht „Indexer kaputt“: Besonders, wenn ein Worker durchläuft und nur einer ausfällt.

Fazit

In einem Wazuh-Cluster, in dem Worker #1 normal indexiert und Worker #2 „verschwindet“, ist der Indexer selten „generell kaputt“. Der Befund „Connection OK, Pipelines aktiv, failed=0“ passt sehr gut zu zwei typischen Root Causes: (1) Index-Write-Blocks, die nach einer Disk-Pressure-Phase bestehen bleiben, und/oder (2) Routing-/Sichtbarkeitsprobleme (andere Indizes, Zeitstempel-Drift, Dashboard-Data-View). Die zielführendste Strategie ist: erst auf dem Indexer per Query beweisen, ob Worker #2 Dokumente erzeugt, dann konsequent Blocks/Allocation erklären und Filebeat-Bulk-Responses auswerten. Das führt in der Regel deutlich schneller zum Fix als „noch mehr Logs sammeln“.

https://wazuh.slack.com/archives/C07BZJY86G3/p1765472595554929