ELK praktiskais pielietojums. Logstash iestatīŔana

Ievads

Izvietojot citu sistēmu, mēs saskārāmies ar nepiecieÅ”amÄ«bu apstrādāt lielu skaitu dažādu žurnālu. Kā rÄ«ks tika izvēlēts ELK. Å ajā rakstā tiks apspriesta mÅ«su pieredze Ŕīs kaudzes iestatÄ«Å”anā.

Mēs neizvirzām mērÄ·i aprakstÄ«t visas tā iespējas, bet vēlamies koncentrēties tieÅ”i uz praktisku problēmu risināŔanu. Tas ir saistÄ«ts ar to, ka, lai arÄ« ir diezgan daudz dokumentācijas un gatavu attēlu, ir diezgan daudz slazdu, vismaz mēs tās atradām.

Mēs izvietojām steku, izmantojot docker-compose. Turklāt mums bija labi uzrakstÄ«ts docker-compose.yml, kas ļāva mums gandrÄ«z bez problēmām palielināt steku. Un mums Ŕķita, ka uzvara jau ir tuvu, tagad mēs to nedaudz pielabosim, lai tā atbilstu savām vajadzÄ«bām, un viss.

Diemžēl mēģinājums konfigurēt sistēmu, lai saņemtu un apstrādātu žurnālus no mÅ«su lietojumprogrammas, uzreiz nebija veiksmÄ«gs. Tāpēc mēs nolēmām, ka ir vērts izpētÄ«t katru komponentu atseviŔķi un pēc tam atgriezties pie to savienojumiem.

Tātad, mēs sākām ar logstash.

Vide, izvietoŔana, Logstash palaiŔana konteinerā

IzvietoÅ”anai mēs izmantojam docker-compose; Å”eit aprakstÄ«tie eksperimenti tika veikti operētājsistēmās MacOS un Ubuntu 18.0.4.

Logstash attēls, kas tika reģistrēts mūsu sākotnējā docker-compose.yml, ir docker.elastic.co/logstash/logstash:6.3.2

Mēs to izmantosim eksperimentiem.

Mēs uzrakstÄ«jām atseviŔķu docker-compose.yml, lai palaistu logstash. Protams, attēlu bija iespējams palaist no komandrindas, bet mēs risinājām konkrētu problēmu, kur mēs palaižam visu no docker-compose.

ÄŖsi par konfigurācijas failiem

Kā izriet no apraksta, logstash var palaist vai nu vienam kanālam, tādā gadījumā tam ir jānodod *.conf fails, vai vairākiem kanāliem, tādā gadījumā tam ir jānodod pipelines.yml fails, kas, savukārt, , izveidos saiti uz failiem .conf katram kanālam.
Mēs izvēlējāmies otro ceļu. Tas mums Ŕķita universālāks un mērogojamāks. Tāpēc mēs izveidojām pipelines.yml un izveidojām pipelines direktoriju, kurā katram kanālam ievietosim .conf failus.

Konteinera iekÅ”pusē ir vēl viens konfigurācijas fails - logstash.yml. Mēs to neaiztiekam, lietojam to tādu, kāds ir.

Tātad, mūsu direktoriju struktūra:

ELK praktiskais pielietojums. Logstash iestatīŔana

Lai saņemtu ievades datus, paÅ”laik mēs pieņemam, ka tas ir tcp portā 5046, un izvadei izmantosim stdout.

Å eit ir vienkārÅ”a konfigurācija pirmajai palaiÅ”anai. Jo sākotnējais uzdevums ir palaist.

Tātad, mums ir 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

Ko mēs Å”eit redzam?

  1. TÄ«kli un sējumi tika ņemti no oriÄ£inālā docker-compose.yml (tā, kurā tiek palaists viss steks), un es domāju, ka tie Å”eit Ä«paÅ”i neietekmē kopējo attēlu.
  2. Mēs izveidojam vienu(-s) logstash pakalpojumu(s) no docker.elastic.co/logstash/logstash:6.3.2 attēla un nosaucam to logstash_one_channel.
  3. Mēs pārsÅ«tām portu 5046 konteinera iekÅ”pusē uz to paÅ”u iekŔējo portu.
  4. Mēs kartējam mūsu caurules konfigurācijas failu ./config/pipelines.yml ar failu /usr/share/logstash/config/pipelines.yml konteinerā, kur logstash to paņems un katram gadījumam padarīs tikai lasāmu.
  5. Mēs kartējam direktoriju ./config/pipelines, kurā mums ir faili ar kanāla iestatījumiem, direktorijā /usr/share/logstash/config/pipelines, kā arī padarām to tikai lasāmu.

ELK praktiskais pielietojums. Logstash iestatīŔana

Pipelines.yml fails

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

Šeit ir aprakstīts viens kanāls ar HABR identifikatoru un ceļŔ uz tā konfigurācijas failu.

Un visbeidzot fails ā€œ./config/pipelines/habr_pipeline.confā€

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

Pagaidām neiedziļināsimies tā aprakstā, mēģināsim to palaist:

docker-compose up

Ko mēs redzam?

Konteiners ir sācies. Mēs varam pārbaudīt tā darbību:

echo '13123123123123123123123213123213' | nc localhost 5046

Un mēs redzam atbildi konteinera konsolē:

ELK praktiskais pielietojums. Logstash iestatīŔana

Bet tajā paŔā laikā mēs redzam arÄ«:

logstash_one_channel | [2019-04-29T11:28:59,790][KÄ»ÅŖDA][logstash.licensechecker.licensereader] Nevar izgÅ«t licences informāciju no licences servera {:message=>ā€œElasticsearch nav sasniedzams: [http://elasticsearch:9200/][Manticore ::ResolutionFailure] elasticsearch", ...

logstash_one_channel | [2019-04-29T11:28:59,894][INFO ][logstash.pipeline ] Cauruļvads veiksmīgi sākts {:pipeline_id=>".monitoring-logstash", :thread=>"# "}

logstash_one_channel | [2019-04-29T11:28:59,988][INFO ][logstash.agent ] Cauruļvadi darbojas {:count=>2, :running_pipelines=>[:HABR, :".monitoring-logstash"], :non_running_pipelines=>[ ]}
logstash_one_channel | [2019-04-29T11:29:00,015][KÄ»ÅŖDA][logstash.inputs.metrics] X-Pack ir instalēts Logstash, bet ne Elasticsearch. Lai izmantotu uzraudzÄ«bas funkciju, lÅ«dzu, instalējiet X-Pack vietnē Elasticsearch. Var bÅ«t pieejamas arÄ« citas funkcijas.
logstash_one_channel | [2019-04-29T11:29:00,526][INFO ][logstash.agent ] Veiksmīgi startēts Logstash API galapunkts {:port=>9600}
logstash_one_channel | [2019-04-29T11:29:04,478][INFO ][logstash.outputs.elasticsearch] Tiek veikta veselības pārbaude, lai noskaidrotu, vai Elasticsearch savienojums darbojas {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,487][BRÄŖDINĀJUMS ][logstash.outputs.elasticsearch] Mēģināja atjaunot savienojumu ar miruÅ”o ES gadÄ«jumu, taču radās kļūda. {:url=>"elastÄ«gā meklÄ“Å”ana:9200/", :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch nav sasniedzams: [http://elasticsearch:9200/][Manticore::Re] elasticsearch"}
logstash_one_channel | [2019-04-29T11:29:04,704][INFORMĀCIJA ][logstash.licensechecker.licensereader] Tiek veikta veselības pārbaude, lai noskaidrotu, vai Elasticsearch savienojums darbojas {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,710][BRÄŖDINĀJUMS ][logstash.licensechecker.licensereader] Mēģināja atjaunot savienojumu ar miruÅ”o ES instanci, taču radās kļūda. {:url=>"elastÄ«gā meklÄ“Å”ana:9200/", :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch nav sasniedzams: [http://elasticsearch:9200/][Manticore::Re] elasticsearch"}

Un mūsu baļķis visu laiku ložņā.

Å eit es zaļā krāsā esmu iezÄ«mējis ziņojumu, ka cauruļvads ir veiksmÄ«gi palaists, sarkanā krāsā kļūdas ziņojumu un dzeltenā ziņojumu par mēģinājumu sazināties elastÄ«gā meklÄ“Å”ana: 9200.
Tas notiek tāpēc, ka logstash.conf, kas iekļauts attēlā, satur elasticsearch pieejamības pārbaudi. Galu galā logstash pieņem, ka tas darbojas kā daļa no Elk kaudzes, bet mēs to atdalījām.

Var strādāt, bet tas nav ērti.

Risinājums ir atspējot Å”o pārbaudi, izmantojot XPACK_MONITORING_ENABLED vides mainÄ«go.

Veiksim izmaiņas failā docker-compose.yml un palaidīsim to vēlreiz:

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

Tagad viss ir kārtībā. Konteiners ir gatavs eksperimentiem.

Mēs varam rakstīt vēlreiz nākamajā konsolē:

echo '13123123123123123123123213123213' | nc localhost 5046

Un redzi:

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

Darbs viena kanāla ietvaros

Tātad mēs uzsākām. Tagad jÅ«s faktiski varat veltÄ«t laiku paÅ”a logstash konfigurÄ“Å”anai. Pagaidām neaiztiksim failu pipelines.yml, paskatÄ«simies, ko varam iegÅ«t, strādājot ar vienu kanālu.

Man jāsaka, ka vispārējais princips darbam ar kanāla konfigurācijas failu ir labi aprakstÄ«ts oficiālajā rokasgrāmatā Å”eit Å”eit
Ja vēlaties lasÄ«t krievu valodā, mēs izmantojām Å”o rakstu(bet vaicājuma sintakse tur ir veca, mums tas jāņem vērā).

Pārejam secÄ«gi no sadaļas Ievade. Mēs jau esam redzējuÅ”i darbu pie TCP. Kas vēl Å”eit varētu bÅ«t interesants?

Pārbaudiet ziņojumus, izmantojot sirdsdarbību

Ir tik interesanta iespēja ģenerēt automātiskus testa ziņojumus.
Lai to izdarītu, ievades sadaļā ir jāiespējo sirdsdarbības spraudnis.

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

Ieslēdziet, sāciet saņemt reizi minūtē

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

Ja vēlamies saņemt biežāk, jāpievieno intervāla parametrs.
Tādā veidā mēs saņemsim ziņojumu ik pēc 10 sekundēm.

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

Datu izgūŔana no faila

Mēs arÄ« nolēmām apskatÄ«t failu režīmu. Ja tas darbojas labi ar failu, iespējams, nav nepiecieÅ”ams aÄ£ents, vismaz vietējai lietoÅ”anai.

Saskaņā ar aprakstu darbības režīmam jābūt līdzīgam astes -f, t.i. nolasa jaunas rindas vai pēc izvēles nolasa visu failu.

Tātad, ko mēs vēlamies iegūt:

  1. Mēs vēlamies saņemt rindas, kas ir pievienotas vienam žurnālfailam.
  2. Mēs vēlamies saņemt datus, kas ierakstīti vairākos žurnālfailos, vienlaikus spējot nodalīt saņemto no kurienes.
  3. Mēs vēlamies pārliecināties, ka pēc logstash restartÄ“Å”anas tas vairs nesaņem Å”os datus.
  4. Mēs vēlamies pārbaudÄ«t, vai, ja logstash ir izslēgts un dati turpinās rakstÄ«t failos, tad, kad mēs to palaižam, mēs saņemsim Å”os datus.

Lai veiktu eksperimentu, docker-compose.yml pievienosim vēl vienu rindiņu, atverot direktoriju, kurā ievietojam failus.

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

Un mainiet ievades sadaļu habr_pipeline.conf

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

Sāksim:

docker-compose up

Lai izveidotu un rakstītu žurnālfailus, mēs izmantosim komandu:

ā€Ø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 | }

Jā, tas darbojas!

Tajā paŔā laikā mēs redzam, ka esam automātiski pievienojuÅ”i ceļa lauku. Tas nozÄ«mē, ka nākotnē mēs varēsim filtrēt ierakstus pēc tā.

Pamēģināsim vēlreiz:

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

Un tagad pie cita faila:

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

Lieliski! Fails paņemts, ceļŔ norādÄ«ts pareizi, viss kārtÄ«bā.

Apturiet logstash un sāciet no jauna. PagaidÄ«sim. Klusums. Tie. Mēs vairs nesaņemam Å”os ierakstus.

Un tagad visdrosmīgākais eksperiments.

Instalējiet logstash un izpildiet:

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

Palaidiet logstash vēlreiz un skatiet:

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

Urrā! Viss tika savākts.

Bet mums ir jābrÄ«dina par sekojoÅ”o. Ja logstash konteiners tiek dzēsts (docker stop logstash_one_channel && docker rm logstash_one_channel), nekas netiks noņemts. Faila pozÄ«cija, lÄ«dz kurai tas tika nolasÄ«ts, tika saglabāta konteinerā. Ja palaižat to no nulles, tas pieņems tikai jaunas rindas.

EsoŔo failu lasīŔana

Pieņemsim, ka mēs pirmo reizi palaižam logstash, bet mums jau ir žurnāli, un mēs vēlētos tos apstrādāt.
Ja palaižam logstash ar iepriekÅ” izmantoto ievades sadaļu, mēs neko neiegÅ«sim. Logstash apstrādās tikai jaunas rindas.

Lai rindas no esoŔajiem failiem tiktu izvilktas, ievades sadaļai jāpievieno papildu rinda:

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

Turklāt ir nianse: tas ietekmē tikai jaunus failus, kurus logstash vēl nav redzējis. Tiem paÅ”iem failiem, kas jau bija logstash skata laukā, tas jau ir atcerējies to lielumu un tagad tajos uzņems tikai jaunus ierakstus.

Apstāsimies Å”eit un izpētÄ«sim ievades sadaļu. Joprojām ir daudz iespēju, taču ar to mums pagaidām pietiek turpmākiem eksperimentiem.

MarÅ”rutÄ“Å”ana un datu transformācija

Mēģināsim atrisināt Ŕādu problēmu, pieņemsim, ka mums ir ziņojumi no viena kanāla, daži no tiem ir informatÄ«vi, bet daži ir kļūdu ziņojumi. Tie atŔķiras pēc etiÄ·etes. Daži ir INFO, citi ir KÄ»ÅŖDA.

Mums tie ir jāatdala pie izejas. Tie. Vienā kanālā rakstām informatÄ«vos ziņojumus, citā ā€“ kļūdu ziņojumus.

Lai to izdarītu, pārejiet no ievades sadaļas uz filtru un izvadi.

Izmantojot filtru sadaļu, mēs parsēsim ienākoÅ”o ziņojumu, iegÅ«stot no tā hash (atslēgas vērtÄ«bu pārus), ar kuru jau varam strādāt, t.i. izjaukt atbilstoÅ”i nosacÄ«jumiem. Un izvades sadaļā mēs atlasÄ«sim ziņojumus un nosÅ«tÄ«sim katru uz savu kanālu.

Ziņas parsÄ“Å”ana ar groku

Lai parsētu teksta virknes un no tām iegÅ«tu lauku kopu, filtra sadaļā ir Ä«paÅ”s spraudnis - grok.

Neizvirzot sev mērÄ·i Å”eit sniegt detalizētu aprakstu (Å”ajā sakarā es atsaucos uz to oficiālā dokumentācija), es sniegÅ”u savu vienkārÅ”o piemēru.

Lai to izdarÄ«tu, jums jāizlemj par ievades virkņu formātu. Man tie ir Ŕādi:

1 INFORMĀCIJAS ziņa1
2 KÄ»ÅŖDAS ziņojums2

Tie. Vispirms ir identifikators, pēc tam INFO/ERROR, tad vārds bez atstarpēm.
Tas nav grūti, bet ar to pietiek, lai saprastu darbības principu.

Tātad grok spraudņa filtru sadaļā mums ir jādefinē mÅ«su virkņu parsÄ“Å”anas modelis.

Tas izskatīsies Ŕādi:

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

BÅ«tÄ«bā tā ir regulāra izteiksme. Tiek izmantoti gatavi modeļi, piemēram, INT, LOGLEVEL, WORD. To aprakstu, kā arÄ« citus modeļus var atrast Å”eit Å”eit

Tagad, izejot cauri Ŕim filtram, mūsu virkne tiks pārveidota par trīs lauku jaukŔanu: message_id, message_type, message_text.

Tie tiks parādīti izvades sadaļā.

Ziņojumu marÅ”rutÄ“Å”ana uz izvades sadaļu, izmantojot komandu if

Izvades sadaļā, kā mēs atceramies, mēs plānojām sadalīt ziņojumus divās plūsmās. Daži - kas ir iNFO, tiks izvadīti uz konsoli, un ar kļūdām mēs izvadīsim failā.

Kā mēs noŔķiram Å”os ziņojumus? Problēmas stāvoklis jau liecina par risinājumu - galu galā mums jau ir speciāls lauks message_type, kurā var bÅ«t tikai divas vērtÄ«bas: INFO un ERROR. Pamatojoties uz to, mēs izdarÄ«sim izvēli, izmantojot if paziņojumu.

if [message_type] == "ERROR" {
        # Š—Š“ŠµŃŃŒ Š²Ń‹Š²Š¾Š“ŠøŠ¼ Š² фŠ°Š¹Š»
       } else
     {
      # Š—Š“ŠµŃŃŒ Š²Ń‹Š²Š¾Š“ŠøŠ¼ Š² stdout
    }

Šajā sadaļā var atrast aprakstu par darbu ar laukiem un operatoriem oficiālā rokasgrāmata.

Tagad par paŔu faktisko secinājumu.

Konsoles izvade, Ŕeit viss ir skaidrs - stdout {}

Bet izvade uz failu - atcerieties, ka mēs to visu palaižam no konteinera un, lai fails, kurā ierakstām rezultātu, bÅ«tu pieejams no ārpuses, mums ir jāatver Å”is direktorijs docker-compose.yml.

Kopā:

Mūsu faila izvades sadaļa izskatās Ŕādi:

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

Vietnē docker-compose.yml izvadei pievienojam vēl vienu sējumu:

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

Mēs to palaižam, izmēģinām un redzam sadalījumu divās plūsmās.

Avots: www.habr.com

Pievieno komentāru