Filebeat mit SFTP-Pull

Sharing is caring!

In meinem heutigen Beitrag möchte ich gerne einige Erkenntnisse meiner letzten Arbeitsmonate teilen. Wir haben ein spannendes Projekt erfolgreich gemeistert und dabei interessante Problemstellungen gelöst.

Disclaimer: ich werde keine Interna teilen. Der Kunde ist natürlich geheim und ich werde weder Code noch Konfigurationen publik machen (können), das ist intellectual property meines Arbeitgebers, sprich der Bredex GmbH. Wer vor der gleichen oder einer ähnlichen Problematik steht, sollte sich mit diesen Informationen aber selber helfen können (oder beauftragt uns 😏).

Worum geht's? Die Systeme des Kunden laufen mit Solaris - auf Spark. Hab ich vorher noch nie angefasst. Auf Solaris ist Filebeat nicht verfügbar und für Spark lässt sich das auch afaik nicht cross-kompilieren, was am Ende des Tages aber auch relativ egal ist. Wir haben für diesen Auftrag die Anforderung bekommen, dass wir alle Logs über SFTP abholen müssen. Und das ist schon etwas speziell - wer intensiv nach im Internet sucht, wird recht bald feststellen, dass dies eigentlich nicht so empfohlen ist und wird auch einige Beiträge in den entsprechenden Foren finden, welche sich mit dieser Aufgabenstellung (erfolglos) beschäftigen.

Eigentlich klingt das ganze simpel: alle 15 Minuten bekommen wir die "frischen" Logs zur Verfügung gestellt. Eine Minute später importieren wir die Dateien mit einem kleinen Bash-Script, lftp, loggen den Importvorgang um auf Fehler reagieren zu können, feine Sache. Für jedes System gibt es einen Ordner, dort landen die Logs und werden dann auf unseren Servern mittels Filebeat aufgenommen und in Graylog gepusht. Klingt easy? Joa, kann man so sagen. Der Teufel steckt aber im Detail...

Wenn man das so ausprobiert, wird aber mit der Realität konfrontiert und die Logs werden zigfach von Filebeat importiert! Hat etwas gedauert, bis ich die Zusammenhänge verstanden habe. Erstmal muss man verstehen, wie Filebeat funktioniert. Das ist eigentlich ganz einfach. Filebeat merkt sich die Dateien und wieviele Bytes schon eingelesen worden sind. Wenn eine Datei größer wird, fängt Filebeat dahinter an, neue Zeilen einzulesen. Man muss hier aber auch wissen, wie Dateisysteme unter Linux funktionieren (zumindest fast alle). Im Dateisystem ist eine Datei nicht durch den Namen oder den Pfad definiert, sondern durch eine spezielle Zahl, die inode. Neue inode? Neue Datei! Und auch Filebeat beachtet die inode. Neue Inode? Die Datei muss neu sein, also verwirft Filebeat den Stand, wieviele Bytes schon eingelesen wurden und fängt von vorne an. So hat man zig Duplikate der Ereignisse, die Datenbank von OpenSearch/Graylog-Datanode wird gigantisch groß. Und der Import dauert natürlich entsprechend VIEL länger. Der Grund dafür ist, dass über SFTP Dateien nicht aktualisiert werden, sprich das Delta geholt wird, die Datei wird gelöscht und komplett neu geholt. Neue Datei -> neue inode! rsync-over-SSH könnte das eventuell, war in unserem Fall aber nicht möglich. Nur reines SFTP.

Trotzdem war rsync hier unsere Lösung. Wir importieren jetzt für SFTP/lftp in einen temporären Ordner, danach schieben wir mit rsync --inplace die Logs in den Ordner, aus dem wir mit Filebeat die Daten aufnehmen. Der Parameter inplace sorgt dafür, dass sich die inode nicht ändert. Wird die Datei größer, kann Filebeat an der richtigen Stelle weiterarbeiten. Funktioniert auch, wenn durch logrotate eine neue, frische Logdatei entsteht.

tl;dr: Logimport über SFTP kann funktionieren. Per lftp in ein temporäres Verzeichnis holen, dann mittels rsync --inplace in das finale Verzeichnis übertragen und dort mit Filebeat aufnehmen. So lassen sich Duplikate vermeiden und viel Serverkapazität sparen.