Fluentd - описание

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

Прин­цип рабо­ты fluentd очень про­стой. Он при­ни­ма­ет дан­ные от раз­лич­ных источ­ни­ков, про­ве­ря­ет есть ли соот­вет­ствие по опре­де­лен­но­му кри­те­рию. После про­вер­ки отправ­ля­ет полу­чен­ное сооб­ще­ние на хра­не­ние или обработку.

Кон­фи­гу­ра­ци­он­ный файл нахо­дит­ся по адре­су /etc/td-agent/td-agent.conf и состо­ит из 6ти так назы­ва­е­мых сек­ций. Основ­ные мы сей­час рассмотрим.

  • source — сек­ция опи­сы­ва­ет источ­ник дан­ных. В этом раз­де­ле мы опи­сы­ва­ем то, отку­да к нам посту­па­ют дан­ные, их источник.
  • match — эта сек­ция опи­сы­ва­ет, что нам делать с дан­ны­ми, куда их напра­вить. Будь это пере­да­ча дру­го­му при­ло­же­нию или запись в файл.
  • filter — не часто при­хо­дит­ся исполь­зо­вать эту сек­цию, поз­во­ля­ет нам изме­нять полу­чен­ные данные.
  • system — содер­жит настрой­ки приложения.
  • label — поз­во­ля­ет объ­еди­нить сек­ции match и filter. Упро­ща­ет внут­рен­ний роутинг, гру­бо гово­ря, будем в кон­фи­гу­ра­ции исполь­зо­вать мень­ше тегов.
  • include — поз­во­ля­ет под­клю­чать кон­фи­гу­ра­ци­он­ные фай­лы. Полез­но при боль­шом коли­че­стве источников.

Основ­ное назна­че­ние раз­де­лов кон­фи­гу­ра­ции разо­бра­ли, теперь при­сту­пим к настрой­ке. Будем с одной маши­ны отправ­лять логи при помо­щи rsyslog по tcp протоколу.

Создание файла конфигурации

Для упро­ще­ния редак­ти­ро­ва­ния я создал новый файл в дирек­то­рии /etc/td-agent — host.conf. В основ­ном фай­ле кон­фи­гу­ра­ции td-agent.conf, кото­рый рас­по­ло­жен в этой же дирек­то­рии, доба­вил строч­ку в кон­це @include host.conf. Теперь кон­фи­гу­ра­ци­он­ный файл готов к прав­кам, откро­ем наш создан­ный host.conf.

source

Как и писал выше, в этом раз­де­ле мы будем опи­сы­вать источ­ник дан­ных для хра­не­ния. Мы будем при­ни­мать логи по сети от дру­го­го сер­ве­ра и скла­ды­вать их у себя в опре­де­лен­ной пап­ке. Для это­го доба­вим в кон­фиг следующее:

[codesyntax lang="php"]

[/codesyntax]

Этот кон­фиг гово­рит нам, что мы будем исполь­зо­вать вхо­дя­щий пла­гин syslog, слу­шать он будет порт 42185, на этот порт мы будем отправ­лять логи из дру­гих машин и поме­чать тегом rsyslog, этот тег мы будем исполь­зо­вать в сек­ции match.

Source: откуда брать данные

В бло­ке source содер­жит­ся инфор­ма­ция о том, отку­да нуж­но брать дан­ные. Fluentd может при­ни­мать дан­ные из раз­лич­ных источ­ни­ков: это логи при­ло­же­ний на раз­лич­ных язы­ках про­грам­ми­ро­ва­ния (Python, PHP, Ruby, Scala, Go, Perl, Java), логи баз дан­ных, логи с раз­лич­ных аппа­рат­ных устройств, дан­ные ути­лит мони­то­рин­га…. С пол­ным спис­ком воз­мож­ных источ­ни­ков дан­ных мож­но озна­ко­мить­ся здесь. Для под­клю­че­ние источ­ни­ков исполь­зу­ют­ся спе­ци­а­ли­зи­ро­ван­ные плагины.
В чис­ло стан­дарт­ных пла­ги­нов вхo­дят http (исполь­зу­ет­ся для при­ё­ма HTTP-сооб­ще­ний) и forward (исполь­зу­ет­ся для при­ё­ма TCP-паке­тов). Мож­но исполь­зо­вать оба этих пла­ги­на одновременно.
Пример:

Как вид­но из при­ве­дён­но­го при­ме­ра, тип пла­ги­на ука­зы­ва­ет­ся в дирек­ти­ве type, а номер пор­та — в дирек­ти­ве port.
Коли­че­ство источ­ни­ков дан­ных ничем не огра­ни­че­но. Каж­дый источ­ник дан­ных опи­сы­ва­ет­ся в отдель­ном бло­ке <source>.
Все собы­тия, при­ня­тые из источ­ни­ков, пере­да­ют­ся марш­ру­ти­за­то­ру сооб­ще­ний. Каж­дое собы­тие име­ет три атри­бу­та: tag, time и record. На осно­ва­нии атри­бу­та tag при­ни­ма­ет­ся реше­ние о том, куда долж­ны быть пере­на­прав­ле­ны собы­тия (подроб­нее об этом пой­дёт речь ниже). В атри­бу­те time ука­зы­ва­ет­ся вре­мя (это дела­ет­ся авто­ма­ти­че­ски), а в атри­бу­те record — дан­ные в фор­ма­те JSON.
При­ве­дём при­мер опи­са­ния события:

match

Сооб­ще­ния мы уже можем при­ни­мать, теперь нуж­но их обра­бо­тать. Кон­фи­гу­ра­ция обработчика:

[codesyntax lang="php"]

[/codesyntax]

Здесь я буду исполь­зо­вать пла­гин copy, так как в буду­щем соби­ра­юсь не толь­ко сохра­нять логи в файл, но и отправ­лять в дру­гие источ­ни­ки, поэто­му type ука­зы­ва­ем copy. Далее внут­ри match объ­яв­ля­ем сек­цию store в кото­рой исполь­зу­ем пла­гин file. Этот пла­гин запи­сы­ва­ет посту­па­ю­щие сооб­ще­ния в файл, в дан­ной кон­фи­гу­ра­ции есть опция time_slice_format %Y%m%d, она гово­рит, что нуж­но сохра­нять один файл на в сут­ки. Дру­ги­ми сло­ва­ми, на одни сут­ки у нас будет один файл с логом.
Все, теперь мы гото­вы при­ни­мать логи. Пере­за­пу­стим fluentd(/etc/init.d/td-agent restart) и при­сту­пим к настрой­ке rsyslog на машине-отправителе.

Match: что делать с данными

В сек­ции Match ука­зы­ва­ет­ся, по каком при­зна­ку будут отби­рать­ся собы­тия для после­ду­ю­щей обра­бот­ки. Для это­го исполь­зу­ют­ся спе­ци­а­ли­зи­ро­ван­ные плагины.

К стан­дарт­ным пла­ги­нам выво­да отно­сят­ся match и forward:

В при­ве­дён­ном фраг­мен­те ука­за­но, что все собы­тия, отме­чен­ные тэга­ми myapp и access, нуж­но сохра­нять в фай­ле, путь к кото­ро­му ука­зы­ва­ет­ся в дирек­ти­ве path. Обра­тим вни­ма­ние на то, что собы­тия, кото­рые поми­мо тэгов myapp и access отме­че­ны ещё и дру­ги­ми тэга­ми, в файл отправ­ле­ны не будут.
Крат­ко рас­смот­рим осо­бен­но­сти син­так­си­са дирек­ти­вы match:

  • сим­вол * озна­ча­ет соот­вет­ствие любой части тэга (если ука­зать <match a.*>, то a.b будет соот­вет­ство­вать задан­но­му усло­вию, а a.b.c — нет);
  • ** озна­ча­ет соот­вет­ствие любо­му тэгу (если ука­зать <match **>, то задан­но­му усло­вию будут соот­вет­ство­вать и a, и a.b., и a.b.c);
  • {x, y, z} озна­ча­ет соот­вет­ствие по край­ней мере одно­му из тэгов, ука­зан­ных в фигур­ных скоб­ках (если ука­зать <match {a, b}>, то а и b будут соот­вет­ство­вать задан­но­му усло­вию, а с — нет);
  • фигур­ные скоб­ки мож­но исполь­зо­вать в соче­та­нии с сим­во­ла­ми * и **, напри­мер: <match {a, b}. c.*> или <match {a.*, b}.c>*;
  • <match a b> озна­ча­ет соот­вет­ствие тэгам a и b одновременно;
  • <match a.** b.*> озна­ча­ет соот­вет­ствие тэгам a, a.b и a.b.c (пер­вая часть) и b.d (вто­рая часть).

Fluentd про­ве­ря­ет собы­тия на соот­вет­ствие тэгам в том поряд­ке, в кото­ром бло­ки match сле­ду­ют друг за дру­гом в кон­фи­гу­ра­ци­он­ном фай­ле. Сна­ча­ла ука­зы­ва­ют­ся соот­вет­ствия част­но­го харак­те­ра, а затем — более общие соот­вет­ствия. Если это пра­ви­ло нару­ше­но, Fluentd кор­рект­но рабо­тать не будет. Так, фраг­мент вида

содер­жит ошиб­ку: сна­ча­ла в нём ука­за­ны пре­дель­но общие сов­па­де­ния (<match **> озна­ча­ет, что в файл нуж­но запи­сы­вать собы­тия, отме­чен­ные любым тэгом), а затем — част­ные. Допу­щен­ная ошиб­ка при­ве­дёт к тому, что собы­тия с тэга­ми myapp и access запи­сы­вать­ся вооб­ще не будут. Что­бы все рабо­та­ло так, как надо, фраг­мент дол­жен выгля­деть так:

Include: объединяем конфигурационные файлы

Дирек­ти­вы мож­но импор­ти­ро­вать из одно­го кон­фи­гу­ра­ци­он­но­го фай­ла в дру­гой и объ­еди­нять. Эта опе­ра­ция осу­ществ­ля­ет­ся в бло­ке include:

В этой дирек­ти­ве мож­но ука­зы­вать путь к одно­му или несколь­ким фай­лам с ука­за­ни­ем мас­ки или URL:

System: устанавливаем дополнительные настройки

В бло­ке System мож­но уста­но­вить допол­ни­тель­ные настрой­ки, напри­мер, задать уро­вень логги­ро­ва­ния (подроб­нее см. здесь), вклю­чить ии отклю­чить опцию уда­ле­ния повто­ря­ю­щих­ся запи­сей из логов и т.п.

Поддерживаемые типы данных

Каж­дый пла­гин для Fluentd обла­да­ет опре­де­лён­ным набо­ром пара­мет­ров. Каж­дый пара­метр в свою оче­редь ассо­ци­и­ру­ет­ся с опре­де­лен­ным типом данных.
При­ве­дём спи­сок типов дан­ных, кото­рые под­дер­жи­ва­ют­ся в Fluentd:

  • string — строка;
  • integer — целое число;
  • float — чис­ло с пла­ва­ю­щей точкой;
  • size — чис­ло байт; воз­мож­ны сле­ду­ю­щие вари­ан­ты записи: 
    • <целое число>k — раз­мер в килобайтах;
    • <целое число>g — раз­мер в гигабайтах;
    • <целое число>t — раз­мер терабайтах;
    • если ника­кой еди­ни­цы изме­ре­ния не ука­за­но, то зна­че­ние в поле size будет вос­при­ня­то как чис­ло байт.
  • time — вре­мя; воз­мож­ны сле­ду­ю­щие вари­ан­ты записи: 
    • <целое число>s — вре­мя в секундах;
    • <целое число>m — вре­мя в минутах;
    • <целое число>h — вре­мя в часах;
    • <целое число>d — вре­мя в днях;
    • если ника­кой еди­ни­цы изме­ре­ния не ука­за­но, что зна­че­ние в поле time будет вос­при­ня­то как коли­че­ство секунд.
  • array — мас­сив JSON;
  • hash — объ­ект JSON.

Плагины Fluentd: расширяем возможности

В Fluentd исполь­зу­ет­ся 5 типов пла­ги­нов: пла­ги­ны выво­да, пла­ги­ны вво­да, пла­ги­ны буфе­ри­за­ции, пла­ги­ны форм и пла­ги­ны парсинга.

Плагины ввода

Пла­ги­ны вво­да исполь­зу­ют­ся для полу­че­ния логов из внеш­них источ­ни­ков. Обыч­но такой пла­гин созда­ет пото­ко­вый сокет (thread socket) и про­слу­ши­ва­ю­щий сокет (listen socket). Мож­но так­же настро­ить пла­гин так, что он будет полу­чать дан­ные из внеш­не­го источ­ни­ка с опре­де­лён­ной периодичностью.
К пла­ги­нам вво­да относятся:

  • in_forward — про­слу­ши­ва­ет TCP-сокет;
  • in_http — при­ни­ма­ет сооб­ще­ния, пере­да­ва­е­мые в POST-запросах;
  • in_tail — счи­ты­ва­ет сооб­ще­ния, запи­сан­ные в послед­них стро­ках тек­сто­вых фай­лов (рабо­та­ет так же, как коман­да tail -F);
  • in_exec — с помо­щью это­го пла­ги­на мож­но запус­кать сто­рон­нюю про­грам­му и полу­чать её лог собы­тий; под­дер­жи­ва­ют­ся фор­ма­ты JSON, TSV и MessagePack;
  • in_syslog — с помо­щью это­го пла­ги­на мож­но при­ни­мать сооб­ще­ния в фор­ма­те syslog по про­то­ко­лу UDP;
  • in_scribe — поз­во­ля­ет полу­ча­ет сооб­ще­ния в фор­ма­те Scribe (Scribe — это тоже кол­лек­тор логов, раз­ра­бо­тан­ный Facebook).

Плагины вывода

Пла­ги­ны выво­да делят­ся на три группы:

  • пла­ги­ны без буфе­ри­за­ции — не сохра­ня­ют резуль­та­ты в буфе­ре и момен­таль­но пишут их в стан­дарт­ный вывод;
  • с буфе­ри­за­ци­ей — делят собы­тия на груп­пы и запи­сы­ва­ют пооче­ред­но; мож­но уста­нав­ли­вать лими­ты на коли­че­ство хра­ни­мых собы­тий, а так­же на коли­че­ство собы­тий, поме­ща­е­мых в очередь;
  • с раз­де­ле­ни­ем по вре­мен­ным интер­ва­лам — эти пла­ги­ны по сути явля­ют­ся раз­но­вид­но­стью пла­ги­нов с буфе­ри­за­ци­ей, толь­ко собы­тия делят­ся на груп­пы по вре­мен­ным интервалам.

К пла­ги­нам без буфе­ри­за­ции относятся:

  • out_copy — копи­ру­ет собы­тия в ука­зан­ное место (или несколь­ко мест);
  • out_null — этот пла­гин про­сто выбра­сы­ва­ет пакеты;
  • out_roundrobin — запи­сы­ва­ет собы­тия в раз­лич­ные лока­ции выво­да, кото­рые выби­ра­ют­ся мето­дом кру­го­во­го перебора;
  • out_stdout — момен­таль­но запи­сы­ва­ет собы­тия в стан­дарт­ный вывод (или в файл лога, если он запу­щен в режи­ме демона).

В чис­ло пла­ги­нов с буфе­ри­за­ци­ей входят:

  • out_exec_filter — запус­ка­ет внеш­нюю про­грам­му и счи­ты­ва­ет собы­тие из её вывода;
  • out_forward — пере­да­ёт собы­тия на дру­гие узлы fluentd;
  • out_mongo (или out_mongo_replset) — пере­да­ёт запи­си в БД MongoDB.

Плагины буферизации

Пла­ги­ны буфе­ри­за­ции исполь­зу­ют­ся в каче­стве вспо­мо­га­тель­ных для пла­ги­нов выво­да, исполь­зу­ю­щих буфер. К этой груп­пе пла­ги­нов относятся:

  • buf_memory — изме­ня­ет объ­ём памя­ти, исполь­зу­е­мой для хра­не­ния буфе­ри­зо­ван­ных дан­ных (подроб­нее см. в офи­ци­аль­ной документации);
  • buf_file — даёт воз­мож­ность хра­нить содер­жи­мое буфе­ра в фай­ле на жёст­ком диске.

Более подроб­но о том, как рабо­та­ют пла­ги­ны буфе­ри­за­ции, мож­но про­чи­тать здесь.

Плагины форматирования

С помо­щью пла­ги­нов фор­ма­ти­ро­ва­ния мож­но изме­нять фор­мат дан­ных, полу­чен­ных из логов. К стан­дарт­ным пла­ги­нам этой груп­пы относятся:

  • out_file — поз­во­ля­ет касто­ми­зи­ро­вать дан­ные, пред­став­лен­ные в виде «вре­мя — тэг — запись в фор­ма­те json»;
  • json — уби­ра­ет из запи­си в фор­ма­те json поле «вре­мя» или «тэг»;
  • ltsv — пре­об­ра­зу­ет запись в фор­мат LTSV;
  • single_value — выво­дит зна­че­ние одно­го поля вме­сто целой записи;
  • csv — выво­дит запись в фор­ма­те CSV/TSV.

Более подроб­но о пла­ги­нах фор­ма­ти­ро­ва­ния мож­но про­чи­тать здесь.

Плагины парсинга

Эти пла­ги­ны исполь­зут­ся для того, что­бы пар­сить спе­ци­фи­че­ские фор­ма­ты дан­ных на вхо­де в слу­ча­ях, когда это невоз­мож­но сде­лать при помо­щи штат­ных средств. С подроб­ной инфор­ма­ци­ей о пла­ги­нах пар­син­га мож­но озна­ко­мить­ся здесь.

Есте­ствен­но, что все пла­ги­ны fluentd в рам­ках обзор­ной ста­тьи опи­сать невоз­мож­но — это тема для отдель­ной пуб­ли­ка­ции. С пол­ным спис­ком всех суще­ству­ю­щих на сего­дняш­ний день пла­ги­нов мож­но озна­ко­мить­ся на этой стра­ни­це.

Общие параметры для всех плагинов

Для всех пла­ги­нов ука­зы­ва­ют­ся так­же сле­ду­ю­щие параметры:

  • type — тип;
  • id — иден­ти­фи­ка­ци­он­ный номер;
  • log_level — уро­вень логги­ро­ва­ния (см. выше).

На офи­ци­аль­ном сай­те fluentd выло­же­ны гото­вые кон­фи­гу­ра­ци­он­ные фай­лы, адап­ти­ро­ван­ные под раз­лич­ные сце­на­рии исполь­зо­ва­ния (см. здесь).

Вывод данных и интеграция с другими решениями

Собран­ные с помо­щью Fluentd могут быть пере­да­ны для хра­не­ния и даль­ней­шей обра­бот­ки в базы дан­ных (MySQL, PostgreSQL, CouchBase, CouchDB, MongoDB, OpenTSDB, InfluxDB) рас­пре­де­лен­ные фай­ло­вые систе­мы (HDFS — см. так­же ста­тью об инте­гра­ции Fluentd c Hadoop) облач­ные сер­ви­сы (AWS, Google BigQuery), поис­ко­вые инстру­мен­ты (Elasticsearch, Splunk, Loggly).
Для обес­пе­че­ния воз­мож­но­сти поис­ка и визу­а­ли­за­ции дан­ных доволь­но часто исполь­зу­ет­ся ком­би­на­ция Fluentd+Elasticsearc+Kibana (подроб­ную инструк­цию по уста­нов­ке и настрой­ке см., напри­мер, здесь).

Пол­ный спи­сок сер­ви­сов и инстру­мен­тов, кото­рым Fluentd может пере­да­вать дан­ные, раз­ме­щён здесь. На офи­ци­аль­ном сай­те опуб­ли­ко­ва­ны так­же инструк­ции по исполь­зо­ва­нию Fluentd в связ­ке с дру­ги­ми решениями.

Rsyslog

Rsyslog — попу­ляр­ный, быст­рый, гиб­кий сер­вис для управ­ле­ния лога­ми. Нам он нужен в част­но­сти, что­бы отда­вать логи на маши­ну с уста­нов­лен­ным fluentd.

Установка rsyslog

Уста­нов­ка очень три­ви­аль­на и про­ста, запуск одной коман­ды сде­ла­ет всё за вас:

yum install rsyslog

 

Настройка отправки логов

Откры­ва­ем файл кон­фи­гу­ра­ции nano /etc/rsyslog.conf и вно­сим правки(под sudo разумеется):

1
*.* @10.0.2.15:42185

Я доба­вил эту стро­ку вна­ча­ле фай­ла, есте­ствен­но адрес и порт ука­зы­ва­ем того хоста, кото­рый будет при­ни­мать логи. Теперь все логи кото­рые опи­са­ны в кон­фи­гу­ра­ци­он­ных фай­лах будут успеш­но достав­ле­ны на маши­ну с fluentd демо­ном. Пере­за­пус­ка­ем service rsyslog restart и через неко­то­рое вре­мя по ука­зан­но­му пути, кото­рый мы ука­за­ли в кон­фи­ге fluentd, обна­ру­жим фай­лы с лога­ми от уда­лен­но­го сервера.

Вот таким про­стым спо­со­бом мы можем сде­лать самую эле­мен­тар­ную схе­му отправ­ки и хра­не­ния логов на спе­ци­аль­ном сервере.

======================================================