Logs puffern mit rsyslog

Wie wichtig Logdateien sind weiß jeder Administrator und mit Logstash, Graylog und Elasticsearch hat das Thema auch einen kleinen Hype im Open Source Umfeld erfahren. Zur bequemen Analyse der Logs werden diese meist zentral auf einem Logserver gesammelt. Ein typisches Setup wäre z.B. Logstash mit Elasticsearch auf dem Logserver und rsyslog auf den Clients. Warum rsyslog? Es ist mittlerweile der Standard auf den bekannten Linux Distributionen und zudem schlank und zuverlässig. Natürlich macht es Sinn auf Seiten des Logservers Puffer einzubauen (z.B. mit Redis), aber ich will einen genaueren Blick auf die rsyslog-Konfiguration werfen.
Neben einer verschlüsselten Kommunikation erwarte ich von einem Log-Daemon Folgendes:

  • Puffern der Logs, falls der Logserver nicht erreichbar ist.
  • Andere Prozesse dürfen nicht beeinträchtigt oder blockiert werden, wenn der Logserver nicht verfügbar ist.
  • Der Log-Daemon sollte das System auch in extremen Fällen nicht vollschreiben.
  • Logs sollten in einem brauchbarem Format gesendet werden.

Kein Problem:

$WorkDirectory /var/spool/rsyslog
$template ForwardFormat,"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%"
$ActionQueueType LinkedList
$ActionQueueFileName logbuffer
$ActionResumeRetryCount -1
$ActionQueueSaveOnShutdown on
$ActionQueueMaxDiskSpace 200M
$ActionQueueDiscardSeverity 3
$ActionQueueTimeoutEnqueue 5
*.* @@logserver.example.com:4321;ForwardFormat

Ein brauchbares Format wird durch Zeile 2 und 10 erreicht. Vor allem der Timestamp nach RFC3339 ist nützlich. Zeile 2 definiert in dem Template ForwardFormat wie die Logs aussehen sollen und Zeile 10 sendet diese, entsprechend dem Template, per TCP (@@, wie intuitiv) an den Logserver.
Für das Puffern der Logs sind die Zeilen 3-5 zuständig. Als Datentyp soll eine verkettete Liste verwendet werden. Diese hat vor allem den Vorteil, dass nur so viel Speicher wie nötig belegt wird. Ab 8000 Logs im Speicher werden diese auf Platte in die Datei logbuffer gesynct ($ActionQueueHighWaterMark [1,2]). Zeile 7 sorgt dafür, dass maximal 200 MB Logs auf Platte in den Puffer wandern. Weitere Logs (die entweder keinen Platz mehr haben oder zu lange zum Annehmen brauchen) werden dank Zeile 9 verworfen und zwar nach 5 ms. Dies sorgt dafür, dass keine Prozesse blockieren, die versuchen Logs zu schreiben, aber keinen Platz mehr im Puffer kriegen. Zeile 8 bewirkt, dass bei vollen Puffern eher wichtige Logs (Severity 0-2) als unwichtige gepuffert werden. Temporäre Puffer werden auf Grund von Zeile 1 nach /var/spool/rsyslog geschrieben. Die Zeilen 3-9 werden auf die nächste Action angewendet, in diesem Fall Zeile 10.
Mit diesem Setup können Logs immer noch verloren gehen. Allerdings wird es im normalen Zustand wohl kaum passieren, dass der Puffer auf Platte benötigt wird. Sollte es wirklich zu Verbindungsabbrüchen kommen, können hier immer noch 200 MB gepuffert werden und ggf. kann der Wert noch angepasst werden. Mit diesem Setup entscheidet man sich auch für das Verwerfen von Logs, sobald der Puffer voll ist. Dies gewährleistet allerdings, dass andere Systemdienste (wie z.B. sshd) ohne Probleme weiter benutzbar bleiben.
Das Queueing Modell von rsyslog ist nicht so simpel wie oben dargestellt. Eine ausführlichere Beschreibung gibt es in der Dokumentation von rsyslog selbst [1,2].
Anmerkung:
Das oben verwendete Format der rsyslog-Konfiguration wird ab Version 6.3.3 als Legacy Format bezeichnet. In den aktuellen Versionen der bekannten Distributionen wird Version 5.x verwendet.
[1] http://www.rsyslog.com/doc/queues.html
[2] http://www.rsyslog.com/doc/rsyslog_conf_global.html

Achim Ledermüller
Achim Ledermüller
Lead Senior Systems Engineer

Der Exil Regensburger kam 2012 zu NETWAYS, nachdem er dort sein Wirtschaftsinformatik Studium beendet hatte. In der Managed Services Abteilung ist unter anderem für die Automatisierung des RZ-Betriebs und der Evaluierung und Einführung neuer Technologien zuständig.