Дисклеймер


Все эксперименты проводились на CentOS Linux release 7.2.1511 в качестве основной системы, с последними доступными из стоковой репы systemd (systemd-219-19.el7_2.13). Надеюсь, часть приведенных данных будет неактуальна уже на момент публикации статьи.


Вводная часть


Начав захватывать linux-дистрибутивы с выпуска Fedora 15, systemd окончательно победил. Зубры и аксакалы понемногу приучаются к unit'ам и systemctl. Скрежещат зубами последние защитники Старого Доброго. В этих реалиях невозможно обойти дочерние продукты systemd. И сегодня давайте поговорим, например, про journald.



Сам по себе journald (и соответственно journalctl) — прекрасный инструмент. Зародившийся как слегка сторонний к systemd проект, к нынешнему времени journald стал вторым инструментом из семейства systemd, с которым знакомятся системные администраторы. Мне действительно нравится идея рантайм хранилища логов с опциональной возможностью сброса на постоянное хранение, задумка с boot-id journalctl --boot и machine-id (journalctl --machine), возможность из единого интерфейса вызывать логи любых зарегистрированных приложений journalctl -u, а также наличие "из коробки" ротации логов (как по месту, так и по времени) при помощи journalctl --vacuum-size или journalctl --vacuum-time. Из хорошего нельзя не упомянуть ещё и параметры since, until и priority, которыми можно "грепать" события по времени и приоритету, и, разумеется, параметр utc, снимающий огромную головную боль с мульти-таймзонными командами и проектами. Может быть немного спорным бинарный формат хранения файлов, но этот выбор был объяснен авторами ещё при первых анонсах journald (безопасность и дешевизна хранения, интеграция с systemd, принудительный единый формат, переносимость).


К сожалению, не приобрел большого распространения механизм каталогов journald, который позволяет, например, организовать перевод сообщений логов или предоставить конечным пользователям url для решения проблем с конкретными ошибками. Но в целом даже разработчики systemd не пользуются этой возможностью полностью — куда уж нам, смертным.


Это всё реализовано, работает, описано в сотнях мануалов, проверено. Большое спасибо, но я хочу больше.


Преамбула


Не так давно один приятель попросил настроить ему сервер для сбора логов. Хха! — подумал я, — это же прекрасный повод изучить journald в свете его возможностей центрального лог-сервера!


Понятное дело, что инструмент зависит от задачи. Вот и в этот раз был проведен краткий сбор требований:


  1. Необходимо организовать единую точку логирования
  2. Необходимо организовать возможность подключения к единой точке логирования заранее неизвестного количества клиентов (и их отключение, соответственно)
  3. Желательно организовать возможность просмотра логов online, с автоматическим получением новых записей
  4. При выполнении предыдущего пункта, хранение логов на центральной точке можно ограничить N часами (даже не днями)
  5. Формат сообщений непостоянен вплоть до мультилайна
  6. Ключевое интересующее ПО пишет в stdout (да, можно изменить поведение или накостылить, но покупаем, что продают), консоль не закрывает

И общетехническая вводная:


  1. Данные передаются по паблик-сетям
  2. Головная выделенная машина: Centos7.2 (latest)
  3. Подключаемые машины: Ubuntu 16.04

Кажется, что systemd и journald хороший выбор, верно? Ведь все пункты уже реализованы! Поднимаем тестовый стенд!


Головной хост


Ну что же, начнём.
Нас интересуют три компонента:


  1. systemd-journal-gatewayd — http-демон, открывающий порт для просмотра (или скачивания) записей журнала
  2. systemd-journal-remote — демон, скачивающий или принимающий записи журналов на центральном сервере
  3. systemd-journal-upload — демон, дублирующий записи журналов на удаленный сервер

Все эти компоненты входят в centos-пакет systemd-journal-gateway, так что выполняем:


yum -y update && yum -y install systemd-journal-gateway

За получение логов на головной машине используется демон systemd-journal-remote. С него и начнём.


systemd-journal-remote


У remote есть два режима работы: активный (при котором он сам ходит в удаленный журнал и скачивает логи — в том числе в режиме слежения. Для этого режима на всех удаленных машинах нужен systemd-journal-gatewayd) и пассивный (при котором демон висит и ждёт, пока к нему придут). С учетом неизвестного количества машин — выбираем пассивный режим. Вся настройка, собственно, заключается в том, чтобы сделать директорию /var/log/journal/remote, назначить ей права нужного пользователя и запустить сервис:


mkdir -p /var/log/journal/remote
chown systemd-journal-remote:systemd-journal-remote /var/log/journal/remote
systemctl start /var/log/journal/remote

Поскольку мы собираем демо-стенд, давайте переключим протокол приёма файлов с https на http. Для этого необходимо отредатировать стартовый сервис-файл /lib/systemd/system/systemd-journal-remote.service, заменив опцию listen-https на listen-http. Также будет полезно поправить /lib/systemd/system/systemd-journal-remote.socket, указав только интересующий нас адрес для биндинга демона.


Демон стартовал, висит в пассивном режиме, работает по http. Ура!


Дьявол в деталях


Во-первых, при создании директории /var/log/journal все ваши системные логи начнут писаться в директорию /var/log/journal/<uuid>. Чтобы изменить это поведение и вернуть как было, надо заправить конфигурационный файл /etc/systemd/journald.conf (а лучше даже /etc/systemd/journald.conf.d/<ваш конфиг>.conf, т.к. первый может перетереться при обновлениях), а именно строку Storage=. По умолчанию, значение этого параметра auto, что означает "если есть директория в var, journald записывает логи туда". В моём случае, параметр надо было принудительно выставить в volatile.


systemd-journal-upload


С upload всё ещё проще: создаём /etc/systemd/journal-upload.d/<ваш конфиг>.conf, записав туда:


[Upload]
URL=http://<IP-адрес remote>:<порт удаленного демона>

и запустим systemctl start systemd-journal-upload


Дьявол в деталях


Во-вторых, демон не запустится благодаря очень старой баге в Centos. Так что делайте usermod руками: usermod -a -G systemd-journal systemd-journal-upload. После этого демон должен стартовать успешно.


Удаленные клиенты


На удаленных клиентах, напомню, стоит Ubuntu 16.04. Так что ставим там apt-get install systemd-journal-remote и проводим правки /etc/systemd/journal-upload.d/<ваш конфиг>.conf, аналогичные предыдущему пункту (кроме usermod).


systemd-journal-gatewayd


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


Ну что же, давайте хотя бы понаблюдаем за логами:


journalctl -D /var/log/journal/remote --follow

Ну, что-то вроде работает...


Дьявол в деталях


В третьих, благодаря старой баге в systemd, у вас начнёт дичайше пухнуть директория /var/log/journal/remote. И тут вам не поможет ничего...


Дойдём до конца!


Тем не менее, раз уж мы зашли так далеко, давайте дойдём до конца. Запускаем на головной машине демон systemd-journal-gatewayd (опять не забываем поправить /lib/systemd/system/systemd-journal-gatewayd.socket, чтобы ограничить демона, да?) и внимательно изучаем веб-интерфейс просмотрщика:


  • Подкачка логов online фактически отсутствует
  • Лютые on mouse over и on mouse scroll для логов
  • microhttpd под капотом
  • Простите, но ужасающий интерфейс
  • Есть возможность фильтрации логов по systemd-unit, но (в связи с количеством неинформативных session-юнитов например от крон-скриптов) невозможность пользоваться фильтрами
  • Все юниты пишутся полностью — если вы используете например пароли к базам данных в крон-строках, ваши пароли будут вас ждать

Нда. Возможно, и хорошо, что не получилось его настроить, м?


Итого


Для proof of concept за пару дней был написан pet-проект, благо journald предоставляет родную библиотеку для питона. Из особенностей:


  1. Онлайн-просмотр по SSE
  2. Возможность фильтровать выводимые юниты администратором на уровне конфигурации
  3. Возможность фильтровать хосты/приоритет/юниты пользователем на уровне веб-приложения
  4. Ну и немножко бутстрапа

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


Но на больших проектах лично я наверное ещё долго не буду использовать journald в качестве центрального хранилища логов. До тех пор, пока не будут убраны приведенные выше баги, мой выбор — однозначно в пользу syslog.


Автор статьи: Степан Карамышев

Поделиться с друзьями
-->

Комментарии (29)


  1. AlexeevEugene
    13.12.2016 09:50

    Кстати, а многие делают: yum remove firewalld и yum install iptables? :)


    1. ls1
      13.12.2016 10:28

      firewalld я пробовал когда только семёрочка вышла, но из-за отсутствия в нём (по крайней мере на тот момент) админки для Forward — удалил и с тех пор не пользуюсь. Предпочитаю FirewallBuilder


      1. AlexeevEugene
        14.12.2016 12:02

        О! прикольный GUI для iptables! Спасибо


        1. ls1
          14.12.2016 12:20

          Он, к слову, не только для iptables


    1. grossws
      13.12.2016 12:56

      Если конфигурация полностью статическая, то можно и iptables обойтись. Я на firewalld пересел, когда появилась необходимость накатывать новые правила не убивая то, что уже есть mangle и nat (например, правила от docker daemon'а). Ну и разобравшись с его интерфейсом всё становится несколько удобнее для автоматизации (с тем же ansible), хотя некоторые их решения (типа exit code 0 и 1 в качестве true и false) — несколько бесят.


      Также firewalld полезен при наличии роуминга ноута по разным сетям, но это к топику не относится.


      1. AlexeevEugene
        13.12.2016 14:59

        да, хороший аргумент. Не задумывался в таком ключе:) Спасибо за повод изучить это.


    1. navion
      13.12.2016 22:08

      Он разве стоит по-умолчанию в CentOS? В RHEL он точно есть, а свежеустановленная CentOS 7.x удивила отсутствием команды firewall-cmd.


      1. AlexeevEugene
        13.12.2016 23:02

        Всегда ставлю minimal. Там он точно есть.
        ##edit ОГО в 7.2 выпилили!


        1. varnav
          14.12.2016 15:24

          Да, его молча выпилили из 7.2, хотя в 7.1 он был.


      1. grossws
        14.12.2016 04:15
        +1

        Сначала был, потом выпилили. Видимо, по просьбам трудящихся. Но если ставиться с kickstart'а, то разницы никакой, достаточно указать firewall --enabled --ssh и firewalld приедет в комплекте.


  1. luban
    13.12.2016 12:40

    Опечатка — systemctl start /var/log/journal/remote

    Наверно надо: systemctl start systemd-journal-gatewayd


  1. grossws
    13.12.2016 12:45
    +2

    Поскольку мы собираем демо-стенд, давайте переключим протокол приёма файлов с https на http. Для этого необходимо отредатировать стартовый сервис-файл /lib/systemd/system/systemd-journal-remote.service, заменив опцию listen-https на listen-http. Также будет полезно поправить /lib/systemd/system/systemd-journal-remote.socket, указав только интересующий нас адрес для биндинга демона.

    Не надо там редактировать, надо читать документацию. И делать override в /etc/systemd/system/systemd-journal-remote.service или `/etc/systemd/system/systemd-journal-remote.service.d/*.conf


    1. skob
      13.12.2016 15:17
      +1

      Если уж делать оверрайд, то по второму пути, естественно.


      1. grossws
        13.12.2016 15:27
        +1

        Если замещать unit полностью — то по первому, если override куска — то по второму, естественно.


        1. Radjah
          14.12.2016 22:05
          -1

          замещать unit полностью

          И потерять изменения при следующем обновлении пакета.


          1. grossws
            14.12.2016 22:09

            Нет, если мейнтейнеры дистрибутива не идиоты (подсказка: не идиоты). Читать man 5 systemd.unit:


            /etc/systemd/system Local configuration
            /run/systemd/system Runtime units
            /usr/lib/systemd/system Units of installed packages


    1. Chupaka
      20.12.2016 15:39

      Даже если совсем лень читать документацию, можно воспользоваться встроенной командой: systemctl edit systemd-journal-remote.service. Она сама разберётся, что куда записать, чтобы обновления не откатили изменения :)


  1. past
    13.12.2016 12:54

    Я делал такую связку с грейлогом и конвертером системдишного JSONa в грейлоговский (journal2gelf), без возни с недопиленными journal-remote и journal-gatewayd.


  1. akamensky
    13.12.2016 13:02
    -1

    Вот из-за таких корявостей (как например /var/log/journal) многие и недолюбливают systemd.

    Мне лично он очень нравится как замена init.d/upstart, но остальные компоненты честно говоря работают очень нестабильно. Хороший пример systemd-networkd, если сеть не поддерживает IPv6, и он как следствие отключен, то на серверах с DHCP интерфейсы могут быть в статусе «configuring» до 10 минут. И очень странные проблемы с systemd-resolved, когда два запроса подряд на один домен — один может вернуть нормальный ответ, а другой вернет пустой ответ.

    А для логов, я все же предпочитаю использовать rsyslog или syslog-ng, которые из коробки поддерживают пересылку логов через TCP или UDP в syslog совместимом формате.


    1. h31
      13.12.2016 17:43

      Systemd-networkd вроде как рассчитан только на простейшие конфигурации. Например, настроить сеть в контейнере или в VM.
      Сам лично пользовался networkd на реальной машине, но иногда отваливалась сеть. Когда прочитал, что networkd как бы не для этого сделан, перешел на dhcpcd и с тех пор ни одного глюка не видел.


      1. akamensky
        13.12.2016 18:07

        Не уверен откуда такая информация. На официальном сайте systemd-networkd описан как системная служба для настройки сети.

        Заголовок спойлера
        systemd-networkd is a system service that manages networks.


  1. varnav
    13.12.2016 13:56

    А можно сделать совсем просто.

    1. Установить graylog
    2. Выполнить команду (замените адрес и порт грейлога на свои):

    echo '*.* @192.168.5.5:5140;RSYSLOG_SyslogProtocol23Format' >> /etc/rsyslog.conf && service rsyslog restart
    


    1. past
      13.12.2016 14:22

      Значительно информативней высылать с хоста сразу GELF.


      1. varnav
        13.12.2016 15:43

        А это можно делать штатными средствами?


        1. past
          14.12.2016 17:30

          Вам придется поставить питоновский модуль graypy и собственно сам скрипт journal2gelf.


          1. varnav
            14.12.2016 17:48

            Вот в этом то и дело. А перед этим ещё и сам питон поставить.
            А в первом случае ничего не нужно, сработает на чистой minimal установке всех ОС в journald.


  1. worldmind
    13.12.2016 18:40

    > Может быть немного спорным бинарный формат хранения файлов, но этот выбор был объяснен авторами ещё при первых анонсах journald (безопасность и дешевизна хранения, интеграция с systemd, принудительный единый формат, переносимость).

    а я думал что бинарный формат для быстрого поиска по индексам

    Не уверен что для логов нужен веб-гуй, по мне лучше по ssh заходить и смотреть/грепать на месте


  1. mihmig
    14.12.2016 15:45

    А как в этом journald обстоят дела с безопасностью?
    Может ли например приложение «сыпать» в лог не от своего имени? Если да, то это большая уязвимость.


  1. box4
    20.12.2016 15:39

    простите, а просто настроить rsyslog не достаточно?