Das Bereitstellen von Anwendungen ist eine zentrale Administrationsaufgabe und Fehler hierbei fallen Mitarbeitern wie Kunden unmittelbar auf. Eine wichtige ... (mehr)

Webserver im Container

Als Testapplikation nutzt unser Setup einen Nginx-Container. Dessen Konfiguration erzeugen wir unter "/root/docker/ nginx", wie zuvor beschrieben mit »docker-compose.yml.« Genau genommen sollte auch hier eine ENV-Datei die Umgebung deklarieren, aber für unser einfaches Beispiel haben wir einfach alles direkt in das Compose-File geschrieben. Dazu gibt es einen Ordner "./config" mit einer sehr simplen Datei "site.conf", in der nur das Folgende steht:

server {
      index index.html;
      root /www;

 

}

Ebenfalls unter "/root/docker/nginx/" befindet sich das Verzeichnis "./www" mit einer ganzen Website oder zumindest einer Datei "index.html", die der Nginx-Server darstellen kann. Dazu lautet die passende Datei "Docker-compose.yml":

version: "3"
services:
      nginx-example:
            image: nginx:1.13-alpine
            ports:
                 - "8002:80"
           volumes:
                  - ./www:/www
                  - ./config/site.conf:/etc/nginx/conf.d/default.conf

Neben dem Verzeichnis für die Webserver-Daten blendet Docker die Konfigurationsdatei in die Umgebung ein. Das genügt für unser simples Beispiel.

Bei einem echten Setup würde der Administrator das komplette Verzeichnis "conf.d" mit allen Konfigurationsdateien anbinden:

logging:
      driver: fluentd
      options:
            fluentd-address: localhost:24224
            fluentd-async-connect: 'true'
            fluentd-retry-wait: '1s'
            fluentd-max-retries: '30'
            tag: web.nginx

Den mitgegebenen Tag wird Fluentbit später für die Auswertung nutzen. Starten Sie nun per »docker-compose up« den Nginx-Server, können Sie per "localhost:8002" auf dessen Homepage gehen.

Die Logausgaben des Nginx-Servers erscheinen in "Elasticsearch/Kibana", aber die interessanten Nginx-Loginformationen stecken, wie Bild 1 verdeutlicht, unqualifiziert im "Log"-Feld.

Filter, Parser und Regular Expressions

Theoretisch sollte es nun ausreichen, in der Konfiguration von Fluentd zwischen Input und Output einen passenden Filter einzubauen, der das Logfeld im Nginx-Format auseinandernimmt. Dazu würde in die Datei "fluent-bit.conf" folgender Block hinzukommen:

[FILTER]
      Name parser
      Match web.nginx
      Key_Name log
      Parser nginx
      Reserve_data On

Im Klartext: Fluentd nimmt alle Loginformationen mit dem Tag "web.nginx" und schlüsselt das Feld "log" mit dem Parser "nginx" auf. Die Konfiguration des Parsers Nginx findet sich, unter vielen anderen, in der Datei "parsers.conf" aus dem Github-Repository von Fluentbit.

Nach dem gleichen Prinzip ließen sich dann die Loginformationen anderer Dienste wie Apache, Postgress, PHP-FPM oder MySQL taggen und mit dem passenden Parser zerlegen. In der Praxis funktioniert das Ganze aber leider nicht so einfach, wie es die Dokumentation von Fluentbit verspricht. Die Regular Expression, die der Nginx-Parser aus "parsers.conf" verwendet, passt leider gar nicht zu dem, was unser Nginx-Container in das "log"-Feld schreibt. Das bedeutet, Sie müssen die Regular Expression des Parsers modifizieren – eine Horrorvision vieler Administratoren.

Um den Schmerz bei der Arbeit mit Regular Expressions zu mindern, gibt es die Website [3]. Dort lassen sich Regular Expressions online erstellen und gleich ausprobieren. Mit Hilfe dieses Online-Tools (und sehr viel Geduld) modifizieren Sie die Regular Expression des Nginx-Filters so weit, dass sie für das vorliegende Beispiel passt.

Listing: parsers.conf



[PARSER]
      Name ng2
      Format regex
      Regex ^(?<remote>[^ ]*) - - \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*) "(?<referencer>[^\"]*)" "(?<agent>[^\"]*)"
      Time_Format %d/%b/%Y:%H:%M:%S %z
      Time_Keep Off
      Time_Key log_time

Heraus kommt, wie im gleichnamigen Listing-Kasten ersichtlich, ein neuer Parser in "parsers.conf". Der ist zwar auch nicht perfekt (da er einfach zwei Datenfelder nach der Client-IP und zusätzliche Daten nach dem Agent ignoriert), funktioniert aber für unser Workshop-Beispiel.

Um die Logs noch besser voneinander zu trennen, lassen wir Fluentbit ferner die Daten in separate Indizes schreiben, sodass die Konfiguration in der Datei "fluent-bit.conf" am Ende so aussieht:

[SERVICE]
      Flush 5
      Daemon Off
      Log_Level debug
      Parsers_File parsers.conf
[INPUT]
      Name forward
      Tag *
      Listen 0.0.0.0
      Port 24224

Bis hierhin unverändert – aber die Datei "parsers.conf" enthält den oben erwähnten ng2-Eintrag:

[FILTER]
      Name parser
     Match web.nginx
     Key_Name      log
     Parser ng2
       Reserve_data      On

Der Filter verweist auf den selbst geschriebenen Parser in der parsers.conf:

[OUTPUT]
      Name es
      Match container.*
      Host <IP-Adresse des Hosts>
      Port 9200
      Index bit_docker.0
      Type docker

Die Logs des EFK-Stacks selbst (getagt mit "container.elastic" und "container.kibana") landen im Index "bit_docker.0":

[OUTPUT]
      Name es
      Match web.nginx
      Host <IP-Adresse des Hosts>
      Port 9200
      Index bit_nginx.0
Type docker

Die Logs des Webservers hingegen finden jetzt in einen eigenen Index namens "bit_nginx.0" Platz. Der neu gestartete EFK-Stack wertet im Anschluss die Loginformationen des Webservers detailliert aus (Bild 3).

Sie werden jedoch kaum darum herumkommen, sich mit angepassten und eigenen Regular Expressions auseinanderzusetzen. Während der Debug-Phase der eigenen Parser brauchen Sie dann gar nicht den kompletten EFK-Stack zu starten. Hier genügt ein einzelner Fluentbit-Container mit der Output-Option

[OUTPUT]
      Name stdout
      Match <mein.tag>

Dabei gibt Fluentbit die qualifizierten Logdaten im JSON-Format auf der Kommandozeile der Docker-Compose-Shell aus, sodass Sie direkt sehen, ob und wie Ihr Parser funktioniert.

comments powered by Disqus

Artikel der Woche

Eigene Registry für Docker-Images

Wer selber Docker-Images herstellt, braucht auch eine eigene Registry. Diese gibt es ebenfalls als Docker-Image, aber nur mit eingeschränkter Funktionalität. Mit einem Auth-Server wird daraus ein brauchbares Repository für Images. (mehr)
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Google+

Ausgabe /2019