Jak wysyłać dzienniki w architekturze mikroserwisu za pomocą docker?

Heroku opisuje logi w swoim manifest aplikacji Dwunastofaktowej jako proste strumienie zdarzeń:

Logi to strumień zagregowanych, uporządkowanych w czasie zdarzeń zebranych ze strumieni wyjściowych wszystkich uruchomionych procesów i usług wspierających. Dzienniki w ich surowej formie są zazwyczaj formatem tekstowym z jednym zdarzeniem na wiersz (choć ścieżki zwrotne od WYJĄTKÓW mogą obejmować wiele wierszy). Dzienniki nie mają stałego początku ani końca, ale przepływają w sposób ciągły tak długo, jak długo aplikacja jest działa.

Dodatkowo aplikacje powinny po prostu zapisywać logi do stdout, pozostawiając zadanie "środowisku".

Aplikacja dwunastofaktowa nigdy nie zajmuje się routingiem ani przechowywaniem strumienia wyjściowego. Nie powinien próbować zapisywać lub zarządzać plikami dziennika. Zamiast tego, każdy uruchomiony proces zapisuje swój strumień zdarzeń, niebuforowany, na stdout. Podczas rozwoju lokalnego programista będzie oglądał ten strumień na pierwszym planie swojego terminala, aby obserwować zachowanie aplikacji.

In każdy strumień procesu będzie przechwytywany przez środowisko wykonawcze, zestawiany ze wszystkimi innymi strumieniami z aplikacji i kierowany do jednego lub więcej miejsc docelowych w celu wyświetlenia i długoterminowej archiwizacji. Te cele archiwalne nie są widoczne ani konfigurowalne przez aplikację, a zamiast tego są całkowicie zarządzane przez środowisko wykonawcze. W tym celu dostępne są routery typu Open source (takie jak Logplex i Fluent).

Więc co jest najlepsze jak osiągnąć to w środowisku docker pod względem niezawodności, wydajności i łatwości obsługi? Myślę, że na myśl przychodzą następujące pytania:

  • czy można polegać na własnym logu Dockera (docker logs)?
  • czy uruchamianie Dockera bez odczytu i uważanie jego wyjścia za strumień logowania jest bezpieczne?
  • czy stdout można przekierować bezpośrednio do pliku (miejsca na dysku)?
  • Jeśli używasz pliku, czy powinien on znajdować się wewnątrz obrazu dokera czy woluminu związanego (docker run --volume=[])?
  • jest wymagane logrotacje?
  • czy bezpieczne jest przekierowanie stdout bezpośrednio do logshippera (i który logshipper)?
  • czy nazwa rury (aka FIFO) jest opcją?
  • (więcej pytań?)
Author: Community, 2014-07-17

1 answers

Docker 1.6 wprowadził pojęcie sterowników rejestrujących, aby zapewnić większą kontrolę nad wyjściami dziennika. Flaga --log-driver konfiguruje, gdzie stdout & stderr z procesu uruchomionego w kontenerze powinny być kierowane. Zobacz także Konfigurowanie sterowników logowania .

Dostępnych jest kilka sterowników. Zauważ, że wszystkie z nich z wyjątkiem json-file wyłączają używanie docker logs do gromadzenia dzienników kontenerów.

  • none-wyłącz logi kontenerów.
  • json-file-zachowuje się jak wcześniej, z JSON sformatowanym stdout dostępnym w /var/lib/docker/containers/<containerid>/<containerid>-json.log
  • syslog-zapisuje wiadomości do sysloga. Przyjmuje również --log-opt do kierowania komunikatów dziennika do określonego sysloga przez gniazdo TCP, UDP lub domeny Unix. Wyłącza również docker logs
  • journald-pisze do dziennika systemd.
  • *gelf-Graylog Extended Log Format (GELF). Zapisuje komunikaty dziennika do punktu końcowego GELF, takiego jak Graylog lub Logstash
  • *fluentd-wysyłanie logów kontenera do fluentd. Akceptuje niektóre opcje dostosowywania adresu fluentd i wysyłania znaczników z wiadomościami dziennika.
  • **awslogs-zapisuje komunikaty logów do dzienników AWS CloudWatch

* nowy w Docker 1.8

** nowy w Docker 1.9

Na przykład:

docker run --log-driver=syslog --log-opt syslog-address=tcp://10.0.0.10:1514 ...

Jest to Docker-zalecane rozwiązanie dla oprogramowania, które zapisuje swoje komunikaty dziennika do stdout & stderr. Jednak niektóre programy nie zapisują logów do stdout/stderr. Zamiast tego zapisują do plików logów lub do na przykład syslog. W takich przypadkach nadal obowiązują niektóre szczegóły z oryginalnej Odpowiedzi poniżej. Podsumowanie:

Jeśli aplikacja zapisuje do lokalnego pliku dziennika, zamontuj wolumin z hosta (lub użyj kontenera tylko do danych do kontenera i zapisz wiadomości dziennika w tej lokalizacji.

Jeśli aplikacja zapisuje się do syslog, istnieje kilka opcji:]}
  • wysyłanie do sysloga hosta przez zamontowanie gniazda syslog hosta (/dev/log) do kontenera za pomocą -v /dev/log:/dev/log.
  • jeśli aplikacja akceptuje punkt końcowy syslog w swojej konfiguracji, konfiguruje demona syslog hosta do nasłuchiwania przez TCP i / lub UDP w sieci Docker bridge i używa tego punktu końcowego. Lub po prostu wyślij do zdalnego hosta syslog.
  • Uruchom demona syslog w kontenerze i użyj linków Dockera, aby uzyskać dostęp do niego z innych uruchomionych kontenerów.
  • Dzięki temu, że kontener jest używany do wysyłania logów do zdalnego sysloga przez UDP, można go używać do wysyłania logów.]}

Nie zapominaj, że wszelkie logi w kontenerze powinny być obracane tak, jak na systemie operacyjnym hosta.


Oryginalna odpowiedź dla Docker pre-1.6

Czy można polegać na własnym logu Dockera (Docker logs)?

docker logs drukuje cały strumień za każdym razem, a nie tylko nowe dzienniki, więc nie jest to właściwe. docker logs --follow da funkcjonalność podobną do tail -f, ale wtedy masz polecenie docker CLI działające cały czas. Tak więc, chociaż jest to bezpieczne do uruchomienia docker logs, to nie jest optymalne.

Czy jest bezpiecznie uruchomić Dockera bez odczytu i uznać jego wyjście za strumień logowania?

Możesz uruchamiać kontenery z systemd, a nie demonizować, przechwytując w ten sposób wszystkie stdout w dzienniku systemd, które następnie mogą być zarządzane przez host, jak chcesz.

Czy stdout można przekierować bezpośrednio do pliku (miejsca na dysku)?

Możesz to zrobić oczywiście za pomocą docker run ... > logfile, ale wydaje się kruche i trudniejsze do zautomatyzowania i zarządzania.

Jeśli używasz pliku, czy powinien być wewnątrz obrazu dokera czy woluminu związanego (docker run --volume=[])?

Jeśli piszesz wewnątrz kontenera, musisz uruchomić logrotate lub coś w kontenerze, aby zarządzać plikami dziennika. Lepiej zamontować wolumin z hosta i kontrolować go za pomocą demona obrotu dziennika hosta.

Czy wymagana jest logrotacja?

Oczywiście, jeśli aplikacja pisze dzienniki, musisz je obrócić tak, jak w natywnym środowisku systemu operacyjnego. Ale jest trudniej, jeśli Zapisz wewnątrz kontenera, ponieważ lokalizacja pliku dziennika nie jest tak przewidywalna. Jeśli obrócisz się na hoście, plik dziennika będzie mieszkał pod nim, na przykład z devicemapper jako sterownikiem pamięci, /var/lib/docker/devicemapper/mnt/<containerid>/rootfs/.... Potrzebny byłby jakiś brzydki wrapper, żeby logrotate znalazł logi pod tą ścieżką.

Czy bezpieczne jest przekierowanie stdout bezpośrednio do logshippera (i który logshipper)?

Lepiej użyć syslog i pozwolić, aby kolektor logów zajmował się syslogiem.

Jest o nazwie pipe (aka FIFO) opcja?

Nazwana rura nie jest idealna, ponieważ jeśli koniec odczytu rury umrze, pisarz (Pojemnik) dostanie zepsutą rurę. Nawet jeśli to zdarzenie jest obsługiwane przez aplikację, zostanie ono zablokowane, dopóki nie pojawi się ponownie czytnik. Dodatkowo omija docker logs.

Zobacz również ten post na fluentd z Dockerem.

Zobacz Narzędzie Jeffa Lindsaya logspout które zbiera logi z uruchomionych kontenerów i przekierowuje je niezależnie od tego, chcę.

Na koniec zauważ, że stdout z kontenera loguje się do pliku na hoście w /var/lib/docker/containers/<containerid>/<containerid>-json.log.

 28
Author: Ben Whaley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-05 15:17:33