воскресенье, 4 февраля 2024 г.

Grafana Loki. Сервис promtail. Прием логов из файлов и по syslog. Просмотр информации Loki в оболочке Gragana.

Promtail - это утилита-агент, который отправляет содержимое файлов логов операционной системы Linux в Grafana Loki. Для того чтобы собирать данные логов со всех серверов, promtail нужно установить на каждом сервере.
Promtail умеет не только считывать логи из файлов, но и прослушивать порт tcp для приема сообщений syslog. К сожалению, возможность приема сообщений syslog по udp сразу демоном promtail у меня не заработала, поэтому принимать syslog сообщения напрямую от сетевого оборудования не получилось. Пришлось на сервере вместе с promtail поставить еще syslog-сервер, который принимает сообщения syslog по стандартному порту udp 514 и пересылает на порт tcp 1514, который уже просматривает promtail. Это оказалась рабочая конструкция.
Для просмотра информации из базы Loki самым естественным инструментом является Grafana. Схематически рассматриваемую модель взаимодействия можно представить так:

Установка Promtail.

Promtail можно установить в систему разными путями. Например, promtail скачивается в систему вместе с кодами loki и собирая loki можно так же собрать и исполняемый файл promtail
Порядок сборки Promtail из исходных кодов с установленным интерпретаторов go в Linux:
# cd /usr/src
# git clone https://github.com/grafana/loki
# cd loki/
# go build ./clients/cmd/promtail

В результате в директории /usr/src/loki появиться исполняемый файл promtail, который нужно переместить на постоянное место:
# mv promtail /usr/local/bin/promtail

Promtail можно развернуть из образа Docker. Это рекомендуемый способ, описанный в документации (https://grafana.com/docs/loki/latest/send-data/promtail/installation/), тут данный способ не рассматривается.

И можно скачать готовый исполняемый файл, собранный под типовые операционные системы. На странице текущего релиза (https://github.com/grafana/loki/releases/) ищем ссылку на файл promtail. Дистрибутив с утилитой называется promtail-linux-amd64.zip. Копируем ссылку на этот файл. 31.01.2024 это релиз 2.9.4 и ссылка https://github.com/grafana/loki/releases/download/v2.9.4/promtail-linux-amd64.zip
Порядок получения готового дистрибутива promtail с сайта:
Скачиваем архив с Promtail, распаковываем и перемещаем на постоянное место:
# cd /usr/src
# curl -O -L https://github.com/grafana/loki/releases/download/v2.9.4/promtail-linux-amd64.zip
# unzip promtail-linux-amd64.zip
# rm -f promtail-linux-amd64.zip
# mv promtail-linux-amd64 /usr/local/bin/promtail


Создаем конфигурационный файл сервиса promtail:
# mkdir /etc/promtail
# touch /etc/promtail/promtail.yaml

Для рассматриваемого случая считывания системных логов и получения информации syslog файл конфигурации будет выглядеть так:
# nano /etc/promtail/promtail.yaml
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: 'http://192.168.1.166:3100/loki/api/v1/push'

scrape_configs:
  - job_name: secure
    static_configs:
      - targets:
        - localhost
      labels:
        job: secure
        __path__: /var/log/secure
        host: "192.168.1.166"
  - job_name: audit
    static_configs:
      - targets:
        - localhost
      labels:
        job: audit
        __path__: /var/log/audit/audit.log
        host: "192.168.1.166"
  - job_name: php
    static_configs:
      - targets:
        - localhost
      labels:
        job: php
        __path__: /var/log/php-fpm/*.log
        host: "192.168.1.166"
  - job_name: journal
    journal:
    max_age: 24h
    labels:
      job: systemd-journal
      host: "192.168.1.166"
  - job_name: syslog
    syslog:
      listen_address: 0.0.0.0:1514
      idle_timeout: 60s
      listen_protocol: tcp
      label_structured_data: yes
    labels:
      job: "syslog"
    relabel_configs:
      - source_labels: [__syslog_message_hostname]
         target_label: host
      - source_labels: [__syslog_message_severity]
         target_label: level


Немного о директивах конфигурационного файла.
Директива http_listen_port: 9080 раздела server говорит о том, что сервис Promtail на порту 9080 будет иметь web-морду показа основных данных сервиса.
Раздел positions определяет место, где сервис Promtail будет хранить метки (позиции) уже считанной информации из лог-файлов, чтобы в процессе работы не перечитывать файлы заново и не отправлять в Loki дублирующую информацию.
В разделе clients переменная url определяется путь отправки собранных сервисом данных. Это IP и порт приема данных сервисом Loki.
Раздел scrape_configs описывает задания по считыванию файлов и приема информации сервисом promtail. Задания (job) имеют имя (job_name), тип и метки. Путь считывания файла(ов) задается в подразделе labels оператором __path__.
Одно задание promtail выглядит так:
Каждому событию из файла будет присвоено три метки:
• «job» = «audit»
• «host» = «192.168.1.166»
• «filename» = «название файла»
С помощью этих меток впоследствии в интерфейсе grafana можно будет выполнять поиск в базе Loki. Чем больше меток – тем больше в Loki будет объем индексов и тем медленнее будет поиск. В документации Loki рекомендуют создавать новые метки только тогда, когда Вы точно поймете, что они Вам нужны для выборки данных.
В приведенном выше примере конфигурационного файла будут считываться и отправляться в loki данные из файлов.
/var/log/secure
/var/log/audit/audit.log
/var/log/php-fpm/*.log
Каждый файл логов (группа файлов) описана своим заданием.
Для того, чтобы promtail мог обращаться к файлам логов безопасности системы, важно что бы сервис promtail работал от имени пользователя root.
В рассматриваемом файле конфигурации так же определено задание типа journal. Это задание обязывает Promtail подключаться к системному журналу systemd-journal Linux и считывать оттуда информацию для передачи в Loki.
Для каждого задания по считыванию файлов или данных журнала systemd рекомендую всегда формировать метку, указывающую на IP адрес сервера, откуда поступило лог-сообщение. Благодаря этой информации в базе Loki впоследствии можно будет фильтровать сообщения по хостам.
Директивы конфигурации сервиса приема syslog выглядят так:

Здесь запускается служба на всех IP адресах сервера на порту 1514 и по протоколу tcp выполняется прием сообщений syslog. Каждому сообщению присваиваются метки:
«job» = «syslog»
«level» = «значение Severity»
«host» = «hostname» (или IP адрес)
Дополнительно если в сообщении syslog будет какая-то структура похожая на ключ=значение, то этот фрагмент текста будет преобразован в метку «Ключ (имя метки)»= «Значение»

Для автозапуска Promtail создаем Systemd Unit.
# nano /etc/systemd/system/promtail.service
Содержимое файла:
[Unit]
Description=Promtail service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/promtail-linux-amd64 -config.file /etc/promtail/promtail.yaml
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target

В файле юнита systemd не указан пользователь, который будет владеть процессом. Это сделано умышленно, для того что бы сервис запускался от имени root (это необходимо для считывания логов безопасности Linux, доступных только пользователю root).
После редактирования файла юнита выполняем:
# systemctl daemon-reload
Запускаем сервис и проверяем его работу
# systemctl start promtail
# systemctl enable promtail
# systemctl status promtail
# ss -nltup | grep 9080


Открываем порт 9080 в файрволле и проверяем применение правил:
# firewall-cmd --permanent --add-port=9080/tcp
# firewall-cmd --reload
# firewall-cmd --list-all

Теперь обратившись к Url http://<IP-адрес>:9080 мы увидим информацию о работе сервиса Promtail:

Для отладки конфигурации promtail можно запускать в тестовом режиме вот так:

# /usr/local/bin/promtail --dry-run --inspect --config.file=/etc/promtail/promtail.yaml
Опция --dry-run означает, что данные, полученные promtail не будут отправляются в Loki и лог файл будет читаться с одного и тоже места. Опция --inspect заставит promtail выводить отладочную информацию в консоль. При поступлении новых логов информация и назначаемые информации метки будут в консоли:

Установка и настройка rsyslog.

Rsyslog необходим для того, что бы принимать syslog сообщения по стандартных портам оборудования (514 порт по tcp и udp) и передавать в Loki на порт 1514 tcp. При этом rsyslog форматирует сообщения, которые могут иметь различный формат у разных вендоров. В Loki данные попадают в едином формате.
В системе уже может быть установлен rsyslog по умолчанию, или вместо rsyslog может быть установлен syslog-ng. Поэтому перед установкой rsyslog, необходимо удалить старые версии rsyslog и syslog-ng. Затем провести установку rsyslog в систему:
# yum install rsyslog
# systemctl start rsyslog
# systemctl enable rsyslog

Главный конфигурационный файл rsyslog лежит тут: /etc/rsyslog.conf
Для того что бы rsyslog принимал сообщения по 514 порту (tcp и udp) и перенаправлял их на порт 1514 tcp в едином формате, необходимо добавить следующие директивы в файл конфигурации:
# nano /etc/rsyslog.conf
После директивы include(file="/etc/rsyslog.d/*.conf" mode="optional") нужно вставить:
module(load="imudp")
input(type="imudp" port="514" ruleset="sendRemote")
module(load="imtcp")
input(type="imtcp" port="514" ruleset="sendRemote")
#module(load="omfwd")
ruleset(name="sendRemote") {
    action(type="omfwd" target="10.10.49.166" port="1514" protocol="tcp"
    action.resumeRetryCount="-1"
    Template="RSYSLOG_SyslogProtocol23Format"
    TCP_Framing="octet-counted" KeepAlive="on" RebindInterval="60"
    queue.type="linkedList"
    queue.saveOnShutdown="on"
    queue.maxDiskSpace="1g"
    queue.fileName="fwdRule1")
}
В конфигурации закомментирована одна строчка - #module(load="omfwd"). Дело в том, что в некоторых версиях rsyslog, требуется прописывать данную строку явно, в современных версиях rsyslog модуль перенаправления omfwd загружается при старте rsyslog и отдельное указание на загрузку этого модуля не требуется.

Примечание 1. Если модуль интегрирован в rsyslog, его не нужно загружать, а мы пытаемся это сделать директивой module(load="omfwd") возникнет ошибка:
could not load module 'omfwd', errors: trying to load module /usr/lib64/rsyslog/omfwd.so: /usr/lib64/rsyslog/omfwd.so: /usr/lib64/rsyslog/omfwd.so: cannot open shared object file: No such file or directory [v8.2102.0-117.el9 try https://www.rsyslog.com/e/2066 ]

Примечание 2. Директива RebindInterval="60", описанная в конфигурации, обязывает демон rsyslog каждые 60 секунд пересоздавать соединение tcp с удаленным сервером, куда выполняется перенаправление. Если этого не делать, Loki, если не будет видеть активности на приеме, закроет Tcp соединение через 2 минуты (120 секунд по умолчанию). В логах rsyslog при этом можно будет наблюдать: 
omfwd: remote server at 10.10.49.166:1514 seems to have closed connection. This often happens when the remote peer (or an interim system like a load balancer or firewall) shuts down or aborts a connection. Rsyslog will re-open the connection if configured to do so (we saw a generic IO Error, which usually goes along with that behaviour). [v8.2102.0-117.el9 try https://www.rsyslog.com/e/2027 ]

Grafana. Настройка представления данных Loki.

После установки Gragana, для отображения данных Loki в интерфейсе необходимо выполнить подключение источника данных – Loki и создать дашборд, показывающий эти данные.
Для подключения источника, выбираем в меню «Connections» —> «Data sources»
Затем нажимаем кнопку «Add data source»
Теперь необходимо выбрать тип источника данных. В поисковой строке набираем «loki» и кликаем по найденному драйверу:
В открывшейся форме добавления нового источника вписываем имя источника, например «loki», затем в поле URL вписываем путь до порта, прослушиваемого сервисом loki. Например http://192.168.1.166:3100. Остальные настройки можно оставить по умолчанию. Прокручиваем страницу вниз и нажимаем кнопку «Save & test». После этого произойдет соединение с базой Loki и новый источник данных отобразиться в меню Grafana.
Если что-то пойдет не так и соединение не будет установлено, возникнет ошибка «Unable to connect with Loki. Please check the server logs for more details»
При удачном соединении мы должны увидеть:
В меню «Connections» будет представлен новый источник данных:

Теперь нужно создать типовой Dashboard для показа данных о логах. Для этого заходим в меню Dashboards и нажимаем кнопку «Create Dashboars»
Затем нажимаем кнопку «Add visualization»
На следующем этапе нужно выбрать источник данных. В нашем случае – это источник «loki», который мы подключили ранее
Откроется окно создания нового представления для дашборда:
На нижней панели добавляются запросы, которые будут работать с источником данных «Loki». Для отображения количества лог-записей системного журнала systemd, поступивших за 1 минуту в базу Loki нужно задать следующее:
Метки (Label filter): job=system-journal,
Операции: Count over time, Range, 1m
То есть тут задается фильтр меток по которым из базы Loki будут извлечены только записи, обладающие меткой «job»=«system-journal», а затем указывается операция преобразования этой выборки – показывать количество записей за указанный временной интервал.
Для проверки работы выборки справа представлена кнопка «Run query».
При нажатии на эту кнопку сверху будет показан график, построенный на основе нашего запроса к базе.
Для сохранения этого представления на дашборде на правой панели нужно задать имя представления (Title), например «system-journal count», и нажать «Apply»:
После этого представление добавиться на дашбоард. Представление не будет занимать все пространство дашбоарда:
Что бы растянуть представление на всю ширину, нужно ухватить мышкой за правый нижний угол панели представления и растянуть картинку во всю ширину:
Теперь нужно сохранить дашборд в памяти Grafana. Для этого нужно нажать на панели вверху справа кнопку сохранения «Save dashboard»
После этого нужно ввести имя (Title) дашборда, например «Logs», и нажать кнопку сохранения «Save»
Добавим на дашборд кроме графика количества логов еще и таблицу с записями логов. Для этого сверху на панели инструментов нажимаем «Add»--> «Visualization»
Для того что бы добавить панель представления с таблице логов нужно выбрать тип представления. Тип представления выбирается справа из выпадающего списка. Для показа логов нужно выбрать тип «Logs»:
Затем задаем имя представления (Title), например «systemd-journal logs». Для показа времени события (времени прихода лога) делаем активным переключатель Time. Для того что бы длинные записи лога переносились на новую строку активируем переключатель «Wrap lines»:
После этого в нижней панели слева формируем запрос к базе, который будет работать на этом представлении.
Указываем, что нужно отображать записи, обладающей меткой «job»=«system-journal». Для проверки отображения данных нажимаем «Run query»
На панели сверху должны отобразиться логи. Для сохранения этого представления нужно нажать кнопку «Apply», расположенную сверху справа:
После добавления нового представления на дашборд нужно еще раз сохранить дашборд нажав «Save dashboard» и еще раз «Save»
Теперь внешний вид дашбора будет выглядеть так:

Для удобства работы с dashboard можно ввести сразу на этом дашборде доступ к показу данных с конкретного сервера и фильтр поиска по тексту лога, так как сейчас нет возможности отделить в потоке логов логи от разных серверов и искать информацию внутри логов.
Для этого нужно на дашборд добавить переменные. Это делается в настройках дашборад. Нужно нажать кнопку «Dashboard settings»:
И затем выбрать пункт меню «Variables»
Далее нажимаем кнопку добавления переменной «Add variable»
Нам нужно добавить две переменные. Первая переменная будет являться выпадающим списком, который содержит все IP адреса хостов, откуда в Loki валяться логи. Вторая переменная будет обычным текстовым полем, чтобы задавать текст, который нужно искать в теле лог-сообщения.
Для добавления выпадающего списка хостов (IP адресов источника логов) тип переменной должен быть «Query». Затем нужно задать:
Имя переменной - «Name», например «host»
Метку переменной (ту что будет отображаться на дашборде) – «Label», например «host».
Источник данных, как будет заполняться переменная. В нашем случае выпадающий список будет формироваться из уникальных меток «host» источника «Loki». Для значения переменной будет браться значение меток («Label values»)
Остальные поля можно оставить по умолчанию и нажать «Apply»
После этого в панели свойств дашборда появиться созданная переменная «host»
Для добавления второй переменной нажимаем «New variable». Для добавления простой переменной, которую будем использовать для поиска внутри лог-сообщения нужно добавить переменную типа «Text box». Затем нужно задать
Имя переменной - «Name», например «search_txt»
Метку переменной (ту что будет отображаться на дашборде) – «Label», например «search»
Остальное оставляем по умолчанию и нажимаем «Apply»
Теперь в списке переменных дашборад должно появиться две переменные:
Сохраняемся, чтобы не потерять изменения (добавление переменных).
Теперь переменные нужно внедрить на дашборд. Сами поля для выбора-задания переменных уже появились на дашборде, но пока они не работают. Для вплетения переменных в запросы данных Loki на дашборде справа на панели представления количества логов в минуту вызываем меню и выбираем «Edit»
Теперь необходимо отредактировать цепочку запроса добавив условие, связанное с переменными. В цепочку меток добавляем «host» = «$host», для поиска внутри логов вписываем имя переменной в поле Line contains – «$search_txt». Упоминание переменных в запросах нужно делать добавляя к именам переменных символ доллара.
После изменений запросов представления не забываем нажимать «Apply».
Для второго представления, показывающего сами логи, нужно сделать аналогичное действие. Выбрать меню редактирования представления и добавить в запрос переменные $host и $search_txt следующим образом. Затем сохраниться нажав «Apply»
После данных манипуляций необходимо сохранить изменения в дашборде нажав «Save Dashboard» и затем «Save».
Теперь на дашборде можно проводить поиск логов по IP адресу источника и по произвольному тексту в логах

Дашборд – это панель, на которой должно показываться укрупненно ход текущей работы системы. Если что-то пойдет не так, на графиках, в цифрах и пр, оператор, как правило это видет и переходит к детальному анализу логов. Детальный анализ логов и поиск по базе локи удобно проводить не на дашборде, а в специально предназначенном разделе Grafana – Explore. Перейти в этот раздел можно из меню слева:
Откроется окно составления запросов к базе Loki.
Результат запросов – график количества записей логов и список логов, соответствующий запросу будет представлен ниже на этой же странице