ELK praktiline rakendamine. Seame sisse logstashi

Sissejuhatus

Uue süsteemi seadistamisel seisime silmitsi vajadusega töödelda suurt hulka erinevaid logisid. Tööriistana valisime ELK-i. Käesolevas artiklis räägime oma kogemustest selle tehnoloogia seadistamisel.

Me ei püüa kirjeldada kõiki selle võimalusi, vaid tahame keskenduda praktiliste probleemide lahendamisele. See on tingitud sellest, et kuigi dokumentatsiooni ja valmisipildid on piisavalt, võib alatu takistusi olla palju, vähemalt meie kogemuses ilmnesid need.

Seadsime stacki üles docker-compose'i kaudu. Veelgi enam, meil oli hästi kirjutatud docker-compose.yml, mis võimaldas meil peaaegu probleemideta stacki üles tõsta. Meile tundus, et võit on käeulatuses, nüüd kohandame seda veidi oma vajadustele ja kõik on korras.

Kahjuks ei õnnestunud meil kohe logide vastuvõtmise ja töötlemise seadistamine meie rakenduselt. Seetõttu otsustasime, et tasub uurida iga komponenti eraldi ja seejärel naasta nende seoste juurde.

Nii et alustasime logstashist.

Keskkond, Logstashi seadistamine ja paigaldamine konteineris

Kasutame rakenduste seadistamiseks docker-compose'i, need eksperimentide kirjeldused viidi läbi MacOS-is ja Ubuntu 18.0.4-l.

Meie docker-compose.yml failis määratletud logstash pilt on docker.elastic.co/logstash/logstash:6.3.2.

Seda kasutame eksperimenteerimiseks.

Logstashi käitamiseks kirjutasime eraldi docker-compose.yml faili. Loomulikult oleks võinud pilti käsurealt käivitada, kuid me lahendasime konkreetset ülesannet, kus kõik käivitatakse docker-compose'i kaudu.

Lühike ülevaade konfiguratsioonifailidest.

Kuna kirjelduse kohaselt saab logstashi käivitada kas ühe kanali jaoks, selleks tuleb edastada *.conf fail, või mitme kanali jaoks, sel juhul tuleb edastada pipelines.yml fail, mis omakorda viitab .conf failidele iga kanali jaoks.
Valisime teise tee. See tundus meile universaalsem ja skaleeritavam. Seetõttu lõime pipelines.yml faili ja kujundasime pipelines katalooge, kuhu paigutame .conf failid iga kanali jaoks.

Konteineris on veel üks konfiguratsioonifail — logstash.yml. Me ei puuduta seda, kasutame seda sellisena nagu see on.

Nii et meie kataloogide struktuur on järgmine:

ELK praktiline rakendamine. Seame sisse logstashi

Sisendi andmete saamiseks oletame, et see on TCP sadamal 5046 ning väljundi jaoks kasutame stdout.

Siin on nii lihtne konfiguratsioon esmakäivitamiseks. Lõppude lõpuks on algne eesmärk — käivitada.

Nii et meil on selline 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 mahutid on võetud algsest docker-compose.yml-st (see, kus kogu virn käivitub), ja ma arvan, et nad ei mõjuta oluliselt üldpilti.
  2. Loome ühe teenuse (services) logstash, kasutades pilti docker.elastic.co/logstash/logstash:6.3.2 ning määrame sellele nimeks logstash_one_channel.
  3. Me edastame konteinerisse sadama 5046, samal sisemisel sadamal.
  4. Me kaardistame oma kanali seadistusfaili ./config/pipelines.yml failile /usr/share/logstash/config/pipelines.yml konteineri sees, kust logstash selle haarab ja teeme selle ainult lugemiseks, igaks juhuks.
  5. Kuvame katalooge ./config/pipelines, kus asuvad meie kanalite seadistamise failid, katalooge /usr/share/logstash/config/pipelines ja muudame selle samuti ainult lugemiseks.

ELK praktiline rakendamine. Seame sisse logstashi

Fail pipelines.yml

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

Siin on kirjeldatud ühte kanalit ID-ga HABR ja tee selle konfigureerimisfailini.

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

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

Ärme süvene selle kirjelduse detaile, proovime seda käivitada:

docker-compose up

Mida me näeme?

Konteiner käivitati. Saame kontrollida selle tööd:

echo '13123123123123123123123213123213' | nc localhost 5046

Ja näeme konteineri konsoolis vastust:

ELK praktiline rakendamine. Seame sisse logstashi

Kuid samal ajal näeme ka:

logstash_one_channel | [2019-04-29T11:28:59,790][ERROR][logstash.licensechecker.licensereader] Unable to retrieve license information from license server {:message=>"Elasticsearch Unreachable: [http://elasticsearch:9200/][Manticore::ResolutionFailure] elasticsearch", …

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

logstash_one_channel | [2019-04-29T11:28:59,988][INFO ][logstash.agent ] Pipelines running {:count=>2, :running_pipelines=>[:HABR, :".monitoring-logstash"], :non_running_pipelines=>[]}
logstash_one_channel | [2019-04-29T11:29:00,015][ERROR][logstash.inputs.metrics ] X-Pack on Logstash is installed, but not on Elasticsearch. Please install X-Pack on Elasticsearch to enable the monitoring feature. Other features might still be available.
logstash_one_channel | [2019-04-29T11:29:00,526][INFO ][logstash.agent ] Logstash API endpoint successfully started {:port=>9600}
logstash_one_channel | [2019-04-29T11:29:04,478][INFO ][logstash.outputs.elasticsearch] Running health check to verify if the Elasticsearch connection is functioning {:healthcheck_url=>http://elasticsearch:9200/, :path=>"/"}
logstash_one_channel | [2019-04-29T11:29:04,487][WARN ][logstash.outputs.elasticsearch] Attempted to revive the connection to a dead ES instance, but encountered an error. {:url=>«elasticsearch:9200/», :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>«Elasticsearch Unreachable: [http://elasticsearch:9200/][Manticore::ResolutionFailure] elasticsearch»}
logstash_one_channel | [2019-04-29T11:29:04,704][INFO ][logstash.licensechecker.licensereader] Running health check to verify if the Elasticsearch connection is functioning {:healthcheck_url=>http://elasticsearch:9200/, :path=>"/"}
logstash_one_channel | [2019-04-29T11:29:04,710][WARN ][logstash.licensechecker.licensereader] Attempted to revive the connection to a dead ES instance, but encountered an error. {:url=>«elasticsearch:9200/», :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>«Elasticsearch Unreachable: [http://elasticsearch:9200/][Manticore::ResolutionFailure] elasticsearch»}

Ja meie logi tõuseb pidevalt.

Siin olen tõstnud roheline värviga esile sõnumi, et pipeline käivitus edukalt, punasega — veateate ja kollasega — sõnumi katsetest ühendust võtta. elasticsearch:9200.
See, see, et on logstash.conf, mis on kaasatud pildi, olemas elasticsearch'i kättesaadavuse kontroll. Logstash eeldab, et see töötab Elk stackis, kuid me oleme selle eraldanud.

Töötamine on võimalik, aga ebamugav.

Lahenduseks on selle kontrolli keelamine XPACK_MONITORING_ENABLED keskkonnamuutuja kaudu.

Teeme muudatuse docker-compose.yml ja käivitame 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 korras. Konteiner on katsetamiseks valmis.

Saame uuesti naaberterminalis kirjutada:

echo '13123123123123123123123213123213' | nc localhost 5046

Ja näha:

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öö ühe kanali piires

Nii, oleme käivitanud. Nüüd saame aega pühendada logstashi seadistamisele. Ärgem puudutame veel faili pipelines.yml, vaatame, mida saame teha ühe kanaliga.

Pean ütlema, et kanali konfigureerimise üldine põhimõte on hästi kirjeldatud ametlikus juhendis, siin on link: siit
Kui soovite lugeda vene keeles, siis kasutasime seda: artiklit(aga päringute süntaks seal on vana, seda tuleb silmas pidada).

Liigume järjestikku Input sektsiooni. TCP töö on juba nähtud. Mis veel siin võiks huvitav olla?

Test sõnumid, kasutades heartbeat'i

On olemas huvitav võimalus genereerida automaatseid test sõnumeid.
Selleks tuleb input sektsiooni lisada heartbeat plugin.

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

Aktiveerime, hakkame saama sõnumeid iga minuti tagant.

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

Tahame sagedamini saada, peame lisama parameetri interval.
Nii saame sõnumi iga 10 sekundi tagant.

sisend {
  südame löögisagedus {
    sõnum => "Südame löögisagedus!"
    intervall => 10
   }
  }

Andmete saamine failist

Otsustasime ka vaadata file režiimi. Kui failiga töötab normaalselt, siis võib-olla ei ole agenti üldse vaja, vähemalt kohaliku kasutuse jaoks.

Kirjelduse järgi peaks töörežiim olema analoogne tail -f, st loeb uusi ridu või, nagu valik, loeb kogu faili.

Nii et mida me tahame saada:

  1. Me tahame saada ridu, mis lisatakse ühte logifaili.
  2. Me tahame saada andmeid, mis kirjutatakse mitmesse logifaili, samas on meil võimalus eristada, kust mis on saadud.
  3. Me tahame kontrollida, et logstash'i taaskäivitamisel ei saa ta neid andmeid uuesti.
  4. Me tahame kontrollida, et kui logstash lahti ühendada, aga andmeid faile jätkuvalt kirjutatakse, siis kui me selle käivitame, saame need andmed.

Eksperimendi läbiviimiseks lisame docker-compose.yml faili veel ühe rea, avades kausta, kuhu me failid paneme.

versioon: '3'

võrgud:
  elk:

mahud:
  elasticsearch:
    draiver: kohalik

teenused:

  logstash:
    konteineri_nimi: logstash_one_channel
    pilt: docker.elastic.co/logstash/logstash:6.3.2
    võrgud:
      - elk
    keskkond:
      XPACK_MONITORING_ENABLED: "false"
    sadamad:
      - 5046:5046
   mahud:
      - ./config/pipelines.yml:/usr/share/logstash/config/pipelines.yml:ro
      - ./config/pipelines:/usr/share/logstash/config/pipelines:ro
      - ./logs:/usr/share/logstash/input

Ja muudame sektsiooni input failis habr_pipeline.conf

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

Käivitame:

docker-compose up

Logifailide loomise ja salvestamise jaoks 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 | }

Nojah, töötab!

Sellega näeme, et meil on automaatselt lisatud väli path. See tähendab, et tulevikus saame selle alusel kirjeid filtreerida.

Proovime veel:

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 teises failis:

 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 on edukalt laaditud, path on õige, kõik on hästi.

Peatame logstashi ja käivitame selle uuesti. Ootame. Vaikus. Ehk siis, neid kirjeid me uuesti ei saa.

Ja nüüd kõige julgem katse.

Kandke logstash ja täitke:

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

Käivitage logstash uuesti ja näeme:

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

Hästi! Kõik on laaditud.

Kuid tuleb tähelepanu juhtida järgmisele. Kui konteiner logstash eemaldatakse (docker stop logstash_one_channel && docker rm logstash_one_channel), siis ei jää midagi kinni. Konteineris säilitati faili positsioon, millele oli lugemine peatatud. Kui käivitame "nullist", siis aktsepteerib see ainult uusi ridu.

Juba olemasolevate failide lugemine

Oletame, et käivitame logstashi esmakordselt, kuid meil on juba logid ja tahame neid töödelda.
Kui käivitame logstashi sama input-sektsiooniga, mida kasutasime varem, siis ei saa me midagi. Ainult uusi ridu töödeldakse logstashi poolt.

Et olemasolevatest failidest ridasid võtta, tuleb input-sektsiooni lisada järgmine rida:

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

Oluline on märkida, et see kehtib ainult uute failide kohta, mida logstash pole veel näinud. Juba varasemalt logstashi tähelepanu saanud failide puhul on see juba nende suuruse meelde jätnud ja nüüd võtab sealt ainult uusi kirjeid.

Lõpetame selle input-sektsiooni uurimisega. Seal on veel palju variante, kuid meie edasiseks katsetamiseks piisab praegu sellest.

Andmete suunamine ja töötlemine

Proovime lahendada järgmise ülesande, oletame, et meil on teavet, mis tuleb ühelt kanalilt, osa neist on informatiivsed ja osa veateated. Need erinevad sildi poolest. Ühed on INFO, teised ERROR.

Me peame need väljundis eraldama. St. Informatiivsed teated kirjutame ühte kanalisse ja veateated teise.

Selleks liigume input sektsioonist filteri ja väljundisse.

Filtri sektsiooni abil analüüsime sisendteate, saades selle tulemusena hash (võti-väärtus paarid), millega on juba võimalik töötada, st. analüüsida tingimuste alusel. Väljundi sektsioonis valime teated ja saadame igaühe oma kanalisse.

Teate analüüsimine grok abil

Kuna me tahame analüüsida tekstiridasid ja saada neist välja hulga välju, on filtri sektsioonis spetsiaalne pistikprogramm — grok.

Ilma et seaksime eesmärgiks selle üksikasjaliku kirjelduse andmise (selle jaoks suunangi teid), ametlikus dokumentatsioonistoome oma lihtsa näite.

Selleks tuleb kindlaks teha sisendriistade format. Minu omad näevad välja sellised:

1 INFO message1
2 ERROR message2

St. Identsifitseerija on esimesel kohal, seejärel INFO/ERROR, seejärel mõni sõna ilma tükkideta.
Ei ole keeruline, kuid põhimõtte mõistmiseks piisab sellest.

Seega, grok plugin'is filter jaotises peame määrama mustri meie stringide analüüsimiseks.

See näeb välja järgmine:

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

Põhimõtteliselt on see regulaarne väljend. Kasutatakse juba olemasolevaid mustreid, nagu INT, LOGLEVEL, WORD. Nende kirjeldust ning teisi mustreid saab vaadata siit siit

Nüüd, liikudes läbi selle filtri, muutub meie string hash'iks, mis koosneb kolmest väljast: message_id, message_type, message_text.

Need väljad kuvatakse output jaotises.

Sõnumite marsruutimine output jaotises if käsu abil

Output jaotises, nagu me mäletame, plaanisime jagada sõnumid kaheks vooguks. Ühed – INFO, kuvatakse konsoolile, ja veateated salvestatakse faili.

Kuidas need sõnumid jagada? Ülesande tingimus juba vihjab lahendusele – meil on juba eraldatud väli message_type, mis võib omada ainult kahte väärtust INFO ja ERROR. Just selle põhjal teeme valiku if operaatori abil.

if [message_type] == "ERROR" {
        # Siin väljastame faili
       } else
     {
      # Siin väljastame stdout'i
    }

Väljade ja operaatoritega töötamise kirjeldust saab vaadata siit ametlikust manuaalist.

Nüüd, räägime täpselt väljundist.

Väljund konsooli, siin on kõik selge — stdout {}

Aga väljund faili — meenutame, et käivitame seda kõik konteinerist ja et fail, kuhu me kirjutame tulemuse, oleks väljastpoolt kättesaadav, peame avama selle katalooge docker-compose.yml-is.

Kokku:

Meie faili väljundi osa 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 {
             }
     }
  }

docker-compose.yml-i lisame veel ühe mahu, väljundiks:

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

Käivitame, proovime, näeme jagunemist kahte voogu.

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster