ELK praktiline rakendamine. Logstashi seadistamine

Sissejuhatus

Teise süsteemi juurutamisel seisime silmitsi vajadusega töödelda suurt hulka erinevaid logisid. Pilliks valiti ELK. See artikkel räägib meie kogemustest selle virna seadistamisel.

Me ei sea eesmärgiks kirjeldada kõiki selle võimalusi, vaid tahame keskenduda praktiliste probleemide lahendamisele. See on tingitud sellest, et piisavalt suure hulga dokumentatsiooni ja valmispiltide juures on lõkse palju, vähemalt meie leidsime need üles.

Juurutasime virna docker-compose kaudu. Lisaks oli meil hästi kirjutatud docker-compose.yml, mis võimaldas meil pinu peaaegu probleemideta tõsta. Ja meile tundus, et võit on juba lähedal, nüüd keerame seda veidi oma vajaduste järgi ja kõik.

Kahjuks ei õnnestunud süsteemi häälestada meie rakendusest logide vastuvõtmiseks ja töötlemiseks kohe. Seetõttu otsustasime, et tasub iga komponenti eraldi uurida ja seejärel nende seoste juurde tagasi pöörduda.

Alustame siis logstashiga.

Keskkond, juurutamine, Logstashi käitamine konteineris

Juurutamiseks kasutame docker-compose'i, siin kirjeldatud katsed viidi läbi MacOS-i ja Ubuntu 18.0.4-ga.

Algses failis docker-compose.yml olev logstash-pilt on docker.elastic.co/logstash/logstash:6.3.2

Kasutame seda katseteks.

Logstashi käitamiseks kirjutasime eraldi faili docker-compose.yml. Muidugi oli võimalik pilti käivitada ka käsurealt, aga lõppude lõpuks lahendasime konkreetse ülesande, kus meie eest käivitatakse kõik alates docker-compose'ist.

Lühidalt konfiguratsioonifailide kohta

Nagu kirjeldusest järeldub, saab logstashi käivitada nagu ühe kanali jaoks, sel juhul peab see üle kandma faili *.conf või mitme kanali jaoks, sel juhul peab edastama faili pipelines.yml, mis omakorda , viitab iga kanali failidele .conf.
Võtsime teise tee. See tundus meile mitmekülgsem ja skaleeritavam. Seetõttu lõime pipelines.yml ja tegime torujuhtmete kataloogi, kuhu paneme iga kanali jaoks .conf-failid.

Konteineri sees on veel üks konfiguratsioonifail - logstash.yml. Me ei puuduta seda, kasutame seda nii nagu on.

Seega on meie kataloogi struktuur järgmine:

ELK praktiline rakendamine. Logstashi seadistamine

Praegu eeldame, et see on tcp pordis 5046 sisendandmete vastuvõtmiseks ja kasutame väljundiks stdout.

Siin on nii lihtne konfiguratsioon esimeseks käivitamiseks. Sest lähteülesanne on käivitada.

Nii et meil on see docker-compose.yml

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

Mida me siin näeme?

  1. Võrgud ja mahud on võetud algsest docker-compose.yml-st (sellest, kus käivitatakse kogu virn) ja ma arvan, et need ei mõjuta siin üldist pilti eriti.
  2. Loome pildilt docker.elastic.co/logstash/logstash:6.3.2 ühe teenuse (teenused) logstash ja anname sellele nime logstash_one_channel.
  3. Edastame pordi 5046 konteineri sees samasse sisemisse porti.
  4. Seotame oma ./config/pipelines.yml toru konfiguratsioonifaili konteineris oleva /usr/share/logstash/config/pipelines.yml failiga, kust logstash selle üles korjab ja kirjutuskaitstuks teeb, et olla turvaline pool.
  5. Vastame ./config/pipelines kataloogi, kus on torusätetega failid, kataloogi /usr/share/logstash/config/pipelines ja muudame selle ka kirjutuskaitstuks.

ELK praktiline rakendamine. Logstashi seadistamine

faili torustik.yml

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

See kirjeldab ühte kanalit HABR-i identifikaatoriga ja selle konfiguratsioonifaili teed.

Ja lõpuks fail "./config/pipelines/habr_pipeline.conf"

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

Me ei lähe praegu selle kirjeldusse, proovime käivitada:

docker-compose up

Mida me näeme?

Konteiner on käivitunud. Selle tööd saame kontrollida:

echo '13123123123123123123123213123213' | nc localhost 5046

Ja me näeme konteinerikonsoolis vastust:

ELK praktiline rakendamine. Logstashi seadistamine

Kuid samal ajal näeme ka:

logstash_one_channel | [2019-04-29T11:28:59,790][VIGA][logstash.licensechecker.licensereader] Litsentsi teavet ei saa litsentsiserverist tuua {:message=>"Elasticsearch kättesaamatu: [http://elasticsearch:9200/][Manticore" ::ResolutionFailure]elasticsearch", ...

logstash_one_channel | [2019-04-29T11:28:59,894][INFO ][logstash.pipeline ] Pipeline käivitati edukalt {:pipeline_id=>".monitoring-logstash", :thread=>"# »}

logstash_one_channel | [2019-04-29T11:28:59,988][INFO ][logstash.agent ] Konveierid töötavad {:count=>2, :running_pipelines=>[:HABR, :".monitoring-logstash"], :non_running_pipelines=>[ ]}
logstash_one_channel | [2019-04-29T11:29:00,015][VIGA][logstash.inputs.metrics ] X-Pack on installitud Logstashi, kuid mitte Elasticsearchi. Jälgimisfunktsiooni kasutamiseks installige Elasticsearchi X-Pack. Saadaval võivad olla ka muud funktsioonid.
logstash_one_channel | [2019-04-29T11:29:00,526][INFO ][logstash.agent ] Logstash API lõpp-punkti {:port=>9600} käivitamine õnnestus
logstash_one_channel | [2019-04-29T11:29:04,478][INFO ][logstash.outputs.elasticsearch] Tervisekontroll, et näha, kas Elasticsearchi ühendus töötab {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,487][HOIATUS ][logstash.outputs.elasticsearch] Üritasid taastada ühendust surnud ES-i eksemplariga, kuid ilmnes tõrge. {:url=>"elastneotsing:9200/", :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch kättesaamatu: [http://elasticsearch:9200/][Manticore::Re] elastsearch"}
logstash_one_channel | [2019-04-29T11:29:04,704][INFO ][logstash.licensechecker.licensereader] Tervisekontroll, et näha, kas Elasticsearchi ühendus töötab {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,710][HOIATUS ][logstash.licensechecker.licensereader] Prooviti taastada ühendust surnud ES-i eksemplariga, kuid ilmnes tõrge. {:url=>"elastneotsing:9200/", :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch kättesaamatu: [http://elasticsearch:9200/][Manticore::Re] elastsearch"}

Ja meie palk roomab kogu aeg üles.

Siin tõstsin rohelisega esile teate, et torujuhtme käivitamine õnnestus, punasega veateate ja kollasega sõnumi ühenduse võtmise kohta elastneotsing: 9200.
See juhtub seetõttu, et pildil olevas failis logstash.conf kontrollitakse elasticsearchi saadavust. Lõppude lõpuks eeldab logstash, et see töötab Elki virna osana, ja me eraldasime selle.

Võite töötada, kuid see pole mugav.

Lahendus on selle kontrolli keelamine keskkonnamuutuja XPACK_MONITORING_ENABLED kaudu.

Muudame faili docker-compose.yml ja käivitame selle uuesti:

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

Nüüd on kõik hästi. Konteiner on katseteks valmis.

Saame külgnevale konsoolile uuesti sisestada:

echo '13123123123123123123123213123213' | nc localhost 5046

Ja näe:

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 | }

Töötage ühes kanalis

Nii et me alustasime. Nüüd saate tegelikult võtta aega logstashi otse konfigureerimiseks. Ärgem praegu puudutagem faili pipelines.yml, vaatame, mida saame ühe kanaliga töötades.

Pean ütlema, et kanali konfiguratsioonifailiga töötamise üldpõhimõtet on siin ametlikus juhendis hästi kirjeldatud siin
Kui soovite lugeda vene keeles, siis kasutasime seda artiklit(aga päringu süntaks on seal vana, sellega tuleb arvestada).

Lähme järjestikku sisendi jaotisest. Oleme tcp-ga tööd juba näinud. Mis siin veel huvitavat saab olla?

Testige sõnumeid südamelöökide abil

Automaatsete testsõnumite genereerimiseks on selline huvitav võimalus.
Selleks peate sisestussektsiooni lisama südamebean plugina.

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

Lülitame sisse, hakkame kord minutis vastu võtma

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 | }

Soovime saada sagedamini, peame lisama intervalli parameetri.
Nii saame iga 10 sekundi järel sõnumi.

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

Andmete hankimine failist

Otsustasime vaadata ka failirežiimi. Kui see toimib failiga hästi, siis on võimalik, et agenti pole vaja, noh, vähemalt kohalikuks kasutamiseks.

Kirjelduse järgi peaks töörežiim olema sarnane tail -f-ga, st. loeb reavahetust või soovi korral kogu faili.

Mida me siis saada tahame:

  1. Soovime saada ridu, mis on lisatud ühte logifaili.
  2. Soovime saada andmeid, mis on kirjutatud mitmesse logifaili, samal ajal kui saame eraldada, kust saadeti.
  3. Tahame olla kindlad, et kui logstash taaskäivitatakse, ei saaks ta neid andmeid enam kätte.
  4. Tahame kontrollida, et kui logstash on keelatud ja andmete kirjutamine failidesse jätkub, siis selle käivitamisel saame need andmed kätte.

Katse läbiviimiseks lisame faili docker-compose.yml veel ühe rea, avades kataloogi, kuhu failid asetame.

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

Ja muutke faili habr_pipeline.conf sisendosa

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

Me alustame:

docker-compose up

Logifailide loomiseks ja kirjutamiseks kasutame käsku:


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 | }

Jah, see töötab!

Samal ajal näeme, et oleme teevälja automaatselt lisanud. Seega saame edaspidi kirjeid selle järgi filtreerida.

Proovime uuesti:

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 | }

Ja nüüd teise faili juurde:

 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 | }

Suurepärane! Fail korjati üles, tee määrati õigesti, kõik on korras.

Peatage logstash ja taaskäivitage. Ootame. Vaikus. Need. Me ei saa neid kirjeid enam kätte.

Ja nüüd kõige julgem eksperiment.

Panime logstashi ja käivitame:

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

Käivitage uuesti logstash ja vaadake:

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 | }

Hurraa! Kõik sai üles.

Kuid on vaja hoiatada järgmise eest. Kui logstash konteiner eemaldatakse (docker stop logstash_one_channel && docker rm logstash_one_channel), ei võeta midagi üles. Faili asukoht, milleni see loeti, salvestati konteinerisse. Kui alustate nullist, võtab see vastu ainult uusi ridu.

Olemasolevate failide lugemine

Oletame, et kasutame logstashi esimest korda, kuid meil on logid juba olemas ja tahaksime neid töödelda.
Kui käivitame logstashi ülaltoodud sisendjaotisega, ei saa me midagi. Logstash töötleb ainult uusi ridu.

Olemasolevatest failidest ridade tõmbamiseks lisage sisestussektsiooni täiendav rida:

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

Lisaks on nüanss, see mõjutab ainult uusi faile, mida logstash pole veel näinud. Samade failide puhul, mis olid juba logstashi vaateväljas, on see juba nende suuruse meeles pidanud ja võtab nüüd neisse ainult uued kirjed.

Lõpetagem sellel sisendosa uurimisega. Võimalusi on palju rohkem, kuid praegu on meil edasisteks katseteks piisavalt.

Marsruutimine ja andmete teisendamine

Proovime lahendada järgmise probleemi, oletame, et meil on teated ühest kanalist, osa neist on informatiivsed ja osa veateated. Need erinevad märgistuse poolest. Mõned on INFO, teised on ERROR.

Peame need väljapääsu juures eraldama. Need. Ühte kanalisse kirjutame infoteateid, teise tõrketeateid.

Selleks minge sisendosast filtreerima ja väljastama.

Filtrisektsiooni abil parseldame sissetuleva kirja, saades sealt räsi (võtme-väärtuse paarid), millega saame juba tööd teha, s.t. sõeluda vastavalt tingimustele. Ja väljundi jaotises valime sõnumid ja saadame igaüks oma kanalile.

Sõnumi sõelumine grokiga

Tekstistringide sõelumiseks ja nendest väljade komplekti saamiseks on filtri jaotises spetsiaalne pistikprogramm - grok.

Seadmata endale eesmärgiks seda siin üksikasjalikult kirjeldada (selleks viitan ametlik dokumentatsioon), toon oma lihtsa näite.

Selleks peate otsustama sisestusridade vormingu üle. Mul on need sellised:

1 INFO teade1
2 ERROR teade2

Need. Kõigepealt identifikaator, siis INFO/VIGA, siis mõni sõna ilma tühikuteta.
Pole keeruline, kuid piisavalt, et mõista tööpõhimõtet.

Niisiis peame groki pistikprogrammi filtri jaotises määratlema stringide sõelumise mustri.

See näeb välja selline:

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

Põhimõtteliselt on see regulaaravaldis. Kasutatakse valmis mustreid, nagu INT, LOGLEVEL, WORD. Nende kirjeldust ja ka muid mustreid saab vaadata siit. siin

Nüüd, selle filtri läbimisel, muutub meie string kolmest väljast koosnevaks räsiteks: message_id, message_type, message_text.

Need kuvatakse väljundi jaotises.

Sõnumite suunamine väljundsektsioonis käsuga if

Nagu mäletame, jagasime väljundi jaotises sõnumid kahte voogu. Mõned - mis on iNFO, väljastame konsooli ja vigade korral faili.

Kuidas me saame neid sõnumeid jagada? Probleemi seisund viitab juba lahendusele - meil on juba spetsiaalne väli message_type, mis võib võtta ainult kaks väärtust INFO ja ERROR. Selle põhjal teeme valiku if-lause abil.

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

Väljade ja operaatoritega töö kirjelduse leiate sellest jaotisest ametlik käsiraamat.

Nüüd järeldusest endast.

Konsooli väljund, siin on kõik selge – stdout {}

Aga väljund faili - pidage meeles, et me käivitame seda kõike konteinerist ja selleks, et fail, millesse me tulemuse kirjutame, oleks väljastpoolt saadaval, peame selle kataloogi avama failis docker-compose.yml.

Kokku:

Meie faili väljundosa näeb välja selline:


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

Lisage faili docker-compose.yml väljundiks veel üks köide:

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

Alustame, proovime, näeme jagunemist kaheks vooluks.

Allikas: www.habr.com

Lisa kommentaar