Централизованное ведение журнала

Централизуйте ведение журнала Docker с помощью системного журнала

Лучший способ понять наши системы и их успехи или неудачи - это вести большой журнал.

Фон

Во время одного из проектов, над которым я работал в последние годы, передо мной стояла задача интегрировать централизованную систему ведения журналов со стеком приложений, который мы используем (в соответствии с микросервисной архитектурой). Первая идея, которая пришла в голову, заключалась в создании стека ELK (Elasticsearch, Logstash, Kibana) для выполнения этой задачи. Однако оказалось, что это не вариант из-за ограниченности ресурсов проекта.

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

  • Собирайте журналы Docker напрямую.
  • Использование системного журнала для сбора журналов.

Как я уже сказал, первой идеей было построить стек ELK для сбора логов. Однако это было невозможно из-за ограничений бюджета и ресурсов для проекта.

Другая идея заключалась в пересылке журналов в управляемый сервис, такой как logz.io. Этот вариант также был невозможен, потому что производственные серверы не имеют доступа в Интернет - плюс те же бюджетные ограничения.

Третья идея заключалась в создании сценария Logrotate, который выполняет следующие действия для создания файлов журнала:

  • Соберите журналы Docker из /var/lib/docker/containers/*.
  • Переименуйте файлы, используя имена контейнеров вместо идентификаторов.
  • Сожмите файлы журнала.

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

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

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

Реализации

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

  • Кластер Docker с двумя узлами, на котором размещены сервисы.
  • Один узел для хранения логов.

Конфигурации сервера журналов

Чтобы настроить сервер журналов и подготовить его к сбору журналов с хостов Docker, мне пришлось сделать следующие шаги:

  • Убедитесь, что Syslog установлен, или установите его, используя следующие команды:
$> yum update -y
$> sudo yum install rsyslog rsyslog-doc
  • Перечислите правильный TCP-порт. Строка ниже должна существовать в файле конфигурации системного журнала /etc/rsyslog.conf:
$ModLoad imtcp $InputTCPServerRun 514
  • Обновите конфигурации ограничения скорости журнала для системного журнала и journald. Приведенные ниже конфигурации следует добавить в файл /etc/rsyslog.conf, чтобы избежать потери журнала в случае слишком большого количества сообщений журнала. См. Документацию системного журнала для получения дополнительной информации.
$imjournalRatelimitInterval 0
$imjournalRatelimitBurst 0
  • Кроме того, для конфигурации ограничения скорости необходимо установить значение 0 в файле конфигурацииjournald /etc/systemd/journald.conf.
RateLimitInterval=0

По умолчанию Syslog сохраняет все журналы в /var/log/messages. Однако мы хотели бы разделить журналы по имени контейнера, чтобы упростить исследование. Чтобы настроить сервер системного журнала для разделения журналов из разных контейнеров в разные файлы, нам необходимо выполнить следующие шаги:

  • Решите и создайте папку для хранения всех журналов.
$> mkdir /var/log/dockerlfs
  • Соберите журналы для демона Docker и сохраните их на диск. Приведенное ниже правило конфигурации Syslog (хранящееся в /etc/rsyslog.d/docker_daemon.conf) запускает Syslog для сохранения всех журналов, принадлежащих программе, которая запускает docker, в /var/log/dockerlfs/daemon.log.
  • Собирайте журналы контейнеров Docker и сохраняйте их в отдельные файлы журналов. Приведенное ниже правило конфигурации системного журнала сохраняет журналы в отдельные файлы для каждого из запущенных контейнеров на основе имени контейнера. Правило должно храниться в /etc/rsyslog.d/docker_container.con. Это правило полагается на то, что хосты Docker помечают все журналы с помощью container_name.

Следующим шагом является установка правила Logrotate для ротации журналов и предотвращения больших файлов журналов на сервере. Системные администраторы могут заархивировать старые журналы. Приведенное ниже правило будет обновлять журналы на сервере ежедневно или если размер файла превышает 20 МБ. Он также будет хранить только последние 30 файлов журнала для каждого контейнера.

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

$> systemctl restart rsyslog
$> systemctl restart systemd-journald

Настроить хосты Docker

Теперь, когда мы закончили настройку сервера Syslog, мы можем перейти к настройке хостов Docker для пересылки журналов с серверов на сервер Syslog.

Первое, что необходимо сделать, - это перенастроить демон Docker для использования драйвера журнала syslog вместо journald и пометить журналы именем контейнера. Для достижения этой цели нам нужно изменить файл конфигурации демона Docker, который находится в /etc/docker. daemon.json должен включать следующее содержание:

Переменную SYSLOG_SERVER_IP следует заменить IP-адресом сервера системного журнала. Переменную ENV_NAME следует заменить именем среды (тестирование, подготовка или производство). С приведенными выше конфигурациями Docker будет перенаправлять журналы непосредственно на сервер Syslog. В случае, если сервер системного журнала не работает или нет действительного подключения к нему, мы можем потерять некоторые журналы с конфигурациями выше.

Чтобы улучшить нашу систему ведения журналов и избежать потери журналов, мы собираемся внести следующие изменения:

  • Перенаправить журналы из Docker на локальный сервер.
  • Настройте локальный системный журнал для пересылки журналов на централизованный сервер журналов.

Чтобы пересылать журналы из Docker на локальный сервер Syslog, нам просто нужно удалить следующую строку из /etc/docker/daemon.json или заменить SYSLOG_SERVER_IP на 127.0.0.1:

"syslog-address": "tcp://${SYSLOG_SERVER_IP}:514",

Когда мы закончим настройку Docker, нам нужно перезапустить демон Docker.

$> systemctl restart docker

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

конфигурации системного журнала и журнала

Нам понадобится следующий элемент конфигурации для journald в файле /etc/systemd/journald.conf: RateLimitInterval=0.

Нам понадобятся следующие элементы конфигурации для Syslog в файле /etc/rsyslog.conf:

$ActionQueueFileName fwdRule1
$ActionQueueSaveOnShutdown on
$ActionQueueType LinkedList
$ActionResumeRetryCount -1
$imjournalRatelimitInterval 0
$imjournalRatelimitBurst 0
  • ActionQueueFileName: Добавляет уникальный префикс имени для файлов очереди.
  • ActionQueueSaveOnShutdown: Сохранять сообщения на диск при завершении работы.
  • ActionQueueType: запускать асинхронно.
  • ActionResumeRetryCount: Я бесконечное количество попыток, если хост не работает.

С приведенными выше конфигурациями Syslog будет продолжать повторять попытки отправки журналов на централизованный сервер до тех пор, пока журналы не будут захвачены сервером назначения. Однако до сих пор мы не настраивали локальный сервер системного журнала на хостах Docker для пересылки журналов на другие серверы. Поэтому все журналы, собранные из Docker, будут сохранены в файле по умолчанию /var/log/messages.

Перенаправить журналы из системного журнала на другой сервер очень просто. Вам нужно только добавить следующее правило в конец файла /etc/rsyslog.conf и заменить SYSLOG_SERVER_IP действительным IP-адресом сервера журнала. Это правило в основном проверяет все журналы и фильтрует их на основе тегов и имени программы. Если теги сообщений содержат тег с именем container_name или programname, начните с docker. Затем он отправит журналы на SYSLOG_SERVER_IP.

Мы можем улучшить приведенное выше правило, сохраняя копии журналов локально на серверах Docker. С внесенными ниже изменениями наше правило системного журнала будет отправлять журналы на удаленный сервер системного журнала и будет хранить копии файлов журналов локально на отдельных серверах, на которых запущен Docker, под /var/log/dockerlfs.

Поскольку теперь у нас есть копии файлов журналов на серверах Docker, имеет смысл добавить правило Logrotate для ротации и этих файлов. Мы можем использовать то же правило, что и для серверных узлов.

Наконец, чтобы Syslog и journald приняли новые конфигурации, перезапустите их.

$> systemctl restart rsyslog
$> systemctl restart systemd-journald

Заключение

Централизованные системы регистрации и стеки могут быть реализованы множеством различных методов и инструментов. Системный журнал - один из этих методов, и он особенно полезен, когда есть некоторые ограничения на рабочую среду и отсутствие опыта управления и использования более сложных стеков, таких как ELK.