2015-10-30 33 views
16

Ho una serie di applicazioni ancorate su più server e cerco di configurare la registrazione centralizzata a livello di produzione con ELK. Sto bene con la parte ELK stessa, ma sono un po 'confuso su come inoltrare i log ai miei logstashes. Sto cercando di usare Filebeat, a causa della sua funzione loadbalance. Vorrei anche evitare di riempire Filebeat (o qualsiasi altra cosa) in tutte le mie finestre mobili, e tenerlo separato, messo in bacino o meno.Registrazione di app Docker con Filebeat e Logstash

Come posso procedere?

Ho provato quanto segue. I miei Docker eseguono l'accesso su stdout, quindi con un filebeat non ancorabile configurato per leggere dallo stdin, faccio:

log docker -f mycontainer | ./filebeat -e -c filebeat.yml

Sembra funzionare all'inizio. I primi registri vengono inoltrati al mio logstash. Quello in cache credo. Ma a un certo punto si blocca e continua a inviare lo stesso evento

E 'solo un bug o sono diretto nella direzione sbagliata? Quale soluzione hai installato?

+0

Ho appena provato la stessa cosa con il vecchio logstash-forwarder: log docker -f mycontainer | ./logstash-forwarder_linux_amd64 -config forwarder.conf E funziona. Ho il sospetto di un bug di Filebeat. L'unico problema rimane che c'è solo una connessione casuale a un logstash senza bilanciamento del carico. – Gianluca

+0

Quale versione di filebeat stai usando? Questo sembra un potenziale bug. Sentiti libero di aprire un problema [qui] (https://github.com/elastic/filebeat/issues) in modo che possiamo analizzare più a fondo il problema. Per riferimento: alcune discussioni aggiuntive sull'implementazione della finestra mobile possono essere trovate qui: https://github.com/elastic/libbeat/issues/37 – ruflin

risposta

5

Docker consente di specificare il logDriver in uso. Questa risposta non interessa Filebeat o il bilanciamento del carico.

In una presentazione che ho usato syslog per inoltrare i registri a un'istanza Logstash (ELK) in ascolto sulla porta 5000. Il comando seguente invia costantemente messaggi attraverso syslog per Logstash:

docker run -t -d --log-driver=syslog --log-opt syslog-address=tcp://127.0.0.1:5000 ubuntu /bin/bash -c 'while true; do echo "Hello $(date)"; sleep 1; done' 
+0

Ho dato un'occhiata al logDriver ma per quanto riguarda la disponibilità elevata? Avrò bisogno di un bilanciamento del carico TCP per indirizzare le richieste al mio cluster logstash? – Gianluca

+0

Non sono sicuro della scala del tuo sistema. Usando ~ 200 produttori di log (il comando nella mia risposta) non ho notato alcun problema. Tuttavia non ho pensato alla disponibilità elevata o al bilanciamento del carico/clustering. – michaelbahr

+0

Non sono preoccupato per la quantità di log, è la disponibilità di logstash. Ho bisogno di almeno 2 o 3 di loro per garantire una buona tolleranza agli errori, e quindi alcuni meccanismi per passare da uno all'altro. – Gianluca

16

Ecco un modo per inoltrare docker logs alla pila ELK (richiede finestra mobile> = 1.8 per il driver di log GELF):

  1. Avviare un contenitore Logstash con il gelf input plugin per legge da GELF e uscite a un elasticsearch h host (ES_HOST: porta):

    docker run --rm -p 12201:12201/udp logstash \ 
        logstash -e 'input { gelf { } } output { elasticsearch { hosts => ["ES_HOST:PORT"] } }' 
    
  2. Ora iniziamo un contenitore Docker e utilizzare il gelf Docker logging driver. Ecco un esempio stupido:

    docker run --log-driver=gelf --log-opt gelf-address=udp://localhost:12201 busybox \ 
        /bin/sh -c 'while true; do echo "Hello $(date)"; sleep 1; done' 
    
  3. Caricare fino Kibana e le cose che hai atterrato in docker logs sono ora visibili. Il gelf source code mostra che alcuni campi a portata di mano sono generati per voi (cappello-punta: Christophe Labouisse): _container_id, _container_name, _image_id, _image_name, _command, _tag, _created.

Se si utilizza finestra mobile-composizione (assicurarsi di utilizzare finestra mobile-Compose> = 1.5) e aggiungere le impostazioni appropriate in docker-compose.yml dopo aver iniziato il contenitore logstash:

log_driver: "gelf" 
log_opt: 
    gelf-address: "udp://localhost:12201" 
+3

Penso che il problema con gelf sia l'utilizzo di udp e la possibilità di eliminare gli eventi di registro in modo silenzioso. – urso

+3

Buon punto, @urso. Il driver di registrazione 'syslog' può essere utilizzato in modo simile per distribuire i registri tramite TCP [ecco un esempio] (https://github.com/edefaria/docker-logstash). I documenti [Graylog Extended Format (GELF)] (https://www.graylog.org/resources/gelf/) menzionano potenziali problemi usando TCP in contrasto con UDP che droppano silenziosamente gli eventi di registrazione. – Pete

7

Utilizzando filebeat si può solo pipe docker logs output come hai descritto. Il comportamento che si sta vedendo suona sicuramente come un bug, ma può anche essere la configurazione a riga di lettura parziale che ti colpisce (invia nuovamente le linee parziali finché non viene trovato il simbolo di nuova riga).

Un problema che vedo con le tubazioni è la contropressione possibile nel caso in cui non sia disponibile logstash. Se filebeat non può inviare eventi, memorizzerà gli eventi internamente e ad un certo punto interromperà la lettura da stdin. Nessuna idea di come/se la finestra mobile protegge dallo stdout che non risponde. Un altro problema con le tubature potrebbe essere il comportamento di riavvio di filebeat + docker se si utilizza la finestra mobile-compose. docker-compose di default riutilizza immagini + stato immagine. Quindi quando si riavvia, spedirai di nuovo tutti i vecchi log (dato che il file di log sottostante non è ancora stato ruotato).

Invece di eseguire il piping, è possibile provare a leggere i file di registro scritti dalla finestra mobile sul sistema host. Il driver di registro docker predefinito è json log driver. È possibile e necessario configurare il driver di registrazione di json per eseguire la rotazione dei log + mantenere alcuni vecchi file (per il buffering su disco). Vedi le opzioni max-size e max-file. Il driver json mette una riga di dati "json" per ogni riga da registrare. Sul sistema host della finestra mobile i file di registro vengono scritti in /var/lib/docker/containers/container_id/container_id-json.log. Questi file verranno inoltrati da filebeat a logstash. Se logstash o rete non sono disponibili o filebeat viene riavviato, continua a inoltrare le righe di registro da cui è rimasto (i file dati non sono stati cancellati a causa della rotazione del registro). Nessun evento sarà perso. Nel logstash è possibile utilizzare il codec o il filtro json_lines per analizzare le linee json e un filtro grok per ottenere ulteriori informazioni dai log.

C'è stato some discussion sull'utilizzo di libbeat (utilizzato da filebeat per i file di registro di spedizione) per aggiungere un nuovo driver di registro alla finestra mobile. Forse è possibile raccogliere i registri tramite dockerbeat in futuro utilizzando la finestra di dialogo dei registri dock (tuttavia, non sono a conoscenza di piani per l'utilizzo dell'API dei registri).

L'utilizzo di syslog è anche un'opzione. Forse è possibile ottenere un relè syslog sugli eventi del registro di bilanciamento del carico dell'host di docker. Oppure avere syslog scrivere i file di log e usare filebeat per inoltrarli. Penso che rsyslog abbia almeno una modalità di failover. È possibile utilizzare il plug-in di input syslog di logstash e rsyslog per inoltrare i registri al logstash con il supporto di failover nel caso in cui l'istanza di logstash attiva non sia disponibile.

+0

Re json-file, https://github.com/moby/moby/issues/17763 indica che i file json docker sono considerati dati interni e non destinati a essere utilizzati da altri processi. –

0

Solo per aiutare gli altri che hanno bisogno di fare questo, si può semplicemente utilizzare Filebeat per spedire i registri. Vorrei usare il contenitore di @ brice-argenson, ma avevo bisogno del supporto SSL quindi sono andato con un'istanza Filebeat installata localmente.

Il cercatore da filebeat è (ripetizione per più contenitori):

- input_type: log 
    paths: 
    - /var/lib/docker/containers/<guid>/*.log 
    document_type: docker_log 
    fields: 
    dockercontainer: container_name 

fa schifo un po 'che è necessario conoscere i GUID come potrebbero cambiare gli aggiornamenti.

Sul server logstash, messa a punto la solita fonte di ingresso filebeat per logstash, e utilizzare un filtro come questo:

filter { 
    if [type] == "docker_log" { 
    json { 
     source => "message" 
     add_field => [ "received_at", "%{@timestamp}" ] 
     add_field => [ "received_from", "%{host}" ] 
    } 
    mutate { 
     rename => { "log" => "message" } 
    } 
    date { 
     match => [ "time", "ISO8601" ] 
    } 
    } 
} 

Ciò analizzare il JSON dai registri finestra mobile, e impostare il timestamp a quello riportato di Docker.

Se stai leggendo i log dall'immagine Docker nginx, è possibile aggiungere questo filtro così:

filter { 
    if [fields][dockercontainer] == "nginx" { 
    grok { 
     match => { "message" => "(?m)%{IPORHOST:targethost} %{COMBINEDAPACHELOG}" } 
    } 
    mutate { 
     convert => { "[bytes]" => "integer" } 
     convert => { "[response]" => "integer" } 
    } 
    mutate { 
     rename => { "bytes" => "http_streamlen" } 
     rename => { "response" => "http_statuscode" } 
    } 
    } 
} 

Converti/rinomina sono opzionali, ma fissa una svista nella COMBINEDAPACHELOG espressione in cui non gettato questi valori ai numeri interi, rendendoli non disponibili per l'aggregazione in Kibana.

+0

Grazie per questo! Per quanto riguarda il tuo suggerimento sui GUID, sono d'accordo, tuttavia probabilmente non vorrai fare una configurazione come questa a mano, ma piuttosto usare qualcosa come Ansible. Quindi solo "docker ps | grep container_name | awk '{print $ 1}'", quindi maschera il risultato nella configurazione e riavvia filebeat. –

+0

Secondo i documenti, dovresti essere in grado di utilizzare un modello come questo nei tuoi prospectors.path: '/ var/lib/docker/containers/*/*. Log' – erewok

0

ho verificato cosa erewok scritto sopra in un commento:

Secondo la documentazione, si dovrebbe essere in grado di utilizzare un modello come questo nei tuoi prospectors.paths:/var/lib/docker/contenitori /*/*.log - erewok 18 apr alle 21:03

finestra mobile contenitore GUID, rappresentato come il primo '*', siano correttamente risolto quando filebeat avvia. Non so cosa succede quando vengono aggiunti i contenitori.