Suche
Kolumne

Docker rockt Java: Wie Sie die Docker-Logging-Plug-ins verwenden

Peter Roßbach

Peter Roßbach ist ein InfraCoder, Systemarchitekt und Berater vieler Websysteme. Sein besonderes Interesse gilt dem Design und der Entwicklung von komplexen Infrastrukturen. Er ist Apache Tomcat Committer und Apache Member. Mit der bee42 solutions gmbh realisiert er Infrastrukturprodukte und bietet Schulungen auf der Grundlage des Docker-Ökosystems, aktuellen Webtechnologien, NoSQL-Datenbanken und Cloud-Plattformen an.
Web: http://www.bee42.com

Log-Events einsammeln, auswerten und visualisieren ist eine tägliche Herausforderung. Die Anzahl der vermeintlichen Lösungen für Docker-Container wächst stetig. Die Analyse der Logs ist unerlässlich im Fehlerfall und zur kontinuierlichen Verbesserung der Systeme. In diesem Artikel werden verschiedene Möglichkeiten zum Einsammeln von Log-Events für Docker-Container vorgestellt.

In der Docker Engine können die Ausgaben aller Container unterschiedlich bereitgestellt werden. Traditionell werden die Log-Events von stdout und stderr jedes Containers in eine Datei geschrieben. Der Docker Daemon erledigt diese Umlenkung beim Start jedes Containers. Die Ausgaben können mit der Docker-CLI, genauer dem HTTP-Docker-API, jederzeit auch rückwirkend abgerufen werden. Seit der Version 1.7 kann die Ausgabe auf einen Zeitausschnitt beschränkt werden. Leider funktioniert diese Option aktuell nur in der experimentellen Version für Docker 1.8 hier. Wenn die eigene Software also alle Ausgaben zeilenweise in die Konsole schreibt, können die Ausgaben eines Docker-Hosts also zentral „beauskunftet“ und eingesammelt werden.

 

$ docker run --name logger -d \
  busybox /bin/sh -c \
  'while true; do >&2 echo "hello world"; sleep 1; done;'
$ docker logs -t -f --since 5m logger

Docker Syslog Driver

Seit der Docker-Version 1.7 können die Log-Events auch alternativ zu einem bestehenden Syslog Daemon gesendet werden (Abb. 1). Dieser Syslog-Service kann natürlich am besten in einem Container verpackt und gestartet werden (Listing 2). Damit die Speicherung effizient bleibt, werden die Log-Events in einem Volume im Container gestartet (Listing 3). Natürlich kann alternativ ein Data-Container oder ein Host-Filesystem als Volume definiert werden. Die Installation beruht auf dem Standard-Debian rsyslog. Es werden nur die UDP- und TCP-Module aktiviert und der Zeitstempel konfiguriert. Mit der Umstellung werden nun alle Events in eine Datei gelenkt oder können zu einem zentralen Log-Server weitergeleitet werden.

 

$ mkdir -p rsyslog
$ cd rsyslog
$ cat >Dockerfile < @PRossbach

RUN DEBIAN_FRONTEND=noninteractive apt-get update \
  && apt-get -y -q install rsyslog \
  && rm -rf /var/lib/{apt,dpkg,cache,log}/

RUN sed 's/#$ModLoad imudp/$ModLoad imudp/' -i /etc/rsyslog.conf \
 && sed 's/#$UDPServerRun 514/$UDPServerRun 514/' -i /etc/rsyslog.conf \
 && sed 's/$ModLoad imklog/#$ModLoad imklog/' -i /etc/rsyslog.conf \
 && sed 's/#$ModLoad imtcp/$ModLoad imtcp/' -i /etc/rsyslog.conf \
 && sed 's/$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat/#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat/' -i /etc/rsyslog.conf \
 && sed 's/#$InputTCPServerRun 514/$InputTCPServerRun 514/' -i /etc/rsyslog.conf

VOLUME /var/log

EXPOSE 514/tcp 514/udp

ENTRYPOINT ["/usr/sbin/rsyslogd"]
CMD ["-n"]
EOF
$ docker build -t infrabricks/rsyslog .
$ docker run -d --name rsyslog \
  --volume $(pwd)/logs:/var/log \
  -p 127.0.0.1:514:514/udp infrabricks/rsyslog
$ docker run --rm -ti \
  --volumes-from rsyslog \
  --link rsyslog:logger ubuntu:14.04
> logger -u /foo --udp --server logger "This works fine :)"
> exit
$ docker exec -ti rsyslog tail -f /var/log/syslog

 

$ docker run -d \
  --log-driver syslog \
  --log-opt=syslog-address=udp://127.0.0.1:514 \
  busybox /bin/sh -c \
  'while true; do >&2 echo "hello syslogger"; sleep 1; done;'
$ docker exec -ti rsyslog tail -f /var/log/syslog
Abb. 1: Docker-Driver-Architektur

Abb. 1: Docker-Driver-Architektur

Alternative Docker-Logging-Services

Einer der großen Nachteile der Umlenkung der Log-Events mit syslog ist, dass keine Beauskunftung der Logs über den Docker Daemon mehr möglich ist und die Nachrichten evtl. verlorengehen können. Der Syslog-Container muss als erster auf dem Host laufen, aber leider hat der Docker Daemon noch keine Möglichkeit, Reihenfolgen beim Start der Container zu berücksichtigen. Das sind gewichtige Gründe, warum normalerweise eher eine andere Lösung gewählt wird.

Auf jedem System wird deshalb meist ein Service gestartet, der über das Eventsystem und API des Docker Daemons vom Starten und Stoppen der Container erfährt und dann die Container-Log-Dateien an einen entfernten Logging-Service sendet. Für viele Log-Cloud-Services und für die Log-Systeme Fluentd, Graylog und logstash existieren entsprechende Lösungen. Eine sehr schlanke und universelle Lösung bietet das Projekt logspout, (Abb. 2). Hier werden alle Container-Logs eingesammelt und können dann entweder mit HTTP/WebSockets beauskunftet oder flexibel via Syslog weitergeleitet werden. Das Projekt lässt sich sehr elegant über Module erweitern. Die Erweiterungen werden dazu mit einem separaten Image Build in das bestehende GO-Projekt einkompiliert. Zur Laufzeit können die Events bestimmter Container dynamisch auf weitere logspout Backends gesendet werden.

Abb. 2: Logging mit logspout umlenken

Abb. 2: Logging mit logspout umlenken

Mehr Verbreitung hat allerdings das Projekt logstash-forwarder zur Umlenkung der Logs in den ELK-Stack hier und hier gefunden. Das ehemalige Projekt lumberjack schickt die Docker-Log-Events über einen verschlüsselten Kanal zu einem logstash Backend, das dann für die Filterung, Transformation und Verteilung der Log-Events zuständig ist. Dies hat den Vorteil, dass alle Log-Events erstmal als Datei für jeden Container gespeichert werden und dann später auf ein zentrales System ausgelagert werden. Ein Kommunikationsproblem oder ein temporären Ausfall des Log Backends kann kompensiert werden. Eine sehr elegante logstash-forwarder-Verwendung bietet das Projekt docker-logstash-forwarder von digtial-wonderland. Die JSON-Logfiles aller Container eines Docker-Hosts werden automatisch registriert und als Konfiguration für den logstash forwarder genutzt. Die Verwendung von Verschlüsslung macht es möglich, dass der Forwarder auch problemlos in der Cloud eingesetzt werden kann. Allerdings gibt es einen Nachteil: Die Berücksichtigung von Containern für die Weiterleitung an logstash, geschieht nur alle 5 Sekunden. Kurzlebige Batches oder Toolstarts finden so nicht sicher den Weg zum zentralen Logsystem. Diese Art Container sollte lieber mit dem Syslog Driver gestartet und die Datei des rsyslog-Containers /var/log/syslog in die statische Konfiguration des docker-logstash-forwarder aufgenommen werden, oder der rsylog-Container leitet dies direkt an den entfernten logstash weiter (Abb. 3).

Abb. 3: Docker-Host-Logging-Stack

Abb. 3: Docker-Host-Logging-Stack

Fazit

Für Java-Entwickler ist es nicht immer einfach, alle Ausgaben eines Prozesses nach stdout oder syslog zu lenken. JEE- und Web-Container-Produkte und die diversen Logging-Frameworks haben hier meist eigene Vorstellungen. Für die zahlreichen Logging-Frameworks sind natürlich Log Backends – wie Console, Dateien, Syslog oder andere Network Backends – verfügbar. Aber beispielsweise im Apache-Tomcat-Projekt ist es nicht vorgesehen, die Ausgaben des AccessLogs nach Stdout umzulenken. In dem infrabricks/tomcat8-Projekt ist eine solche Erweiterung enthalten [1]. Alternativ können Logdateien natürlich in den logstash-forwarder eingebunden werden. Dies hat aber immer eine Konfiguration und einen Restart des logstash-forwarder zur Folge. Eine Konvention beliebige Logfiles aus einem Container einzubinden, besteht noch nicht und der Zugang für den logstash-forwarder muss auch über einen gemeinsamen Data-Container oder Host Volume konfiguriert werden. Problematisch bleibt es, Container mit einer großen Anzahl von Log-Events länger zu betreiben. Aktuell ist noch keine Rotation der Dateien nach Größe oder Zeit für den Docker Log JSON Driver vorgesehen. Natürlich kann dies mit rsyslog und logrotate konfiguriert werden. Für das Logging-System besteht der Wunsch der Community, das neue Docker-Plug-in-System für Docker 1.8 ebenfalls zu nutzen. Es lohnt weiterhin als Java-Entwickler, den Blick auf das Projekt log4j2 und die Anwendung des Graylog-Formats GELF zu verwerfen. Die Verarbeitung vieler paralleler Log-Events, Kontextinformationen oder Stacktraces bleibt also eine Herausforderung. Mit Docker ist es allerdings einfacher, die entsprechende Infrastruktur, auch schon in der Entwicklung herzustellen und wie später im Betrieb zu nutzen.

 

Aufmacherbild: Software Developer von Shutterstock / Urheberrecht: Mclek

Geschrieben von
Peter Roßbach
Peter Roßbach
Peter Roßbach ist ein Infracoder, Systemarchitekt und Berater vieler Websysteme. Sein besonderes Interesse gilt dem Design und der Entwicklung von komplexen Infrastrukturen. Er ist Apache Tomcat Committer und Apache Member. Mit der bee42 solutions gmbh realisiert er Infrastrukturprodukte und bietet Schulungen auf der Grundlage des Docker-Ökosystems, aktuellen Webtechnologien, NoSQL-Datenbanken und Cloud-Plattformen an.
Kommentare

Hinterlasse einen Kommentar

1 Kommentar auf "Docker rockt Java: Wie Sie die Docker-Logging-Plug-ins verwenden"

avatar
400
  Subscribe  
Benachrichtige mich zu:
Jochen
Gast

> Es lohnt weiterhin als Java-Entwickler, den Blick auf […] die Anwendung des Graylog-Formats GELF zu verwerfen.

Selbstverständlich nicht nur als Java-Entwickler, aber die Integration in praktisch alle gängigen Logging Frameworks auf der JVM macht es einfacher (https://marketplace.graylog.org/addons?tag=java). 😉

Außerdem bringt Docker seit Version 1.8.0 von Haus aus einen GELF Logging Driver mit, durch den automatisch Container-spezifische Informationen (wie etwa das verwendete Image, die Container ID oder der Name des Docker Hosts) mitgeschickt und durch geeignete Tools nutzbar gemacht werden können.

Unter https://www.graylog.org/centralize-your-docker-container-logging-with-graylog-native-integration/ gibt es einen kleinen Einführungsartikel dazu.