Logstash - описание

Thank you for reading this post, don't forget to subscribe!

Что такое Logstash

Logstash — это кон­вей­ер обра­бот­ки дан­ных, кото­рый полу­ча­ет сырые дан­ные (напри­мер, логи) из одно­го или несколь­ких  источ­ни­ков, обра­ба­ты­ва­ет их и улуч­ша­ет филь­тра­ми, а затем отправ­ля­ет резуль­тат одно­му или несколь­ким полу­ча­те­лямElastic реко­мен­ду­ет в каче­стве полу­ча­те­ля исполь­зо­вать Elasticsearch, но на самом деле мож­но исполь­зо­вать всё, что душе угод­но: STDOUT, WebSocket, обыч­ные соке­ты, оче­ре­ди сооб­ще­ний — выбор огромный.

Logstash схема

Установка

Если на хосте уста­нов­ле­на Java, то мож­но про­сто ска­чать  архив, рас­па­ко­вать его и запу­стить bin/logstash -f logstash.conf. Для запус­ка, прав­да, пона­до­бит­ся файл кон­фи­гу­ра­ции, но для про­стей­ших при­ме­ров сой­дёт что-нибудь вро­де input {STDIN {}} output {STDOUT {}}.

Да, люби­те­лям кон­тей­не­ров мож­но не утруж­дать себя скач­кой архи­вов и исполь­зо­вать завод­ской Docker образ:

Конфигурация, кодеки и «Hello World!»

Итак, архив ска­чан, что даль­ше? Как я упо­мя­нул выше, для запус­ка Logstash нужен файл кон­фи­гу­ра­ции. Напри­мер, такой:

С ним Logstash будет брать дан­ные из кон­со­ли, делать свою магию по-умол­ча­нию, и выда­вать резуль­тат назад в консоль.

Hello world

Я нашёл у себя на хосте немно­го логов от Apache2, так что поче­му бы не скор­мить их Logstash и не посмот­реть, что из это­го получится?

А полу­чит­ся мно­го скуч­но­го тек­ста. Logstash запу­стил­ся, ему на вход вошла стро­ка (4) с логом от Apache2, и она тут же пошла на выход с дву­мя новы­ми поля­ми: вре­мен­ной мет­кой 2017-02-13T05:39:12.684Z и име­нем хоста 269a27a16415.

Кодеки

Но мы можем сде­лать вывод более чита­бель­ным. Logstash раз­ре­ша­ет под­клю­чать ко вво­ду и выво­ду раз­лич­ные коде­ки, кото­рые фор­ма­ти­ру­ют поток тек­ста, но не меня­ют его зна­че­ние: добав­ля­ют отсту­пы, архи­ви­ру­ют, пере­во­дят в JSON, и т. п. В нашем слу­чае мы можем исполь­зо­вать rubydebug для того, что­бы он отфор­ма­ти­ро­вал резуль­тат и пока­зал, как имен­но Logstash «видит» дан­ные, с кото­ры­ми работает.

Кон­фи­гу­ра­ция изме­нит­ся совсем чуть-чуть, но резуль­тат ста­нет намно­го человечнее:

Выводим результаты в Elasticsearch

Преж­де чем дви­нуть­ся даль­ше, сто­ит попро­бо­вать кое-что еще. В нача­ле поста я ска­зал, что полу­ча­те­лей дан­ных может быть боль­ше одно­го, и вооб­ще мы можем писать резуль­та­ты пря­мо в Elasticsearch. Это как раз тот слу­чай, когда мож­но одним тело­дви­же­ни­ем под­твер­дить оба пункта.

Так уж ока­за­лось, что в сосед­нем с Logstash кон­тей­не­ром у меня обос­но­вал­ся чистый Elasticsearch с айпиш­кой 172.19.0.2 и пор­том 9200. Что­бы под­клю­чить их друг к дру­гу, нуж­но доба­вить все­го пару строк в кон­фи­гу­ра­цию Logstash:

Теперь, если пере­за­пу­стить Logstash и сно­ва скор­мить ему  Apache2 логов, в Elasticsearch появит­ся кое что отно­си­тель­но интересное:

Во-пер­вых, там появил­ся новый индекс — logstash-2017.02.12. Во-вто­рых, запу­стив по это­му индек­су поиск, мы полу­чим те же дан­ные, что Logstash писал в STDOUT:

Обрабатываем данные фильтрами

Пока Logstash справ­лял­ся с пере­прав­кой логов из точ­ки А в точ­ку Б, но не делал ниче­го для того, что­бы это дан­ные ста­ли хоть немно­го полез­нее. При­шло вре­мя пере­мен. Кро­ме INPUT и OUTPUT в кон­фи­гу­ра­цию мож­но доба­вить FILTER, и вот там-то основ­ная магия и начнётся.

Филь­тры есть прак­ти­че­ски для все­го: для агре­га­ции мет­рик, мас­ки­ров­ки чув­стви­тель­ных дан­ных (вро­де имён и номе­ров кре­дит­ных карт), добав­ле­ния и уда­ле­ния полей, нахож­де­ния IP по домен­но­му име­ни, нахож­де­ния адре­са по IP (дер­жи­тесь, ком­мен­та­то­ры!), и т.п. Но для нас хоро­шо бы начать с раз­бо­ра стро­ки Apache2 лога на её ком­по­нен­ты: IP, путь, user agent, и так далее. Фильтр, кото­рый зани­ма­ет­ся подоб­ной рабо­той, назы­ва­ет­ся grok.

Grok

Grok — это основ­ной инстру­мент для при­да­ния фор­мы и струк­ту­ры сплош­но­му мас­си­ву тек­ста. Рабо­та­ет это так: из пред­уста­нов­лен­ных пат­тер­нов (IP, Number, Word, …) мы соби­ра­ем стро­ку-шаб­лон, кото­рая по струк­ту­ре повто­ря­ет ту, кото­рую мы соби­ра­ем­ся пар­сить. Напри­мер, если бы мои логи выгля­де­ли так:

То я бы исполь­зо­вал такой шаб­лон для их разбора:

После обра­бот­ки филь­тром в логах появи­лись бы новые поля: sequenceclient и target. Те самые, кото­рые ука­за­ли в шаблоне.

Кро­ме эле­мен­тар­ных пат­тер­нов вро­де Number есть более слож­ные, кото­рые опи­сы­ва­ют извест­ные фор­ма­ты логов цели­ком. Напри­мер, COMBINEDAPACHELOG опи­сы­ва­ет стро­ку лога от Apache2. Вот её-то и мож­но попро­бо­вать в действии.

Новая кон­фи­гу­ра­ция:

И реак­ция Logstash на неё:

Сра­бо­та­ло!

Дополнительные настройки GROK

Но обра­бот­ку мож­но сде­лать еще луч­ше. В сере­дине рас­пар­ше­но­го лога зате­са­лось поле message, кото­рое дуб­ли­ру­ет всё, что мы толь­ко что рас­пар­си­ли. Хоро­шо бы его убрать. А в grok как раз есть допол­ни­таль­ные настрой­ки, одна из кото­рых назы­ва­ет­ся remove_field — как раз то, что нам нужно:

Теперь резуль­тат про­сто пре­кра­сен. Но мы можем сде­лать его ещё лучше.

geoip фильтр

Как сле­ду­ет из назва­ния, geoip кон­вер­ти­ру­ет IP адрес в коор­ди­на­ты на кар­те и сопут­ству­ю­щий улич­ный адрес. Я заме­нил доке­ров­скую айпиш­ку одно­го из логов на свою внеш­нюю, вклю­чил geoip, и про­пу­стил лог через Logstash еще раз:

 

Резуль­тат:

geoip взял clientip поле, кото­рое создал grok, и потом доба­вил несколь­ко соб­ствен­ных полей. Мне даже не при­шлось что-то выка­чи­вать из ваших интер­не­тов, что­бы это заработало.

А теперь, когда обра­бо­тан­ные дан­ные сте­ка­ют­ся в Elasticsearch, мы можем исполь­зо­вать его поиск на пол­ную катуш­ку и начать зада­вать вопро­сы. Были ли посе­ти­те­ли из Oakville?

Конеч­но были. А сколь­ко HTTP оши­бок было вче­ра? Пытал­ся ли кто-нибудь зай­ти в админ­ку бло­га без спро­са? Сколь­ко раз? Где он живёт?