При администритовании парка серверов примерно от 10 и выше, возникает необходимость в централизованном хранении логов.
Целей тут несколько.
- Во первых безопасность — все фиксируется, и дублируется не только локально, но и на удаленном сервере. Если взломают сервер и потрут логи, то в частном случае можно будет восстановить что и когда было сделано; кем и откуда.
- Второй момент — удобная обработка логов. Логи можно быстро затолкать в эластик и через интерфейс kibana легко смотреть что происходит, строить зависимости и тд.
- Третий, важный момент — единая с программистами среда разбора логов. Можно сопоставлять время того или иного событиям по определенным критериям с событиями на других серверах, обычно этот критерий является основным для внедрения централизованной хранилки логов.
- Есть еще один очень важный момент в крупных кампаниях — протокол syslog очень удобно использовать для доставки сообщений не только от серверов но и от приложений, кронов и прочего в хранилку. Плюс тут в существенном росте производительности — приложению не требуется ни открывать файл на диске, ни тем более соединятсья по сети с elasticsearch — все что нужно это записать данные в syslog сокет. Дальше при правильной настройке доставка произойдет средствами самого сислога, а процесс продолжит свою работу без существенных задержек.
Приступаем. На большинстве серверов в коробке уже стоит rsyslogd, который помимо всего прочего умеет отправлять логи в elasticsearch. Это очень круто, так как не требуется лишнее звено в виде logstash!
Для надежности в эластике мы будем дублировать логи в эластике и на диске.
Для пересылки у нас используется tcp, т.к. сеть большая, с несколькими впн туннелями, накладных расходов от такого подхода — 100мс, на установку соединения, а терять логи не по джадайски. Конфиг для передающей стороны выглядит следующим образом:
# cat /etc/rsyslog.d/rsyslog-server.conf
$MaxMessageSize 65536
$ActionQueueType Direct
$ActionResumeRetryCount -1 #пытаться отправить бесконечно
$ActionQueueSaveOnShutdown on # При завершении работы сбросить очередь на диск
*.* @@syslogserver.casp.ru/old:514
Тут параметр $ActionQueueType Direct подбирался экспериментально, в скупой официальной документации на эту тему сказано ровно следующее:
queue.type [FixedArray/LinkedList/Direct/Disk]
Экспериментально было выяснено:
- LinkedList — асинхронный режим, при получении больших сообщений не передает их сразу а некоторое время ожидает, до полуминуты.
- Direct — синхронный режим, быстро и сразу передает сообщения
- Disk — сихнронный самый медленный режим, предполагающий все сообщения вместе с передачей писать в очередь на диск
- FixedArray — не экспериментировл, но по смыслу похоже на LinkedList
И далее на принимающем сервере создаем следующий конфиг:
# cat /etc/rsyslog.d/remotelogger.conf
$MaxMessageSize 65536
$ModLoad imudp
$UDPServerRun 514
$ModLoad imtcp
$InputTCPServerRun 514
$PreserveFQDN on
$template RemoteHost,\"/var/log/remote/%HOSTNAME%/syslog.log\"
*.* ?RemoteHost
Тут все просто и внимание стоит обратить на две последние строчки — создаем темплейт по которому будут писаться сообщения в файловой системе и в последней строке пишем.
В первых же 4х строках мы открыли на прием стандартные порты на tcp и udp.
В обоих случаях необходимо указывать $MaxMessageSize желательно заметно больше ожидаемой длины пакета.
Теперь самое вкусное — запись логов в elasticsearch. В том же кониге создаем два темплейта. Первый переведет полученные данные в json и подготовит для загрузки в elasticsearch, второй определяет индекс для отправки логов в самом эластике:
template (name=\"plain-syslog\"
type=\"list\") {
constant(value=\"{\")
constant(value=\"\\\"@timestamp\\\":\\\"\") property(name=\"timereported\" dateFormat=\"rfc3339\")
constant(value=\"\\\",\\\"host\\\":\\\"\") property(name=\"hostname\")
constant(value=\"\\\",\\\"severity\\\":\\\"\") property(name=\"syslogseverity-text\")
constant(value=\"\\\",\\\"facility\\\":\\\"\") property(name=\"syslogfacility-text\")
constant(value=\"\\\",\\\"tag\\\":\\\"\") property(name=\"syslogtag\" format=\"json\")
constant(value=\"\\\",\\\"message\\\":\\\"\") property(name=\"msg\" format=\"json\")
constant(value=\"\\\"}\")
}
template(name=\"syslog-index\"
type=\"list\") {
constant(value=\"syslog-\")
property(name=\"timereported\" dateFormat=\"rfc3339\" position.from=\"1\" position.to=\"4\")
constant(value=\".\")
property(name=\"timereported\" dateFormat=\"rfc3339\" position.from=\"6\" position.to=\"7\")
constant(value=\".\")
property(name=\"timereported\" dateFormat=\"rfc3339\" position.from=\"9\" position.to=\"10\")
}
Следующим шагом загружаем модуль вывода данных в эластик и отправляем в него данные по шаблону определенному выше:
module(load=\"omelasticsearch\")
*.* action(type=\"omelasticsearch\"
server=\"127.0.0.1\" # destination Elasticsearch host
serverport=\"9200\" # and port
template=\"plain-syslog\"
searchIndex=\"syslog-index\"
dynSearchIndex=\"on\")
По теме rsyslog на этом месте можно закончить! Не расскрытой осталась тема работы с kibana.
Если у Вас она еще не стоит, то вот простой рецепт. Создаете файл docker-compose.yml следующего содержимого на этот же сервер:
elasticsearch:
image: elasticsearch:latest
container_name: elastic
command: elasticsearch -Des.network.host=0.0.0.0
#net: host
ports:
- \"127.0.0.1:9200:9200\"
volumes:
- \"/srv/docker/elastic/db:/usr/share/elasticsearch/data\"
restart: always
kibana:
image: kibana
restart: always
container_name: kibana
links:
- elasticsearch:elasticsearch
ports:
- \"5601:5601\"
После чего выполняем в папке с этим файлом команду docker-compose up -d, далее происходит скачка, установка и запуск контейнеров. Сразу же после запуска в эластк начнут поступать данные из сислога, а в кибану мы сможем попасть по порту 5601 (отпубликованному в конфиге выше). Нам остается в кибане создать индекс syslog- и начать пользоваться фильтрами.