Рубрика:
Администрирование /
DevOps
|
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|
СЕРГЕЙ ЯРЕМЧУК, сисадмин/DevOps, автор более 1000 статей и шести книг. С «СА» с первого номера. Интересы: сетевые технологии, защита информации, свободные ОС, yaremchuk@samag.ru
Настраиваем стек ELK для централизованного хранения журналов
В статье разберем, как настроить магическую тройку Elasticsearch + Logstash + Kibana
После настройки сервисов и деплоя приложений журналы, как правило, разбросаны по нескольким каталогам, и к ним нередко обращаются только в случае появления ошибки.
Проблема в том, что сервис обычно представлен несколькими подсистемами, которые относятся к серверной части (LEMP, Redis, RabbitMQ...), и само приложение нередко состоит из микросервисов. Все может быть расположено на разных серверах, что усложняет поиск проблемы. К тому же обнаруженная ошибка могла появиться гораздо раньше (например, после последнего деплоя), но не была так явно выражена (выходные или праздники, нагрузка меньше).
Если проверять журналы по одному, то проблему сразу обнаружить не получится, так как она бывает не очевидна, да и тратится больше времени на обнаружение связи и закономерности. Поэтому, когда количество cерверов и сервисов начинает превышать разумный предел, не обойтись без инструмента, позволяющего хранить и анализировать записи журналов.
Особенно такого средства не хватает в случае, когда ведется активная разработка и к записям журналов нужно допустить множество людей с выдачей нужных прав. Это заодно повышает безопасность, т.к. для анализа журнала не нужно прямого доступа разработчиков к самому серверу, плюс мы можем хранить историю за любой период, хранение на другом сервере позволяет их защитить в случае взлома. Плюс меньше отвлекает сисадмина, т.к. не все могут знать, где находится нужный журнал. Дополнительно получаем разные «плюшки» в виде удобного отбора информации в визуальной среде, с возможностью сохранения фильтров, для последующего использования, алерты, графики, и многое другое.
Стек ELK
На самом деле, чтобы реализовать подобную схему, нужны три инструмента:
- кто-то должен отправить данные (это может быть rsyslog или специальный агент),
- кто-то их собирает (с предварительной обработкой),
- и, наконец, сам анализатор.
Здесь могут быть варианты, каждый имеет свои плюсы и минусы, и очень легко запутаться с выбором. А выбирать есть из чего, реализаций агрегаторов журналов, как свободных, так и коммерческих, реализованных в виде облачного решения, предостаточно: Graylog2, Loggly, Log4j, Splunk, Logentries, PaperTrail, Fluentd, ArcSight, макрософтовское Log Analytics Azure и другие. Список на самом деле очень большой.
Очень тяжело советовать идеальную конфигурацию, часто бывает, что подходит одним, совершенно не приживается в другой обстановке, при тех же исходных данных. Но, наверное, самым популярным из Open Source-решений является стек ELK – Elasticsearch, Logstash, Kibana. Все они разрабатываются нидерландской Elasticsearch BV [1], поэтому очень хорошо работают в связке и просто настраиваются.
Kibana – это удобный инструмент, позволяющий на порядок быстрее локализовать проблемы |
Основой является поисковый движок Elasticsearch, построенный на базе библиотеки Apache Lucene, используемый для индексирования и поиска информации в любом типе документов. Язык запросов достаточно простой, хотя и потребует некоторого времени на усвоение. Для индексации большого количества данных несколько копий Elasticsearch легко объединяются в кластер.
Logtash разработан Джорданом Сисселем (Jordan Sissel) как автономный инструмент для обработки большого количества журналов из нескольких источников, а после того как Джордан присоединился в 2013 году к Elasticsearch, этот продукт стал неотъемлемой частью платформы ELK.
Поддерживается множество входных типов данных – журналы, метрики разных сервисов и служб. Полученная информация фильтруется, идентифицируется (при помощи Grok, склеивание, мутация, удаление...), нормализуется, что упрощает дальнейшую обработку.
Результат обычно отдается в Elasticsearch (размещенный на этом же сервере или удаленной системе), но это может быть другой приемник данных – email, stdout, файл. То есть фактически вместо Elasticsearch можем использовать любое другое решение или обработчик.
Но у Logstash есть одна проблема – производительность. Он написан на Ruby и требует запуска JVM, в результате он очень любит память, особенно если задействуется много конвейеров и фильтрация.
Как результат, появился проект Lumberjack – написанное на Go приложение, представляющее легкую реализацию сборщика журналов и отправку на удаленный хост. Со временем проект переименовали в Logstash-Forwarder, вторая версия протокола стала основой нового семейства форвардеров под названием Beats – специальных клиентов, обеспечивающих сбор и отправку данных в Logstash.
В частности, за сбор данных с журналов отвечает Filebeat, причем современные версии позволяют производить предварительную фильтрацию. Кроме этого, также доступны Winlogbeat (сбор событий Windows Event Logs), Metricbeat (метрики), Packetbeat (сетевая информация) и Heartbeat (uptime). Все клиенты доступны для платформ Linux, Windows и Mac OSX. В статье разберем, как настраивать Filebeat.
И, наконец, Kibana – это веб-интерфейс для вывода индексированных Elasticsearch логов. Кстати, изначально Kibana была привязана к данным именно Logstash и только после перехода разработчика Rashid Khan в Elasticsearch переориентирована на информацию, выводимую Elasticsearch. При помощи веб-интерфейса можно отбирать нужную информацию для анализа. Причем доступны не только сами записи, но на их основе можно строить разные графики и таблицы. При установке дополнительного X-Pack будут доступны отчеты, визуализация геоинформации, мониторинг, алерты, интеграция с LDAP и многое другое. Предлагается X-Pack под несколькими лицензиями [2], есть и Free.
Настройка Filebeat
Нужно отметить, что с установкой и обновлением всех продуктов линейки проблем нет. Доступны как apt и yum-репозитории, так и deb и rpm-файлы. В сети есть готовые плейбуки для Ansible и других систем управления конфигурацией. Причем очень удобно – в репозитории можно найти абсолютно любую версию, когда-то выпущенную командой. Обновление вверх обычно происходит без проблем, старые индексы подхватываются с лета. Проблема может быть в несовместимости параметров в конфигурационных файлах. А вот вниз далеко откатить уже не всегда возможно, старая версия не видит новых индексов. Актуальной версией является 6.1.2, но я пока использую 5.6, поэтому буду ориентироваться на нее. Хотя существенных отличий нет.
Подключаем репозиторий и ставим пакеты:
$ sudo apt-get install apt-transport-https
$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
$ echo "deb https://artifacts.elastic.co/packages/5.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-5.x.list
$ sudo apt-get update && sudo apt-get install filebeat
Сервис помечен как enable для автозапуска, но в Ubuntu 16.04 для всех продуктов от Elasticsearch почему-то это не происходит.
$ sudo systemctl enable filebeat
Все настройки производятся в конфигурационном файле /etc/filebeat/filebeat.yml, после установки уже есть готовый шаблон с минимальными настройками. Там же лежит файл filebeat.full.yml (в новой версии filebeat.reference.yml), в котором прописаны все установки, доступные для Filebeat [3].
В файле для Filebeat нужно указать, что брать и куда отправлять. При этом указываются тип документа (input_type, log_type и document_type, он потом будет доступен в поиске) и специфические параметры подключения. По умолчанию Filebeat собирает все файлы в пути /var/log/*.log, то есть все файлы в каталоге /var/log, заканчивающиеся на .log.
filebeat.prospectors:
- type: log
paths:
- /var/log/messages
- /var/log/*.log
Очень удобно, что поддерживаются шаблоны, поэтому можно задать что-то вроде /var/www/microservices/*/shared/var/logs/*.log и не беспокоиться при появлении нового микросервиса, что его журналы не попадут в Filebeat. Тип указывает на характер данных – log, redis, docker stdin, udp. Дополнительные опции позволяют отобрать определенные файлы и события. Так, параметр exclude_files позволяет задать шаблон файлов, которые не нужно собирать. По умолчанию экспортируются все строки, используя include_lines и exclude_lines, задаются или исключаются строки из сбора. Их можно указывать в как общем для всех, так и для каждого paths.
include_lines: ['^ERR', '^WARN']
exclude_lines: ['^OK']
Если определены оба варианта, Filebeat сначала выполняет include_lines, а затем exclude_lines. Порядок, в котором они прописаны, значения не имеет. Кроме этого, в описании задаются при необходимости кодировка, теги, поля и тип документа.
Источники с одинаковыми input_type, log_type и document_type можно указывать по одному в строке. Если они отличаются, то создается отдельная запись. Создадим запись, собирающую ошибки nginx, и укажем поле nginx_error, которое затем будем использовать в фильтрах.
- input_type: log
paths:
- /var/log/nginx/error.log
fields:
log_type: nginx_error
Раздел Outputs файла указывает, куда нужно отдавать данные. В шаблоне уже есть установки для Elasticsearch и Logstash. Мы отправляем в Logstash, минимально нужно указать только адрес и порт.
output:
logstash:
hosts: ['logstash.host:5044']
Если соединяемся через небезопасную сеть, необходима авторизация по ключу.
output:
logstash:
hosts: ['logstash.host:5044']
tls:
certificate_authorities: ['/etc/ssl/logstash/log.crt']
ssl:
enabled: true
verification_mode: none
supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2]
В случае появления в журнале /var/log/filebeat/filebeat записи:
ERR Connecting error publishing events (retrying): read tcp i/o timeout
следует поиграть параметрами filebeat.spool_size, timeout, bulk_max_size, slow_start, max_retries.
В конце настраивается ротация журналов:
logging:
files:
rotateeverybytes: 10485760
Проверяем настройки:
$ filebeat.sh -configtest -e
Применяем:
$ sudo systemctl start filebeat
$ sudo systemctl status filebeat
Для проверки работы можно использовать шаблон:
$ curl -XPUT 'http://localhost:9200/_template/filebeat' -d@/etc/filebeat/filebeat.template.json {"acknowledged":true}
Настраиваем Logstash
Для Logstash и Elasticsearch нужна Java. Это может быть как официальная Java SE или OpenJDK, имеющаяся с репозиториях дистрибутивов Linux. Но здесь есть нюанс. Сам Elasticsearch отлично ладит с Java 9, а вот для Logstash придется использовать Java 8. Репозиторий добавляется так же.
Ставим:
$ sudo apt install logstash
$ sudo systemctl enable logstash
Конвейер Logstash имеет два обязательных элемента – input и output – и необязательный – filter. Плагины ввода берут данные из источника, выходные записывают по назначению, фильтры изменяют данные по указанному шаблону.
Флаг -e позволяет указать конфигурацию непосредственно в командной строке, что можно использовать для тестирования.
Простой конвейер выглядит так:
$ /usr/share/logstash/bin/logstash -e 'input { stdin { } } output { stdout {} }'
То есть просто выводим то, что пришло на stdin, Logstash продублирует, добавив метку времени.
Все конфигурационные файлы находятся в /etc/logstash. Настройки в /etc/logstash/startup.options, jvm.options определяют параметры JVM и в logstash.yml параметры работы самого сервиса. Важный момент. По умолчанию количество воркеров, обрабатывающих запросы, привязано к количеству CPU. Это можно изменить при помощи параметра pipeline.workers в конфигурационном файле, но в случае проблем с производительностью это может не помочь. Нужно просто добавить еще CPU. Ну и поиграть с другими pipeline-параметрами, в частности:
pipeline.batch.size: 125
pipeline.batch.delay: 5
Сами конвейеры описываются в файлах в каталоге /etc/logstash/conf.d. Он пока пуст. При запуске считываются все файлы, поэтому их можно компоновать как удобно. Очевидны два варианта: файлы по назначению (input, output и filter) или каждый сервис описывать в отдельном файле. Описания плагинов для inputs, outputs и filter, обеспечивающих ту или иную функцию (beats, file), доступны на сайте [4]. После установки в системе уже есть некоторые плагины. Их список можно получить при помощи специальной команды.
$ /usr/share/logstash/bin/logstash-plugin list
Или конкретная группа:
$ /usr/share/logstash/bin/logstash-plugin list --group input
Рисунок 1. Проверяем список плагинов
Периодически их можно обновлять, хотя обычно все обновления приходят с новой версией, а версии выпускаются достаточно часто. Но тем не менее могут быть ситуации, когда это понадобится.
$ /usr/share/logstash/bin/logstash-plugin update
$ /usr/share/logstash/bin/logstash-plugin install logstash-input-http --no-verify
Этой же командой добавляются и собственные плагины.
Указываем порт, на котором будем принимать подключение Filebeat.
$ sudo nano /etc/logstash/conf.d/01-input.conf
input {
input {
beats {
port => 5044
ssl => true
ssl_certificate => "/etc/ssl/logstash/logstash.crt"
ssl_key => "/etc/ssl/logstash/logstash.key"
}
}
Как уже говорилось, Logstash может самостоятельно собирать информацию журналов локального узла.
input {
file {
path => "/var/log/nginx/*.log"
}
}
Отдаем данные на Elasticsearch.
$ sudo nano /etc/logstash/conf.d/02-output.conf
output {
elasticsearch {
hosts => ["localhost:9200"]
}
}
Если Elasticsearch работает на другом сервере, то, как и ранее, используем сертификаты. Дополнительно можно указать что-то около 50 параметров для управления соединением и индексацией.
И далее фильтры. В Logstash их тоже около 50, все варианты расписаны в документации [5], наиболее популярный, наверное, Grok, при помощи которого можно отобрать любые неструктурированные данные, причем без особой подготовки. Создаем для примера файл, который будет обрабатывать данные с типом nginx-access.
$ sudo nano /etc/logstash/conf.d/03-nginx-error.conf
filter {
if [type] == "nginx_error" {
grok {
match => { "message" => "(?<timestamp>%{YEAR}[./] %{MONTHNUM}[./]%{MONTHDAY} %{TIME}) \[%{LOGLEVEL:severity}\] %{POSINT:pid}#%{NUMBER}: %{GREEDYDATA:errormessage},
\ client: %{IP:client}, server: \$domain, request: \"%{WORD:method} %{URIPATH:path}\"" }
}
}
}
Рисунок 2. Фильтр Grok, при помощи которого можно отобрать любые неструктурированные данные
Если сравнить c любым сообщением из файла ошибок nginx, то станет очевидно, как создается такой шаблон.
2018/01/30 16:53:25 [error] 1167#1167: *57846 rewrite or internal redirection cycle while internally redirecting to "/index.html", client: 192.168.1.148, server: *.example.org, request: "GET //phpMyAdmin/scripts/setup.php HTTP/1.1"
Logstash после установки уже содержит приблизительно 120 шаблонов буквально на все случаи, и обычно с нуля писать ничего не нужно. Просмотреть варианты можно в github проекта [6]. Свои правила лучше прописать в отдельном файле, задав уникальное имя. На место нахождения каталога с правилами указывает переменная patterns_dir:
patterns_dir => ["./patterns"]
Для проверки корректности правил можно использовать сайт [7], там же можно поискать еще готовые паттерны.
Перезапускаем:
$ sudo service logstash restart
Убеждаемся в журналах, что все работает.
$ tail -f /var/log/logstash/logstash-plain.log
[INFO ][logstash.inputs.beats ] Beats inputs: Starting input listener {:address=>"localhost:5044"}
[INFO ][logstash.pipeline ] Pipeline main started
[INFO ][logstash.agent ] Successfully started Logstash API endpoint {:port=>9600}
Устанавливаем Elasticsearch
Важно: для эластика, возможно, потребуется место. В нашем случае данные за полгода для боевого кластера спокойно умещались в 150 Гб, с переходом на микросервисы объем пришлось увеличить до 1 Тб. Установка стандартна. По умолчанию данные размещаются в /var/lib/elasticsearch, но этот путь можно изменить при помощи переменной path.data.
$ sudo apt install elasticsearch
$ sudo systemctl enable elasticsearch
$ sudo systemctl start elasticsearch
По умолчанию Elasticsearch слушает локальный 9200-й порт. Большинство операций выполняется при помощи обычного curl.
$ curl localhost:9200
{
"name" : "XBzHrYa",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "48m0tuBHR0Cas8AI0iYupA",
"version" : {
"number" : "5.6.6",
"build_hash" : "7d99d36",
"build_date" : "2018-01-09T23:55:47.880Z",
"build_snapshot" : false,
"lucene_version" : "6.6.1"
},
"tagline" : "You Know, for Search"
}
В большинстве случаев лучше так и оставить, для кластера или в случае другой необходимости можно указать внешний IP и изменить порт, если он уже занят.
$ sudo nano /etc/elasticsearch/elasticsearch.yml
#network.host: 192.168.1.2
#http.port: 9200
В общем, поначалу здесь можно ничего не трогать, а приступить к изучению настроек в случае проблем с производительностью. Файл хорошо комментирован, плюс документация. Не без экспериментов, но все настраивается прекрасно. Нужно помнить, что Elasticsearch любит ОЗУ (по умолчанию запускается 2 Гб -Xms2g -Xmx2g), в зависимости от возможности сервера и данных в процессе эксплуатации параметры скорее всего нужно будет переопределить в /etc/elasticsearch/jvm.options. Но больше 50% ОЗУ отдавать не рекомендуется. Это все. Эластик начал индексировать данные.
Список актуальных индексов можно получить при помощи запроса:
$ curl 'localhost:9200/_cat/indices?v'
Чтобы удалить ненужный индекс выполняем:
$ curl -XDELETE 'localhost:9200/filebeat-2018.01.01?pretty'
Для постоянной чистки индексов лучше использовать elasticsearch-curator, который также есть в репозитории.
$ apt install elasticsearch-curator
Настройки работы хранятся в файле /etc/curator/curator.yml. Там описывается подключение к Elasticsearch, и, в общем, его можно не трогать. Далее индекс можно чистить как из командной строки, так и создав готовые настройки. Например, для удаления индексов logstash-*, filebeat-* старше 90 дней подготовим такой файл:
$ sudo vi /etc/curator/delete_indices.yml
---
actions:
1:
action: delete_indices
description: >-
Delete indices older than 90 days (based on index name), for logstash-
and filebeat- prefixed indices.
options:
ignore_empty_list: True
timeout_override:
continue_if_exception: False
disable_action: False
filters:
- filtertype: pattern
kind: regex
value: '^(logstash-|filebeat-).*$'
exclude:
- filtertype: age
source: name
direction: older
timestring: '%Y.%m.%d'
unit: days
unit_count: 90
exclude:
Прописываем запуск в crontab, и нам остается только следить за местом на жестком диске:
0 1 * * * /usr/bin/curator --config /etc/curator/curator.yml /etc/curator/delete_indices.yml 2>/tmp/cron_errors/curator_indices.cron_err
Настройка Kibana
С Kibana то же самое.
$ sudo apt-get install kibana
$ sudo systemctl enable kibana
$ sudo systemctl start kibana
По умолчанию Kibana стартует на localhost:5601. Изменив параметр server.host в файле /etc/kibana/kibana.yml, можно разрешить подключаться удаленно, но так как какой-то аутентификации не предусмотрено, лучше в качестве фронта использовать nginx, настроив обычный proxy_pass и доступ с htaccess. Ну, или посмотреть в сторону X-Pack.
Все. Можно смотреть. Kibana пока ничего не знает об индексах. Нужно указать, что будем искать, для работы нужно указать хотя бы один индекс (индекс по умолчанию). Идем в Management → Index Patterns. Обычно нужно некоторое время подождать, затем указать новый индекс (см. рис. 3). Для filebeat пишем filebeat-*, можно использовать -*. Кибана подхватит шаблон и покажет поля.
Рисунок 3. Настраиваем индекс
Теперь в разделе Discover начнут появляться записи (см. рис. 4).
Рисунок 4. Записи журналов в Kibana
По умолчанию отображаются последние 15 минут, изменить время можно в правом верхнем углу. Выбрав сообщение, можно посмотреть подробно.
Справа отображаются поля. Если выбрать любое, оно будет использовано как фильтр поиска. Таким образом, можно указать файл, сервер, статус запроса и т.д. Далее в строке поиска указываем, что ищем, в самом простом случае только пишем текст (см. рис. 5), на временной метке также будет показано, когда появилась нужная запись. В более сложных случаях придется все-таки прочитать документацию [8].
Рисунок 5. Выполняем запрос
Запросы можно сохранять для повторного использования и для вызова графиков Visualize. Здесь просто. Нажимаем Create new visualization, выбираем тип и сохраненный запрос.
Для удобства из визуализаций создаем Dashboard, на котором будут показаны все данные.
Проект предлагает готовые Dashboard [9], которые можно взять за основу.
К кибане, конечно, нужно привыкнуть, многие находят ее поначалу неудобной, но с опытом приходит понимание, насколько это удобный инструмент, позволяющий на порядок быстрее локализовать проблемы.
- Сайт Elasticsearch – http://www.elastic.co.
- Условия подписки продуктов Elasticsearch – https://www.elastic.co/subscriptions.
- Параметры Filebeat – https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-configuration-details.html.
- Параметры Logstash – https://www.elastic.co/guide/en/logstash/current/working-with-plugins.html.
- Фильтры Logstash – https://www.elastic.co/guide/en/logstash/current/filter-plugins.html.
- GitHub Logstash – https://github.com/logstash-plugins/logstash-patterns-core/tree/master/patterns.
- Проверка Grok – https://grokdebug.herokuapp.com/.
- Cинтаксис запросов в Kibana – https://www.elastic.co/guide/en/elasticsearch/reference/5.6/query-dsl-query-string-query.html#query-string-syntax
- Beats Dashboard – https://www.elastic.co/guide/en/beats/libbeat/1.3/load-kibana-dashboards.html.
Ключевые слова: elasticsearch, kibana, logstash, filebeat, журналы.
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|