EL-стек без Kibana: собираем логи nginx и Windows Event Log в Elasticsearch
Elasticsearch 0.19 + Logstash 1.0 для централизованных логов: конфиг, производительность на одном узле, и почему мы отложили Kibana в сторону.
Elasticsearch 0.19 и Logstash 1.0 набирают популярность как open-source стек для централизованного хранения и поиска по логам
Три месяца назад мы переводили клиента на syslog-ng PE с Elasticsearch - там источники были Unix-only и объём скромный. Сейчас другая история: клиент из ритейла, смешанная среда - nginx на фронтах, десятки Windows-серверов с Event Log, и вопрос «что вообще происходит в инфраструктуре» решается раз в три дня grep-ом по SSH. Нас позвали сделать нормальный централизованный сбор.
Задача: один узел, все логи в одном месте, поиск через API или хотя бы curl. Не SIEM, не compliance, просто видимость.
Почему именно Elasticsearch + Logstash
Мы смотрели на несколько вариантов. Splunk - коммерческий, лицензия с ограничением по объёму данных в сутки, у клиента бюджет не резиновый. Graylog2 - интересный, но тащит за собой MongoDB и выглядит сыровато для продакшена. Syslog-ng PE с его elasticsearch destination мы уже знаем, но там нет нормального парсинга Windows Event Log из коробки.
Logstash 1.0.x в итоге оказался разумным выбором: он умеет принимать syslog, читать файлы, принимать события через TCP/UDP, разбирать их через grok-паттерны и писать прямо в Elasticsearch. Одна JVM на весь пайплайн. Elasticsearch 0.19 - уже достаточно стабильный для индексации логов, REST API работает предсказуемо.
Kibana. Она существует, мы смотрели на неё - но версия 1.x, которая есть сейчас, требует довольно много ручной настройки дашбордов, фактически это Kibana поверх Elasticsearch без нормального темплейтинга. Для разовой демонстрации подойдёт, для операционной работы - нет. Оставили на потом, пока работаем через прямые запросы к ES.
Схема сборки
nginx access.log ──► Logstash (file input) ─┐
nginx error.log ──► Logstash (file input) ─┤
├─► Elasticsearch 0.19
Windows Event Log ──► NXLog (UDP → Logstash) ─┘
(через nxlog-агент на каждом хосте)
На Windows-хостах поставили nxlog - он отправляет события в syslog-совместимом формате по UDP на Logstash. Logstash слушает на порту 514 и дополнительно читает файлы nginx.
Конфиг Logstash
input {
file {
path => "/var/log/nginx/access.log"
type => "nginx_access"
}
file {
path => "/var/log/nginx/error.log"
type => "nginx_error"
}
syslog {
port => 514
type => "windows_event"
}
}
filter {
if [type] == "nginx_access" {
grok {
pattern => "%{COMBINEDAPACHELOG}"
}
date {
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
}
}
if [type] == "windows_event" {
grok {
pattern => "%{SYSLOGTIMESTAMP:evtime} %{SYSLOGHOST:winhost} %{GREEDYDATA:message}"
}
}
}
output {
elasticsearch {
host => "localhost"
port => 9200
index => "logs-%{+YYYY.MM.dd}"
}
}
Ничего хитрого. Дневные индексы (logs-2012.06.27) - так удобнее потом чистить старые данные простым удалением индекса, без шардинга внутри.
Производительность на одном узле
Машина - сервер с 8 ядрами, 16 ГБ RAM, SSD под ES-данные. JVM для Logstash настроили на -Xmx512m - больше давать не нужно, узкое место там не heap.
На пиковой нагрузке (утренний старт бизнеса + ночной batch-процесс одновременно) получаем около 50 тысяч событий в минуту суммарно. ES при этом съедает примерно 4-5 ГБ heap, индексация не проседает. Logstash CPU - 1-1,5 ядра на grok-парсинг.
Два момента, на которые наступили:
Первое - grok на Windows Event Log. Формат, который гонит nxlog, немного отличается от стандартного syslog, особенно в части EventID и уровня важности. Паттерн пришлось дописывать руками, стандартный %{SYSLOGLINE} не справился. Потратили полдня на отладку через http://grokdebug.herokuapp.com - очень рекомендуем, экономит время.
Второе - маппинг полей в ES. По умолчанию Elasticsearch сам угадывает тип поля при первой индексации. Если в первом событии response_code пришёл как строка, а дальше как число - индекс ломается с ошибкой mapping conflict. Мы заранее положили явный mapping через PUT на новый индекс перед первой записью. Не пожалели.
Что в итоге
Поиск по логам через curl работает: curl 'localhost:9200/logs-*/_search?q=status:500&pretty' даёт список 500-х за все дни мгновенно. Клиентские инженеры освоили базовые запросы за час.
Для сопровождения такой инфраструктуры важно сразу договориться о retention - мы настроили cron, который удаляет индексы старше 30 дней. Иначе диск закончится незаметно и в неподходящий момент.
Elasticsearch как поисковый движок для логов ведёт себя предсказуемо. На одном узле, без репликации, без кластерных ухищрений - всё работает. Когда объём вырастет и понадобится отказоустойчивость, будем думать про второй узел и реплики шардов. Пока нагрузка позволяет обходиться одной машиной.
- Syslog-ng PE и Elasticsearch: переводим централизованный syslog с rsyslog · 19 марта 2012
- Взломали роутер, логи стёрты: настраиваем центральный syslog-сервер · 4 сентября 2002