Přejít k navigační liště

Zdroják » Různé » Sběr logů z kontejnerů

Sběr logů z kontejnerů

Články Různé

Vaše aplikace běží pomocí Dockeru na několika serverech a automaticky se škálují. Jak z nich ale dostat logy? SSH, tail a grep jsou téměř nepoužitelné. Podívejte se, jak nakonfigurovat a spustit ELK stack.

ELK je zkratka pro Elastic Search, Logstash, Kibana:

  • Elastic Search je distribuovaný vyhledávací engine,
  • Logstash je nástroj pro směrování zpráv, a
  • Kibana je HTML rozhraní pro zobrazování dat z Elastic Search.

ELK stack je řešením pro problémy s logy: všechny zprávy posíláte na jedno místo, ale díky Elastic Search dobře škálují. V Kibaně si můžete prohlížet grafy, nebo si přímo z API Elastic Search tahat data ve formátu JSON.

Jak připojit kontejnery na ELK? Pomocí Logspout

Logspout je nástroj pro sběr a směrování logů z kontejnerů. Díky adaptéru logspout-logstash je připojení na Logstash jednoduché. Stačí jenom na každém serveru spustit jeden kontejner navíc, který se už o vše další postará sám.

Co musí aplikace a kontejnery umět

Aby se logy správně dostaly zevnitř kontejnerů do Logspout a dál, je potřeba splnit dvě podmínky:

  • Veškeré zprávy jsou zapisované na STDOUT a STDERR: tedy žádné soubory. Jestliže nemůžete výstup aplikace ovlivnit, můžete použít například nástroj dockerize.
  • Kontejnery s aplikací musí být spuštěné bez parametru -t.

Jak spustit ELK stack

Nejjednodušší je použít předpřipravený Docker image: pblittle/docker-logstash. Na stránce projektu je několik příkladů, jak image použít, ale chybí ten pro nás nejpodstatnější: vstup pomocí syslogu. Právě ten totiž používá i Logspout.

Musíte si tak vytvořit vlastní konfigurační soubor a v něm příslušné rozhraní otevřít. Dokumentace Logstash popisuje všechny možnosti, zde je minimální ukázka souboru conf.d/logstash.conf:

input {
  tcp {
    port => 5000
    type => syslog
  }
  udp {
    port => 5000
    type => syslog
  }
}
filter {
  if [type] == "syslog" {
    json {
      source => "message"
    }
  }
}
output {
  elasticsearch {
    embedded => true
    host => "127.0.0.1"
    port => "9200"
    protocol => "http"
  }
}

Při spouštění kontejneru pak musíte tento soubor připojit pomocí volume a zároveň otevřít příslušné porty: 5000 pro vstup logů, 9200 pro API Elastic Search, a 9292 pro rozhraní Kibany.

docker run \
  --volume $(pwd)/conf.d:/opt/logstash/conf.d \
  -p 5000:5000 \
  -p 5000:5000/udp \
  -p 9292:9292 \
  -p 9200:9200 \
  -p 9292:9292 \
  pblittle/docker-logstash

Jestliže se vše povedlo, uvidíte výstupy, prozatím prázdné:

  • http://localhost:9200/: Verze Elastic Search
  • http://localhost:9200/_search: Logy ve formátu JSON
  • http://localhost:9292/: Grafické rozhraní Kibany

Jestliže používáte boot2docker, namísto localhost použijte adresu z boot2docker ip: u mě je to 192.168.59.103.

Jak spustit Logspout

Pro Logspout taky existuje připravený Docker image: gliderlabs/logspout. Ten ale nemá nainstalovaný adaptér pro logstash. Naštěstí je instalace jednoduchá. Nejdřív si vytvořte vlastní soubor modules.go, kde sepíšete všechny pluginy, které budete potřebovat. Může vypadat třeba takhle:

package main

import (
 _ "github.com/gliderlabs/logspout/transports/tcp"
 _ "github.com/gliderlabs/logspout/transports/udp"
 _ "github.com/looplab/logspout-logstash"
)

Potom ve stejném adresáři vytvořte Dockerfile s jediným příkazem, FROM:

FROM gliderlabs/logspout:master

Nezapomeňte použít tag :master! Bez něj se nespustí kompilace.

Pak už stačí jenom vytvořit image. Kompilační skript si sám najde modules.go, nakopíruje ho dovnitř kontejneru a stáhne si moduly z githubu. Kontejner můžete hned spustit:

docker build -t zdrojak/logspout .
docker run -d \
  -v /var/run/docker.sock:/tmp/docker.sock \
  zdrojak/logspout \
  logstash://localhost:5000

Pak už můžete spustit libovolný další kontejner:

docker run --rm ubuntu echo "Hello, Kibana"

Výsledek uvidíte v Kibaně:

Co se do článku už nevešlo

  • Škálování: Elastic Search se umí roztáhnout přes víc serverů
  • Parsování příchozích zpráv: můžete použít například grok. Konfigurovat budete v souboru logstash.conf
  • Promazávání logů kontejnerů: Docker uchovává logy na věky věků. V budoucnu se to pravděpodobně změní (viz #7333 a #8911), ale prozatím to můžete vyřešít například pomocí logrotate.

Alternativní přístup

Mnou popsané řešení není jediné. S následujícími ale nemám zkušenosti a budu rád, když se o ty svoje podělíte v komentářích!

Komentáře

Subscribe
Upozornit na
guest
7 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Sniper

Hoj,
podobnej setup pouzivame uz par mesicu a funguje to dobre (akorat misto logsprout tam mame logstash-forwarder). Pri nasazovani ale pozor na jednu dulezitou vec – elasticsearch neumi zadnou podobu autorizace a autentizace a kibana to moc neresi. Je potreba udelat na logovacim serveru http proxy, ktera se postavi mezi ES server a kibanu. Jinak si muze kdokoliv, kdo otevre kibanu, cist jakykoliv logy a to nechceme.

wsh

My jsme po dlouhém zvažování, jestli rozjíždět vlastní ELK a přidávat si další věc k udržování, zvolili nakonec hostované řešení. Možností je víc, ale vyhrálo Loggly. Pro běžné logy jako je Apache je podpora rovnou, pro naše aplikace používáme buď knihovny do příslušný jazyků nebo přeposílání přes syslog. UI je sice dost pomalé, ale práce s logy se dostala na úplně jinou úroveň díky filtrování a hlavně agregaci. Zjistit jestli nějaká událost vzniká na jednom serveru, určitém regionu nebo třeba jen pro určitého zákazníka, jak často je otázka pár kliknutí.

msgre

Ahoj Petře,
jak moc „ukecané“ máte jednotlivé kontejnery?

Používáme Docker & CoreOS a stalo se nám, že po jednotkách dní nám začal leakovat docker daemon. Nejdříve jsme podezřívali hladovou Javu, ale po podrobnějším prozkoumání to vypadá spíš na kontejnery, které do stdout-u logují hodně hlášek (cca desítky hlášek za vteřinu).

Nezaznamenal jsi náhodou podobné problémy?

David

Ahoj,

nedavno jsem ELK stack rozjizdel u nas. Kvuli skalovani jsem si dal Logstash do docker kontejneru, Kibanu do kontejneru a elesticsearch jako cluster. Problem je, ze jak logstash, tak kibana pro efektivni fungovani spusti vlastni instanci elasticsearchu, ta nema data a komunikuje s ES cluster pres port 9300 obousmerne. Problem mam, ze jsem logstash se prihlasi na ES cluster, ale nahlasi mu IP, kterou ES spusteny logstashem vidi uvnitr kontejneru a ne tu, kterou ma HOST. Vim, ze to jde obejit tim, ze se zmeni nastaveni na logstash, aby byl jen v rezimu transport (param protocol) a nespoustel ES instanci, ale je to mene efektivni. Kibana je take rychlejsi, kdyz ma ES node bez dat u sebe, nez kdyz se napojuje na jiny ES server. Prosim o radu, z dokumentace jsem to nevycetl: http://logstash.net/docs/1.4.2/outputs/elasticsearch . Moc dekuji

msgre
David

Ahoj, to by pomohlo. Jenze s tim ma zas problem marathon :-)

Luděk

S logspoutem a ELK stackem jsem si hral a dal jsem dohromady docker-compose.yml, ktery spusti jak ELK stack tak logspout – jak se k nemu dostat jsem sepsal na svem webu, muze to poslouzit jako inspirace.
Pokud je problem s vykonem u „ukecanych kontejneru“, muze to souviset s tim, ze ve vychozim stavu docker loguje jako JSON do souboru. Resenim by mohlo byt pouzit jiny logovaci driver a do souboru vubec nezapisovat.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.