Подтвердить что ты не робот

Как отправлять журналы в микросервисной архитектуре с помощью докеров?

Heroku описывает журналы в своем Twelve-Factor App manifest как простые потоки событий:

Журналы - это поток агрегированных, упорядоченных по времени событий, собранных из выходных потоков всех запущенных процессов и вспомогательных служб. Журналы в их исходной форме обычно представляют собой текстовый формат с одним событием на строку (хотя обратные трассировки из исключений могут охватывать несколько строк). Журналы не имеют фиксированного начала или конца, но поток непрерывно, пока приложение работает.

Кроме того, приложения должны просто записывать журналы на stdout, оставляя задачу в "среде".

Приложение с двенадцатью фактором никогда не касается маршрутизации или хранения его выходного потока. Он не должен пытаться писать или управлять лог файлами. Вместо этого каждый запущенный процесс записывает поток событий, небуферизованный, в стандартный вывод. Во время локального развития разработчик будет рассматривать этот поток на переднем плане своего терминала, чтобы наблюдать за поведением приложений.

В процессе развертывания или производства каждый поток процесса будет захвачен средой исполнения, сопоставлен со всеми другими потоками из приложения и маршрутизирован в один или несколько конечных пунктов назначения для просмотра и долгосрочного архивирования. Эти архивные адресаты не отображаются или не настраиваются приложением, а полностью управляются средой исполнения. Для этой цели доступны маршрутизаторы журналов с открытым исходным кодом (такие как Logplex и Fluent).

Итак, что лучший способ достичь этого в докерной среде с точки зрения надежности, эффективности и простоты использования? Думаю, на ум приходят следующие вопросы:

  • Можно ли полагаться на собственный журнал Docker (docker logs)?
  • Можно ли безопасно запускать докеры и рассматривать его вывод как поток ведения журнала?
  • Может ли stdout перенаправляться непосредственно на файл (дисковое пространство)?
  • Если вы используете файл, он должен находиться внутри изображения докеры или связанного тома (docker run --volume=[])?
  • Требуется ли лотрование?
  • Безопасно ли перенаправить stdout прямо в logshipper (и какой logshipper)?
  • Есть ли именованный канал (aka FIFO) вариант?
  • (больше вопросов?)
4b9b3361

Ответ 1

Docker 1.6 представил понятие протоколирование драйверов в больше контроля над выходом журнала. Флаг --log-driver настраивает, где stdout и stderr из процесса, запущенного в контейнере, должны быть направлены. См. Также Настройка драйверов ведения журнала.

Доступны несколько драйверов. Обратите внимание, что все из них, кроме json-file, отключают использование docker logs для сбора журналов контейнеров.

  • none - отключить журналы контейнеров.
  • json-file - работает так же, как и ранее, с форматированным форматированием json в /var/lib/docker/containers/<containerid>/<containerid>-json.log
  • syslog - Записывает сообщения в syslog. Также принимает --log-opt, чтобы направлять сообщения журнала в указанный syslog через сокет домена TCP, UDP или Unix. Также отключает docker logs
  • journald - записывает в журнал systemd.
  • * gelf - расширенный формат журнала Graylog (GELF). Записывает сообщения журнала в конечную точку GELF, такую ​​как Graylog или Logstash
  • * fluentd - отправить журналы контейнеров на fluentd. Принимает некоторые параметры для настройки адреса fluentd и отправки тегов с сообщениями журнала.
  • ** awslogs - записывает сообщения журнала в журналы AWS CloudWatch

* Новое в Docker 1.8

** Новое в Docker 1.9

Например:

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

Это рекомендуемое Docker решение для программного обеспечения, которое записывает свои сообщения журнала в stdout и stderr. Однако какое-то программное обеспечение не записывает сообщения журнала в stdout/stderr. Вместо этого они записывают файлы журнала или в syslog, например. В этих случаях некоторые детали из первоначального ответа ниже по-прежнему применяются. Напомним:

Если приложение записывает в локальный файл журнала, смонтируйте том из хоста (или используйте контейнер logspout, чтобы автоматически маршрутизировать журналы контейнеров на удаленный syslog через UDP

Не забывайте, что любые журналы в контейнере должны вращаться так же, как и в ОС хоста.


Оригинальный ответ для Docker pre-1.6

Можно ли полагаться на собственный журнал регистрации Docker (журналы докеров)?

docker logs печатает весь поток каждый раз, а не только новые журналы, поэтому он не подходит. docker logs --follow предоставит tail -f -подобную функциональность, но тогда вы все время выполняете команду CLI докера. Таким образом, хотя безопасно запускать docker logs, это не оптимально.

Можно ли безопасно запускать докеры и рассматривать его вывод как поток ведения журнала?

Вы можете запускать контейнеры с systemd, а не daemonize, таким образом захватывая все stdout в журнале systemd, которые затем могут управляться хостом, но вы хотите.

Может ли stdout быть перенаправлен непосредственно на файл (дисковое пространство)?

Вы можете сделать это с помощью docker run ... > logfile, конечно, но он становится хрупким и сложнее автоматизировать и управлять.

Если вы используете файл, он должен находиться внутри изображения докеры или связанного тома (docker run --volume = [])?

Если вы пишете внутри контейнера, вам нужно запустить logrotate или что-то в контейнере для управления файлами журнала. Лучше установить том из хоста и управлять им с помощью демона вращения журнала хоста.

Требуется ли лотрование?

Конечно, если приложение записывает журналы, вам необходимо повернуть их так же, как в среде родной ОС. Но это сложнее, если вы пишете внутри контейнера, поскольку местоположение файла журнала не так предсказуемо. Если вы вращаетесь на хосте, файл журнала будет жить, например, с devicemapper в качестве драйвера хранилища, /var/lib/docker/devicemapper/mnt/<containerid>/rootfs/.... Некоторая уродливая оболочка понадобится, чтобы logrotate нашел журналы под этим путем.

Безопасно ли перенаправить stdout прямо в logshipper (и какой logshipper)?

Лучше использовать syslog и разрешить сборщику журналов с syslog.

Можно ли использовать именованный канал (aka FIFO)?

Именованный канал не идеален, потому что, если считывающий конец трубы умирает, писатель (контейнер) получит разбитый трубопровод. Даже если это событие будет обработано приложением, оно будет заблокировано до повторного чтения. Плюс он обходит docker logs.

Смотрите также этот пост на fluentd с докером.

См. инструмент Jeff Lindsay logspout, который собирает журналы из запущенных контейнеров и маршрутизирует их, как вы хотите.

Наконец, обратите внимание, что stdout из журнала контейнера в файл на хосте в /var/lib/docker/containers/<containerid>/<containerid>-json.log.