Praktesch Uwendung vun ELK. Logstash opbauen

Aféierung

Beim Ofbau vun engem anere System ware mir konfrontéiert mat der Bedierfnes fir eng grouss Zuel vu verschiddene Logbicher ze veraarbecht. ELK gouf als Tool gewielt. Dësen Artikel wäert eis Erfarung diskutéieren beim Ariichten vun dësem Stack.

Mir setzen net en Zil fir all seng Fäegkeeten ze beschreiwen, mä mir wëllen eis speziell op d'Léisung vu praktesche Problemer konzentréieren. Dëst ass wéinst der Tatsaach, datt och wann et eng zimlech grouss Quantitéit vun Dokumentatioun a prett-feieren Biller ass, sinn et relativ vill Fallen, op d'mannst hu mir se fonnt.

Mir hunn de Stack iwwer Docker-compose ofgesat. Ausserdeem hate mir eng gutt geschriwwen docker-compose.yml, déi eis erlaabt de Stack bal ouni Problemer ze erhéijen. An et huet eis geschéngt datt d'Victoire scho no wier, elo wäerte mir et e bëssen upassen fir eise Besoinen ze passen an dat ass et.

Leider war de Versuch de System ze konfiguréieren fir Logbicher vun eiser Applikatioun ze kréien an ze veraarbechten net direkt erfollegräich. Dofir hu mir décidéiert datt et derwäert wier all Komponent separat ze studéieren, an dann zréck op hir Verbindungen.

Also hu mir ugefaang mat Logstash.

Ëmfeld, Deployment, Lafen Logstash an engem Container

Fir Deployment benotze mir Docker-compose; d'Experimenter, déi hei beschriwwe ginn, goufen op MacOS an Ubuntu 18.0.4 duerchgefouert.

D'Logstash-Bild dat an eisem Original docker-compose.yml registréiert gouf ass docker.elastic.co/logstash/logstash:6.3.2

Mir wäerten et fir Experimenter benotzen.

Mir hunn eng separat docker-compose.yml geschriwwen fir Logstash ze lafen. Natierlech war et méiglech d'Bild vun der Kommandozeil ze lancéieren, awer mir hunn e spezifesche Problem geléist, wou mir alles aus Docker-compose lafen.

Kuerz iwwer Configuratiounsdateien

Wéi aus der Beschreiwung follegt, kann Logstash entweder fir ee Kanal lafen, an deem Fall muss et d'*.conf Datei passéieren, oder fir verschidde Kanäl, an deem Fall muss et d'Pipelines.yml Datei passéieren, déi am Tour , wäert op d'Fichier'en .conf fir all Kanal verbannen.
Mir hunn den zweete Wee gemaach. Et schéngt eis méi universell a skalierbar ze sinn. Dofir hu mir pipelines.yml erstallt, an e Pipelines-Verzeichnis gemaach, an deem mir .conf-Dateien fir all Kanal setzen.

Am Container gëtt et eng aner Konfiguratiounsdatei - logstash.yml. Mir beréieren et net, mir benotzen et wéi et ass.

Also, eis Verzeechnesstruktur:

Praktesch Uwendung vun ELK. Logstash opbauen

Fir Inputdaten ze kréien, gi mir elo un datt dëst tcp um Hafen 5046 ass, a fir Output benotze mir stdout.

Hei ass eng einfach Konfiguratioun fir den éischte Start. Well déi éischt Aufgab ass ze starten.

Also, mir hunn dës 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

Wat gesi mer hei?

  1. Netzwierker a Bänn goufen aus dem Original docker-compose.yml geholl (deen wou de ganze Stack lancéiert gëtt) an ech mengen datt se d'Gesamtbild hei net vill beaflossen.
  2. Mir kreéieren ee Logstash Service (en) vum docker.elastic.co/logstash/logstash:6.3.2 Bild an nennen et logstash_one_channel.
  3. Mir weider port 5046 am Container, op déi selwecht intern port.
  4. Mir mapen eis Päifkonfiguratiounsdatei ./config/pipelines.yml op d'Datei /usr/share/logstash/config/pipelines.yml am Container, wou de Logstash et ophëlt an et nëmme liesen, just am Fall.
  5. Mir mapen den ./config/pipelines Verzeichnis, wou mir Dateien mat Kanalastellungen hunn, an den /usr/share/logstash/config/pipelines Verzeichnis a maachen et och nëmme liesen.

Praktesch Uwendung vun ELK. Logstash opbauen

Pipelines.yml Datei

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

Ee Kanal mat dem HABR Identifizéierer an de Wee zu senger Konfiguratiounsdatei ginn hei beschriwwen.

A schliisslech d'Datei "./config/pipelines/habr_pipeline.conf"

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

Loosst eis elo net op seng Beschreiwung goen, loosst eis probéieren et auszeféieren:

docker-compose up

Wat gesi mir?

De Container huet ugefaang. Mir kënnen hir Operatioun kontrolléieren:

echo '13123123123123123123123213123213' | nc localhost 5046

A mir gesinn d'Äntwert an der Containerkonsole:

Praktesch Uwendung vun ELK. Logstash opbauen

Awer gläichzäiteg gesi mir och:

logstash_one_channel | [2019-04-29T11:28:59,790][ERROR][logstash.licensechecker.licensereader] Kann net Lizenzinformatioun vum Lizenzserver recuperéieren {:message=>“Elasticsearch Unreachable: [http://elasticsearch:9200/][Manticore ::ResolutionFailure] elasticsearch", ...

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

logstash_one_channel | [2019-04-29T11:28:59,988][INFO ][logstash.agent ] Pipelines lafen {: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 ass op Logstash installéiert awer net op Elasticsearch. Installéiert w.e.g. X-Pack op Elasticsearch fir d'Iwwerwaachungsfunktioun ze benotzen. Aner Funktiounen kënne verfügbar sinn.
logstash_one_channel | [2019-04-29T11:29:00,526][INFO ][logstash.agent ] Logstash API Endpunkt gestart {:port=>9600}
logstash_one_channel | [2019-04-29T11:29:04,478][INFO ][logstash.outputs.elasticsearch] Lafen Gesondheetscheck fir ze kucken ob eng Elasticsearch Verbindung funktionnéiert {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,487][WARN ][logstash.outputs.elasticsearch] Versicht d'Verbindung op dout ES Instanz erëmbeliewen, awer krut e Feeler. {:url=>“elastesch Sich:9200/", :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch Unreachable: [http://elasticsearch:9200/][Manticore::Resolution Failure] elasticsearch"}
logstash_one_channel | [2019-04-29T11:29:04,704][INFO ][logstash.licensechecker.licensereader] Lafen Gesondheetscheck fir ze kucken ob eng Elasticsearch Verbindung funktionnéiert {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,710][WARN ][logstash.licensechecker.licensereader] Versicht d'Verbindung op dout ES Instanz erëmbeliewen, awer krut e Feeler. {:url=>“elastesch Sich:9200/", :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch Unreachable: [http://elasticsearch:9200/][Manticore::Resolution Failure] elasticsearch"}

An eise Logbicher kräischen déi ganzen Zäit.

Hei hunn ech a gréng de Message markéiert datt d'Pipeline erfollegräich lancéiert ass, a rout d'Fehlermeldung a giel de Message iwwer e Versuch ze kontaktéieren elastesch Sich: 9200.
Dëst geschitt well logstash.conf, am Bild abegraff, e Scheck fir elasticsearch Disponibilitéit enthält. No all, iwwerhëlt logstash datt et als Deel vun der Elk Stack Wierker, mä mir getrennt et.

Et ass méiglech ze schaffen, awer et ass net bequem.

D'Léisung ass dës Scheck iwwer d'XPACK_MONITORING_ENABLED Ëmfeldvariabel auszeschalten.

Loosst eis eng Ännerung op docker-compose.yml maachen a lafen et nach eng Kéier:

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

Elo ass alles gutt. De Container ass prett fir Experimenter.

Mir kënnen erëm an der nächster Konsole tippen:

echo '13123123123123123123123213123213' | nc localhost 5046

A kuckt:

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

Schafft an engem Kanal

Also hu mir lancéiert. Elo kënnt Dir d'Zäit huelen fir de Logstash selwer ze konfiguréieren. Loosst eis de Pipelines.yml Fichier fir elo net beréieren, kucke wat mir kënne kréien andeems Dir mat engem Kanal schafft.

Ech muss soen datt den allgemenge Prinzip fir mat der Kanalkonfiguratiounsdatei ze schaffen ass gutt an der offizieller Handbuch beschriwwen, hei hei
Wann Dir op Russesch wëllt liesen, hu mir dëst benotzt Artikel(awer d'Ufro-Syntax do ass al, mir mussen dat berücksichtegen).

Loosst eis sequenziell vun der Input Sektioun goen. Mir hu schonn Aarbecht op tcp gesinn. Wat kéint hei nach interessant sinn?

Test Messagen mat Häerzschlag

Et gëtt sou eng interessant Geleeënheet fir automatesch Testmeldungen ze generéieren.
Fir dëst ze maachen, musst Dir den Heartbean Plugin an der Input Sektioun aktivéieren.

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

Maacht et un, fänkt un eemol pro Minutt ze kréien

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

Wa mir méi dacks wëlle kréien, musse mir den Intervallparameter derbäisetzen.
Dëst ass wéi mir all 10 Sekonnen e Message kréien.

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

Recuperéieren Daten aus enger Datei

Mir hunn och decidéiert de Dateimodus ze kucken. Wann et gutt mat der Datei funktionnéiert, da gëtt vläicht keen Agent gebraucht, gutt, op d'mannst fir lokal Benotzung.

Laut der Beschreiwung soll de Betribsmodus ähnlech wéi Schwanz -f sinn, d.h. liest nei Zeilen oder, als Optioun, liest de ganze Fichier.

Also wat mir wëllen kréien:

  1. Mir wëllen Zeilen kréien, déi un eng Logdatei bäigefüügt ginn.
  2. Mir wëllen Daten kréien, déi op e puer Logdateien geschriwwe sinn, wärend mir fäeg sinn ze trennen wat vu wou kritt gëtt.
  3. Mir wëllen sécherstellen datt wann de Logstash nei gestart gëtt, et dës Donnéeën net erëm kritt.
  4. Mir wëllen iwwerpréiwen datt wann de Logstash ausgeschalt ass, an d'Daten weider op Dateien geschriwwe ginn, da wa mir se lafen, kréien mir dës Donnéeën.

Fir den Experiment ze maachen, loosst eis eng aner Zeil op docker-compose.yml derbäisetzen, de Verzeichnis opmaachen an deem mir d'Dateien setzen.

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

A änneren d'Input Rubrik an habr_pipeline.conf

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

Loosst eis ufänken:

docker-compose up

Fir Logbicher ze kreéieren an ze schreiwen benotze mir de Kommando:


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

Jo, et funktionnéiert!

Zur selwechter Zäit gesi mir datt mir automatesch de Weefeld bäigefüügt hunn. Dëst bedeit datt mir an Zukunft records dorop kënnen filteren.

Loosst eis nach eng Kéier probéieren:

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

An elo zu engem anere Fichier:

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

Super! D'Datei gouf opgeholl, de Wee gouf korrekt spezifizéiert, alles ass gutt.

Stop Logstash a fänkt erëm un. Loosst eis waarden. Rou. Déi. Mir kréien dës records net erëm.

An elo dat getraut Experiment.

Installéiert Logstash an ausféiert:

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

Run Logstash erëm a kuckt:

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

Hour! Alles gouf opgeholl.

Mä mir mussen Iech iwwer déi folgend warnen. Wann de Logstash Container geläscht gëtt (docker stop logstash_one_channel && docker rm logstash_one_channel), da gëtt näischt opgeholl. D'Positioun vun der Datei bis zu där se gelies gouf gouf am Container gespäichert. Wann Dir et vun Null leeft, akzeptéiert et nëmmen nei Linnen.

Liesen bestehend Fichieren

Loosst eis soen datt mir Logstash fir d'éischte Kéier lancéieren, awer mir hu scho Logbicher a mir wëllen se veraarbechten.
Wa mir Logstash mat der Input Sektioun lafen, déi mir uewe benotzt hunn, kréie mir näischt. Nëmmen nei Linnen ginn duerch Logstash veraarbecht.

Fir Linnen aus existente Dateien ze zéien, sollt Dir eng zousätzlech Zeil an d'Input Sektioun addéieren:

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

Ausserdeem gëtt et eng Nuance: dëst beaflosst nëmmen nei Dateien déi de Logstash nach net gesinn huet. Fir déiselwecht Dateien, déi schonn am Siichtfeld vu Logstash waren, huet et schonn hir Gréisst erënnert a wäert elo nëmmen nei Entréen an hinnen huelen.

Loosst eis hei ophalen an d'Input Sektioun studéieren. Et ginn nach vill Optiounen, awer dat ass genuch fir eis fir weider Experimenter fir de Moment.

Routing an Daten Transformatioun

Loosst eis probéieren de folgende Problem ze léisen, loosst eis soen datt mir Messagen vun engem Kanal hunn, e puer vun hinnen sinn informativ, an e puer sinn Fehlermeldungen. Si ënnerscheede sech duerch Tag. E puer sinn INFO, anerer sinn ERROR.

Mir mussen se bei der Sortie trennen. Déi. Mir schreiwen Informatiounsmeldungen an engem Kanal, a Fehlermeldungen an engem aneren.

Fir dëst ze maachen, réckelt vun der Input Sektioun op Filter an Output.

Mat der Filtersektioun wäerte mir déi erakommen Noriicht parséieren, en Hash (Schlëssel-Wäertpairen) kréien, mat deem mir scho kënne schaffen, d.h. no Konditiounen disassemble. An an der Ausgangssektioun wäerte mir Messagen auswielen an all eenzel op säin eegene Kanal schécken.

Parsing e Message mat Grok

Fir Text Strings ze analyséieren an e Set vu Felder vun hinnen ze kréien, gëtt et e spezielle Plugin an der Filtersektioun - grok.

Ouni mech d'Zil ze setzen fir eng detailléiert Beschreiwung dovun hei ze ginn (fir dëst bezéien ech op offiziell Dokumentatioun), Ech ginn mäi einfacht Beispill.

Fir dëst ze maachen, musst Dir iwwer d'Format vun den Input Saiten entscheeden. Ech hunn se esou:

1 INFO Message1
2 Feelmeldung 2

Déi. Den Identifizéierer kënnt als éischt, dann INFO/Feeler, dann e puer Wuert ouni Raum.
Et ass net schwéier, awer et ass genuch fir de Prinzip vun der Operatioun ze verstoen.

Also, an der Filtersektioun vum Grok Plugin, musse mir e Muster definéieren fir eis Saiten ze analyséieren.

Et wäert esou ausgesinn:

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

Wesentlech ass et e reguläre Ausdrock. Fäerdeg Mustere gi benotzt, wéi INT, LOGLEVEL, WORD. Hir Beschreiwung, wéi och aner Mustere kënnen hei fonnt ginn hei

Elo, duerch dëse Filter passéiert, wäert eis String an en Hash vun dräi Felder verwandelen: message_id, message_type, message_text.

Si ginn an der Ausgangssektioun ugewisen.

Routing Messagen op d'Output Sektioun mat dem Kommando if

An der Ausgangssektioun, wéi mir eis erënneren, wäerte mir d'Botschaften an zwee Streamen opdeelen. E puer - déi iNFO sinn, ginn op d'Konsole erausginn, a mat Feeler wäerte mir op eng Datei erausginn.

Wéi trenne mir dës Messagen? Den Zoustand vum Problem proposéiert schonn eng Léisung - schliisslech hu mir schonn en dedizéierten Message_type Feld, deen nëmmen zwee Wäerter ka huelen: INFO an ERROR. Et ass op dëser Basis datt mir e Choix maache mat der if Ausso.

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

Eng Beschreiwung vun der Aarbecht mat Felder an Opérateuren kann an dëser Rubrik fonnt ginn offiziell Handbuch.

Elo iwwer déi eigentlech Conclusioun selwer.

Konsolausgang, hei ass alles kloer - stdout {}

Awer d'Ausgab op eng Datei - erënnert datt mir all dëst aus engem Container lafen a fir datt d'Datei, an där mir d'Resultat schreiwen, vu baussen zougänglech ass, musse mir dëse Verzeechnes an docker-compose.yml opmaachen.

Total:

D'Output Sektioun vun eiser Datei gesäit esou aus:


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

An docker-compose.yml addéiere mer en anere Volume fir d'Ausgab:

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

Mir starten et, probéieren et a gesinn eng Divisioun an zwee Streamen.

Source: will.com

Setzt e Commentaire