Jeder Systemadministrator sollte die Logs seiner Server im Auge haben. Sobald man aber mehr als nur ein paar Systeme administriert, wird man mehr oder weniger von den eingehenden Logs überflutet. Um die Übersicht nicht zu verlieren, kann man die Logs z.B. mit Hilfe von syslog-ng kategoriersieren und filtern. Zusätzlich kann man die Logs zentral auf einem Log-Server speichern. Dies hat den Vorteil, dass die Logdateien der Log-Clients auch zur Verfügung stehen, wenn diese ausfallen.
Die Konfigurationdatei syslog-ng.conf folgt auf den Log-Clients und auf dem Log-Server dem gleichem Schema. Um Log-Nachrichten zu speichern werden drei Bereiche definiert, die Sources (die Quelle der Nachrichten, z.B. /proc/kmsg für Nachrichten vom Kernel oder einen TCP/UDP-Port für Nachrichten von anderen Rechnern), die Destionations, welche das Ziele der Nachrichten sind (z.B. Dateien oder Pipes) und die Filter um Nachrichten z.B. nach Typ oder Priorität zu filtern. Der Befehl log bringt abschließend die drei Bereiche zusammen, wobei die Angabe eines Filters optional ist. Um die eingehenden Nachrichten nach Facilities und Prioritäten zu Ordnen reichen schon folgende Zeilen:

source s_local_all {
  system();
  internal();
  file("/proc/kmsg" program_override("kernel"));
};
destination d_seperateToPriority {
  file ("/var/log/$FACILITY/$FACILITY.$PRIORITY" create_dirs(yes));
};

Hier werden alle lokalen Quellen angezapft und entsprechend nach /var/log/ gespeichert. Oftmals will man aber zusammengehörige Nachrichten unterschiedlicher Priorität nicht aus mehreren Dateien zusammen-grep-en. Um alle Nachrichten einer Facility in einer Datei zu speichern kann man noch folgende Destination einfügen:

destination d_facilities {
  file ("/var/log/$FACILITY/$FACILITY.all" create_dirs(yes));
};

Um eine Source und eine Destination zusammmenzuführen fehlt in dem Beispiel nur noch der log-Aufruf. An diesen übergibt man Sources, Filter und Destinations.

log { source(s_local_all); destination(d_facilities); };
log { source(s_local_all); destination(d_seperateToPriority); };

Es sind natürliche auch andere Aufteilungen der Logs möglich. Welche Makros möglich sind kann in der syslog-ng Dokumentation nachgelesen werden.
Um Lognachrichten an einen zentralen Server zu schicken muss folglich nur eine passende Destination definiert werden. Dazu reicht die Angabe einer IP und eines Ports. Sollen die Nachrichten verschlüsselt versendet werden kann SSL verwendet werden.

destination loghost { tcp("10.10.10.10" port(5140)); };

In der Regel will man aber nicht alle Logs zum zentralen Server schicken. Bei syslog-ng hat jede Nachricht eine von acht Prioritäten. Während des normalen Betriebs sind in der Regeln nur die Stufen emerg, alert, crit, err und warning von Interesse. Es macht also Sinn alle anderen Logs (notice, info, debug) vor dem Senden zum Logserver zu filtern.

filter f_warn2emerg { level(warn .. emerg); };

Der Filter bewirkt, dass nur Nachrichten mit einer Priorität von warn bis emerg berücksichtigt werden. Damit der Filter auch aktiv wird, muss dieser an den log-Aufruf übergeben werden. Hier können auch mehrere Filter hintereinander übergeben werden.

log { source(s_local_all); filter(f_warn2emerg); destination(loghost); };

Somit sendet der Client die Logs an unseren zentralen Server. Dieser muss natürlich noch so konfiguriert werden, dass er die Meldungen annimmt. Dazu reicht eine neue Source am Server aus, die am TCP-Port 5140 lauscht.

source s_remote_tcp { tcp( ip(10.10.10.10) port(5140) ); };

Auf dem Server fehlen jetzt nur noch die Destinations und eventuelle Filter. Diese können analog zum oberen Beispiel definiert werden.
In Normalfall sind Logdateien nicht besonders benutzerfreundlich. Eine Analyse der Logdateien vieler Hosts ist ohne weitere Hilfsmittel nicht zu empfehlen. Eine bessere Möglichkeiten stellen Tools wie Logstash, Graylog2 oder die Icinga EventDB dar. Letztere kann mit Hilfe eines kleines Perl-Skripts gefüttert werden. Dazu muss der Logserver die eingehenden Logs an eine Pipe weiterleiten. Diese gibt man in der Konfigurationsdatei von syslog-ng als Destination an. Zusätzlich wird hier noch die Darstellung der Logs angepasst.

destination d_pipe {
  pipe("/var/run/syslog-ng.pipe",
  template("$HOST\t$SOURCEIP\t$PRI\t$YEAR-$MONTH-$DAY\t$HOUR:$MIN:$SEC\t$PROGRAM\t$MSG\n"));
};

Das Perlskript syslog-ng2mysql.pl überwacht diese Pipe und schickt neue Logs an eine MySQL Datenbank, welche wiederrum die EventDB mit Daten versorgt (weitere Infos).
Jetzt noch die Konfigurationsdateien der Log-Clients mit Hilfe von Puppet verteilen und man ist der Flut der Lognachrichten gewappnet.

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.