Практична примена ЕЛК-а. Постављање логстасх-а

Увод

Приликом постављања другог система, суочили смо се са потребом да обрадимо велики број различитих логова. ЕЛК је изабран као алат. Овај чланак ће говорити о нашем искуству у постављању овог стека.

Не постављамо за циљ да опишемо све његове могућности, али желимо да се посебно концентришемо на решавање практичних проблема. То је због чињенице да иако постоји прилично велика количина документације и готових слика, постоји доста замки, барем смо их пронашли.

Распоредили смо стек преко доцкер-цомпосе. Штавише, имали смо добро написан доцкер-цомпосе.имл, који нам је омогућио да подигнемо стек готово без проблема. И чинило нам се да је победа већ близу, сада ћемо је мало дотерати како би одговарало нашим потребама и то је то.

Нажалост, покушај да се систем конфигурише да прима и обрађује евиденције из наше апликације није био одмах успешан. Стога смо одлучили да је вредно проучавати сваку компоненту посебно, а затим се вратити на њихове везе.

Дакле, почели смо са логстасх-ом.

Окружење, имплементација, покретање Логстасх-а у контејнеру

За примену користимо доцкер-цомпосе експерименти описани овде су спроведени на МацОС и Убунту 18.0.4.

Логстасх слика која је регистрована у нашем оригиналном доцкер-цомпосе.имл је доцкер.еластиц.цо/логстасх/логстасх:6.3.2

Користићемо га за експерименте.

Написали смо посебан доцкер-цомпосе.имл за покретање логстасх-а. Наравно, било је могуће покренути слику из командне линије, али смо решавали специфичан проблем, где смо све покретали из доцкер-цомпосе.

Укратко о конфигурационим датотекама

Као што следи из описа, логстасх се може покренути или за један канал, у ком случају треба да проследи *.цонф датотеку, или за неколико канала, у ком случају треба да проследи датотеку пипелинес.имл, која заузврат , повезаће се са датотекама .цонф за сваки канал.
Ишли смо другим путем. Чинило нам се универзалнијим и скалабилнијим. Стога смо креирали пипелинес.имл, и направили директоријум пипелинес у који ћемо ставити .цонф фајлове за сваки канал.

Унутар контејнера постоји још једна конфигурациона датотека - логстасх.имл. Не дирамо га, користимо га какав јесте.

Дакле, наша структура директоријума:

Практична примена ЕЛК-а. Постављање логстасх-а

Да бисмо примили улазне податке, за сада претпостављамо да је ово тцп на порту 5046, а за излаз ћемо користити стдоут.

Ево једноставне конфигурације за прво покретање. Зато што је почетни задатак лансирање.

Дакле, имамо овај доцкер-цомпосе.имл

version: '3'

networks:
  elk:

volumes:
  elasticsearch:
    driver: local

services:

  logstash:
    container_name: logstash_one_channel
    image: docker.elastic.co/logstash/logstash:6.3.2
    networks:
      	- elk
    ports:
      	- 5046:5046
    volumes:
      	- ./config/pipelines.yml:/usr/share/logstash/config/pipelines.yml:ro
	- ./config/pipelines:/usr/share/logstash/config/pipelines:ro

Шта видимо овде?

  1. Мреже и волумени су преузети из оригиналног доцкер-цомпосе.имл (оног где се покреће цео стек) и мислим да они овде не утичу много на целокупну слику.
  2. Креирамо једну логстасх услугу(е) од слике доцкер.еластиц.цо/логстасх/логстасх:6.3.2 и именујемо је логстасх_оне_цханнел.
  3. Проследимо порт 5046 унутар контејнера, на исти унутрашњи порт.
  4. Ми мапирамо нашу конфигурациону датотеку цеви ./цонфиг/пипелинес.имл у датотеку /уср/схаре/логстасх/цонфиг/пипелинес.имл унутар контејнера, где ће је логстасх покупити и учинити је само за читање, за сваки случај.
  5. Директоријум ./цонфиг/пипелинес, где имамо датотеке са подешавањима канала, мапирамо у директоријум /уср/схаре/логстасх/цонфиг/пипелинес и такође га чинимо само за читање.

Практична примена ЕЛК-а. Постављање логстасх-а

Пипелинес.имл датотека

- pipeline.id: HABR
  pipeline.workers: 1
  pipeline.batch.size: 1
  path.config: "./config/pipelines/habr_pipeline.conf"

Овде је описан један канал са ХАБР идентификатором и путања до његове конфигурационе датотеке.

И на крају фајл „./цонфиг/пипелинес/хабр_пипелине.цонф“

input {
  tcp {
    port => "5046"
   }
  }
filter {
  mutate {
    add_field => [ "habra_field", "Hello Habr" ]
    }
  }
output {
  stdout {
      
    }
  }

Хајде да за сада не улазимо у његов опис, хајде да покушамо да га покренемо:

docker-compose up

Шта видимо?

Контејнер је почео. Можемо проверити његов рад:

echo '13123123123123123123123213123213' | nc localhost 5046

И видимо одговор у конзоли контејнера:

Практична примена ЕЛК-а. Постављање логстасх-а

Али у исто време, такође видимо:

логстасх_оне_цханнел | [2019-04-29Т11:28:59,790][ЕРРОР][логстасх.лиценсецхецкер.лиценсереадер] Није могуће преузети информације о лиценци са сервера лиценци {:мессаге=>„Еластицсеарцх недоступан: [хттп://еластицсеарцх:9200/][Мантицоре ::РесолутионФаилуре] еластицсеарцх", ...

логстасх_оне_цханнел | [2019-04-29Т11:28:59,894][ИНФО ][логстасх.пипелине ] Пипелине је успешно започео {:пипелине_ид=>".мониторинг-логстасх", :тхреад=>"# "}

логстасх_оне_цханнел | [2019-04-29Т11:28:59,988][ИНФО ][логстасх.агент ] Цевоводи раде {:цоунт=>2, :руннинг_пипелинес=>[:ХАБР, :.мониторинг-логстасх"], :нон_руннинг_пипелинес=>[ ]}
логстасх_оне_цханнел | [2019-04-29Т11:29:00,015][ЕРРОР][логстасх.инпутс.метрицс] Кс-Пацк је инсталиран на Логстасх, али не и на Еластицсеарцх. Инсталирајте Кс-Пацк на Еластицсеарцх да бисте користили функцију надгледања. Друге функције могу бити доступне.
логстасх_оне_цханнел | [2019-04-29Т11:29:00,526][ИНФО ][логстасх.агент ] Успешно покренута Логстасх АПИ крајња тачка {:порт=>9600}
логстасх_оне_цханнел | [2019-04-29Т11:29:04,478][ИНФО ][логстасх.оутпутс.еластицсеарцх] Покретање здравствене провере да се види да ли Еластицсеарцх веза ради {:хеалтхцхецк_урл=>хттп://еластицсеарцх:9200/, :патх=> "/"}
логстасх_оне_цханнел | [2019-04-29Т11:29:04,487][ВАРН ][логстасх.оутпутс.еластицсеарцх] Покушао да се оживи веза са мртвом ЕС инстанцом, али се појавила грешка. {:урл=>“еластична претрага:9200/", :еррор_типе=>ЛогСтасх::Оутпутс::ЕластицСеарцх::ХттпЦлиент::Поол::ХостУнреацхаблеЕррор, :еррор=>"Еластицсеарцх Унреацхабле: [хттп://еластицсеарцх:9200/Ресолутион][Мантицоре::уре] еластична претрага"}
логстасх_оне_цханнел | [2019-04-29Т11:29:04,704][ИНФО ][логстасх.лиценсецхецкер.лиценсереадер] Покретање здравствене провере да се види да ли Еластицсеарцх веза ради {:хеалтхцхецк_урл=>хттп://еластицсеарцх:9200/, :патх=> "/"}
логстасх_оне_цханнел | [2019-04-29Т11:29:04,710][ВАРН ][логстасх.лиценсецхецкер.лиценсереадер] Покушао да се оживи веза са мртвом ЕС инстанцом, али се појавила грешка. {:урл=>“еластична претрага:9200/", :еррор_типе=>ЛогСтасх::Оутпутс::ЕластицСеарцх::ХттпЦлиент::Поол::ХостУнреацхаблеЕррор, :еррор=>"Еластицсеарцх Унреацхабле: [хттп://еластицсеарцх:9200/Ресолутион][Мантицоре::уре] еластична претрага"}

А наш балван се стално прикрада.

Овде сам зеленом бојом истакао поруку да је цевовод успешно покренут, црвеном поруку о грешци и жутом поруку о покушају контактирања еластична претрага: КСНУМКС.
Ово се дешава зато што логстасх.цонф, укључен у слику, садржи проверу доступности еластичне претраге. На крају крајева, логстасх претпоставља да ради као део Елк стека, али смо га одвојили.

Може се радити, али није згодно.

Решење је да онемогућите ову проверу преко КСПАЦК_МОНИТОРИНГ_ЕНАБЛЕД променљиве окружења.

Хајде да променимо доцкер-цомпосе.имл и поново га покренимо:

version: '3'

networks:
  elk:

volumes:
  elasticsearch:
    driver: local

services:

  logstash:
    container_name: logstash_one_channel
    image: docker.elastic.co/logstash/logstash:6.3.2
    networks:
      - elk
    environment:
      XPACK_MONITORING_ENABLED: "false"
    ports:
      - 5046:5046
   volumes:
      - ./config/pipelines.yml:/usr/share/logstash/config/pipelines.yml:ro
      - ./config/pipelines:/usr/share/logstash/config/pipelines:ro

Сада је све у реду. Контејнер је спреман за експерименте.

Можемо поново да укуцамо у следећој конзоли:

echo '13123123123123123123123213123213' | nc localhost 5046

И види:

logstash_one_channel | {
logstash_one_channel |         "message" => "13123123123123123123123213123213",
logstash_one_channel |      "@timestamp" => 2019-04-29T11:43:44.582Z,
logstash_one_channel |        "@version" => "1",
logstash_one_channel |     "habra_field" => "Hello Habr",
logstash_one_channel |            "host" => "gateway",
logstash_one_channel |            "port" => 49418
logstash_one_channel | }

Рад у оквиру једног канала

Па смо кренули. Сада заправо можете одвојити време да конфигуришете сам логстасх. Хајде да за сада не дирамо датотеку пипелинес.имл, да видимо шта можемо да добијемо радом са једним каналом.

Морам рећи да је општи принцип рада са конфигурационим фајлом канала добро описан у званичном приручнику, овде овде
Ако желите да читате на руском, користили смо овај чланак(али синтакса упита тамо је стара, ово морамо узети у обзир).

Идемо редом од одељка Унос. Већ смо видели рад на ТЦП-у. Шта би ту још могло бити занимљиво?

Тестирајте поруке помоћу откуцаја срца

Постоји тако занимљива прилика за генерисање аутоматских тестних порука.
Да бисте то урадили, потребно је да омогућите додатак хеартбеан у одељку за унос.

input {
  heartbeat {
    message => "HeartBeat!"
   }
  } 

Укључите га, почните да примате једном у минуту

logstash_one_channel | {
logstash_one_channel |      "@timestamp" => 2019-04-29T13:52:04.567Z,
logstash_one_channel |     "habra_field" => "Hello Habr",
logstash_one_channel |         "message" => "HeartBeat!",
logstash_one_channel |        "@version" => "1",
logstash_one_channel |            "host" => "a0667e5c57ec"
logstash_one_channel | }

Ако желимо да примамо чешће, потребно је да додамо параметар интервала.
Овако ћемо добијати поруку сваких 10 секунди.

input {
  heartbeat {
    message => "HeartBeat!"
    interval => 10
   }
  }

Преузимање података из датотеке

Такође смо одлучили да погледамо режим датотеке. Ако добро ради са датотеком, онда можда агент није потребан, барем за локалну употребу.

Према опису, режим рада треба да буде сличан таил -ф, тј. чита нове редове или, као опцију, чита целу датотеку.

Дакле, шта желимо да добијемо:

  1. Желимо да примимо редове који се додају једној лог датотеци.
  2. Желимо да примамо податке који су уписани у неколико датотека евиденције, а да истовремено можемо да одвојимо шта је примљено од куда.
  3. Желимо да будемо сигурни да када се логстасх поново покрене, неће поново примити ове податке.
  4. Желимо да проверимо да ако је логстасх искључен, а подаци настављају да се уписују у датотеке, онда када га покренемо, примићемо ове податке.

Да бисмо спровели експеримент, додајмо још једну линију у доцкер-цомпосе.имл, отварајући директоријум у који смо ставили датотеке.

version: '3'

networks:
  elk:

volumes:
  elasticsearch:
    driver: local

services:

  logstash:
    container_name: logstash_one_channel
    image: docker.elastic.co/logstash/logstash:6.3.2
    networks:
      - elk
    environment:
      XPACK_MONITORING_ENABLED: "false"
    ports:
      - 5046:5046
   volumes:
      - ./config/pipelines.yml:/usr/share/logstash/config/pipelines.yml:ro
      - ./config/pipelines:/usr/share/logstash/config/pipelines:ro
      - ./logs:/usr/share/logstash/input

И промените одељак за унос у хабр_пипелине.цонф

input {
  file {
    path => "/usr/share/logstash/input/*.log"
   }
  }

Почнимо:

docker-compose up

За креирање и писање датотека евиденције користићемо наредбу:


echo '1' >> logs/number1.log

{
logstash_one_channel |            "host" => "ac2d4e3ef70f",
logstash_one_channel |     "habra_field" => "Hello Habr",
logstash_one_channel |      "@timestamp" => 2019-04-29T14:28:53.876Z,
logstash_one_channel |        "@version" => "1",
logstash_one_channel |         "message" => "1",
logstash_one_channel |            "path" => "/usr/share/logstash/input/number1.log"
logstash_one_channel | }

Да, ради!

Истовремено, видимо да смо аутоматски додали поље путање. То значи да ћемо у будућности моћи да филтрирамо записе по њему.

Хајде да пробамо поново:

echo '2' >> logs/number1.log

{
logstash_one_channel |            "host" => "ac2d4e3ef70f",
logstash_one_channel |     "habra_field" => "Hello Habr",
logstash_one_channel |      "@timestamp" => 2019-04-29T14:28:59.906Z,
logstash_one_channel |        "@version" => "1",
logstash_one_channel |         "message" => "2",
logstash_one_channel |            "path" => "/usr/share/logstash/input/number1.log"
logstash_one_channel | }

А сада на другу датотеку:

 echo '1' >> logs/number2.log

{
logstash_one_channel |            "host" => "ac2d4e3ef70f",
logstash_one_channel |     "habra_field" => "Hello Habr",
logstash_one_channel |      "@timestamp" => 2019-04-29T14:29:26.061Z,
logstash_one_channel |        "@version" => "1",
logstash_one_channel |         "message" => "1",
logstash_one_channel |            "path" => "/usr/share/logstash/input/number2.log"
logstash_one_channel | }

Велики! Датотека је подигнута, путања је тачно наведена, све је у реду.

Зауставите логстасх и почните поново. Сачекајмо. Тишина. Оне. Ове записе више не добијамо.

А сада најхрабрији експеримент.

Инсталирајте логстасх и покрените:

echo '3' >> logs/number2.log
echo '4' >> logs/number1.log

Поново покрените логстасх и погледајте:

logstash_one_channel | {
logstash_one_channel |            "host" => "ac2d4e3ef70f",
logstash_one_channel |     "habra_field" => "Hello Habr",
logstash_one_channel |         "message" => "3",
logstash_one_channel |        "@version" => "1",
logstash_one_channel |            "path" => "/usr/share/logstash/input/number2.log",
logstash_one_channel |      "@timestamp" => 2019-04-29T14:48:50.589Z
logstash_one_channel | }
logstash_one_channel | {
logstash_one_channel |            "host" => "ac2d4e3ef70f",
logstash_one_channel |     "habra_field" => "Hello Habr",
logstash_one_channel |         "message" => "4",
logstash_one_channel |        "@version" => "1",
logstash_one_channel |            "path" => "/usr/share/logstash/input/number1.log",
logstash_one_channel |      "@timestamp" => 2019-04-29T14:48:50.856Z
logstash_one_channel | }

Ура! Све је покупљено.

Али морамо вас упозорити на следеће. Ако је логстасх контејнер обрисан (доцкер стоп логстасх_оне_цханнел && доцкер рм логстасх_оне_цханнел), ништа се неће преузети. Позиција датотеке до које је прочитана сачувана је унутар контејнера. Ако га покренете од нуле, прихватаће само нове линије.

Читање постојећих датотека

Рецимо да први пут покрећемо логстасх, али већ имамо евиденције и желимо да их обрадимо.
Ако покренемо логстасх са одељком за унос који смо користили изнад, нећемо добити ништа. Логстасх ће обрадити само нове линије.

Да би се линије из постојећих датотека повукле, требало би да додате још једну линију у одељак за унос:

input {
  file {
    start_position => "beginning"
    path => "/usr/share/logstash/input/*.log"
   }
  }

Штавише, постоји нијанса: ово утиче само на нове датотеке које логстасх још није видео. За исте датотеке које су већ биле у видном пољу логстасх-а, он је већ запамтио њихову величину и сада ће узимати само нове уносе у њима.

Хајде да се зауставимо овде и проучимо одељак за унос. Постоји још много опција, али то нам је за сада довољно за даље експерименте.

Рутирање и трансформација података

Хајде да покушамо да решимо следећи проблем, рецимо да имамо поруке са једног канала, неке од њих су информативне, а неке поруке о грешци. Разликују се по ознаци. Неки су ИНФО, други су ГРЕШКА.

Морамо их раздвојити на излазу. Оне. На једном каналу пишемо информативне поруке, а на другом поруке о грешци.

Да бисте то урадили, пређите са одељка за унос на филтер и излаз.

Користећи секцију филтера, анализираћемо долазну поруку, добијајући од ње хеш (парове кључ-вредност) са којим већ можемо да радимо, тј. раставити према условима. А у излазном делу ћемо изабрати поруке и послати сваку на свој канал.

Рашчлањивање поруке помоћу грока

Да бисте рашчланили текстуалне стрингове и добили скуп поља од њих, постоји посебан додатак у одељку филтера - грок.

Не постављајући себи за циљ да то овде дам детаљан опис (за ово се позивам званична документација), даћу свој једноставан пример.

Да бисте то урадили, морате одлучити о формату улазних низова. имам их овако:

1 ИНФО порука1
2 Порука ЕРРОР2

Оне. Прво долази идентификатор, затим ИНФО/ГРЕШКА, па нека реч без размака.
Није тешко, али довољно је разумети принцип рада.

Дакле, у одељку филтера грок додатка, морамо дефинисати образац за рашчлањивање наших стрингова.

То ће изгледати овако:

filter {
  grok {
    match => { "message" => ["%{INT:message_id} %{LOGLEVEL:message_type} %{WORD:message_text}"] }
   }
  } 

У суштини то је регуларни израз. Користе се готови обрасци, као што су ИНТ, ЛОГЛЕВЕЛ, ВОРД. Њихов опис, као и друге шаре, можете пронаћи овде овде

Сада, пролазећи кроз овај филтер, наш стринг ће се претворити у хеш од три поља: мессаге_ид, мессаге_типе, мессаге_тект.

Они ће бити приказани у одељку за излаз.

Рутирање порука у излазну секцију помоћу команде иф

У излазном делу, као што се сећамо, хтели смо да поделимо поруке у два тока. Неки - који су иНФО, биће излазни на конзолу, а са грешкама ћемо их извести у датотеку.

Како да одвојимо ове поруке? Услов проблема већ сугерише решење – на крају крајева, већ имамо наменско поље мессаге_типе, које може да има само две вредности: ИНФО и ЕРРОР. На основу тога ћемо направити избор користећи иф наредбу.

if [message_type] == "ERROR" {
        # Здесь выводим в файл
       } else
     {
      # Здесь выводим в stdout
    }

Опис рада са пољима и операторима може се наћи у овом одељку званични приручник.

Сада о самом закључку.

Излаз конзоле, овде је све јасно - стдоут {}

Али излаз у датотеку – запамтите да све ово покрећемо из контејнера и да би фајл у који уписујемо резултат био доступан споља, потребно је да отворимо овај директоријум у доцкер-цомпосе.имл.

Укупно:

Излазни део наше датотеке изгледа овако:


output {
  if [message_type] == "ERROR" {
    file {
          path => "/usr/share/logstash/output/test.log"
          codec => line { format => "custom format: %{message}"}
         }
    } else
     {stdout {
             }
     }
  }

У доцкер-цомпосе.имл додајемо још један волумен за излаз:

version: '3'

networks:
  elk:

volumes:
  elasticsearch:
    driver: local

services:

  logstash:
    container_name: logstash_one_channel
    image: docker.elastic.co/logstash/logstash:6.3.2
    networks:
      - elk
    environment:
      XPACK_MONITORING_ENABLED: "false"
    ports:
      - 5046:5046
   volumes:
      - ./config/pipelines.yml:/usr/share/logstash/config/pipelines.yml:ro
      - ./config/pipelines:/usr/share/logstash/config/pipelines:ro
      - ./logs:/usr/share/logstash/input
      - ./output:/usr/share/logstash/output

Покрећемо га, испробамо и видимо поделу на два тока.

Извор: ввв.хабр.цом

Додај коментар