ELK-nın praktik tətbiqi. Logstash qurulur

Giriş

Başqa bir sistemi yerləşdirərkən çoxlu sayda müxtəlif logları emal etmək ehtiyacı ilə qarşılaşdıq. Alət kimi ELK seçilmişdir. Bu yazı bu yığını qurmaq təcrübəmizdən danışacaq.

Biz onun bütün imkanlarını təsvir etməyi qarşımıza məqsəd qoymuruq, amma diqqətimizi praktiki problemlərin həllinə cəmləmək istəyirik. Bu, kifayət qədər böyük miqdarda sənədləşdirmə və hazır şəkillərlə çoxlu tələlərin olması ilə əlaqədardır, heç olmasa onları tapdıq.

Biz yığını docker-compose vasitəsilə yerləşdirdik. Üstəlik, yaxşı yazılmış docker-compose.yml-imiz var idi ki, bu, demək olar ki, heç bir problem olmadan yığını qaldırmağa imkan verdi. Bizə elə gəldi ki, qələbə artıq yaxındır, indi ehtiyaclarımıza uyğunlaşdırmaq üçün onu bir az bükəcəyik və bu qədər.

Təəssüf ki, tətbiqimizdən qeydləri qəbul etmək və emal etmək üçün sistemi tənzimləmək cəhdi dərhal uğurlu alınmadı. Buna görə də qərara gəldik ki, hər bir komponenti ayrıca öyrənməyə və sonra onların əlaqələrinə qayıtmağa dəyər.

Beləliklə, logstash ilə başlayaq.

Ətraf mühit, yerləşdirmə, Logstash-ı konteynerdə işə salmaq

Yerləşdirmə üçün biz docker-compose istifadə edirik, burada təsvir edilən təcrübələr MacOS və Ubuntu 18.0.4-də aparılmışdır.

Orijinal docker-compose.yml-də olan logstash şəkli docker.elastic.co/logstash/logstash:6.3.2-dir.

Təcrübələr üçün istifadə edəcəyik.

Logstash-ı işə salmaq üçün ayrıca docker-compose.yml yazdıq. Əlbəttə ki, təsviri komanda xəttindən işə salmaq mümkün idi, amma nəticədə biz docker-compose-dan tutmuş hər şeyin bizim üçün işə salındığı xüsusi bir vəzifəni həll etdik.

Konfiqurasiya faylları haqqında qısaca

Təsvirdən göründüyü kimi, logstash bir kanal üçün olduğu kimi işlədilə bilər, bu halda *.conf faylını və ya bir neçə kanal üçün köçürməlidir, bu halda pipelines.yml faylını köçürməlidir ki, bu da öz növbəsində. , hər bir kanal üçün .conf fayllarına istinad edəcək.
İkinci yolu tutduq. Bizə daha çox yönlü və miqyaslı görünürdü. Beləliklə, biz pipelines.yml yaratdıq və hər bir kanal üçün .conf fayllarını yerləşdirəcəyimiz boru kəmərləri kataloqu yaratdıq.

Konteynerin içərisində başqa bir konfiqurasiya faylı var - logstash.yml. Biz ona toxunmuruq, olduğu kimi istifadə edirik.

Beləliklə, kataloq quruluşumuz:

ELK-nın praktik tətbiqi. Logstash qurulur

Hələlik, bunun giriş məlumatlarını qəbul etmək üçün 5046 portunda tcp olduğunu güman edirik və çıxış üçün stdout-dan istifadə edəcəyik.

Budur, ilk qaçış üçün belə sadə bir konfiqurasiya. Çünki ilkin vəzifə işə başlamaqdır.

Beləliklə, bizdə bu docker-compose.yml var

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

Biz burada nə görürük?

  1. Şəbəkələr və həcmlər orijinal docker-compose.yml-dən götürülüb (bütün yığının işə salındığı yer) və məncə, onlar buradakı ümumi mənzərəyə o qədər də təsir etmir.
  2. Biz docker.elastic.co/logstash/logstash:6.3.2 şəklindən bir logstash xidmət (xidmət) yaradırıq və ona logstash_one_channel adını veririk.
  3. Konteynerin içindəki 5046 portunu eyni daxili porta yönləndiririk.
  4. Biz ./config/pipelines.yml boru konfiqurasiya faylımızı konteynerin içindəki /usr/share/logstash/config/pipelines.yml faylına uyğunlaşdırırıq, burada logstash onu götürəcək və hər ehtimala qarşı onu yalnız oxumaq üçün edəcək.
  5. Biz boru konfiqurasiya fayllarının olduğu ./config/pipelines qovluğunu /usr/share/logstash/config/pipelines qovluğuna uyğunlaşdırırıq və onu yalnız oxumaq üçün edirik.

ELK-nın praktik tətbiqi. Logstash qurulur

piping.yml faylı

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

O, HABR identifikatoru ilə bir kanalı və onun konfiqurasiya faylına gedən yolu təsvir edir.

Və nəhayət "./config/pipelines/habr_pipeline.conf" faylı

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

Hələlik onun təsvirinə girməyəcəyik, qaçmağa çalışırıq:

docker-compose up

Biz nə görürük?

Konteyner başladı. Onun işini yoxlaya bilərik:

echo '13123123123123123123123213123213' | nc localhost 5046

Konteyner konsolunda cavabı görürük:

ELK-nın praktik tətbiqi. Logstash qurulur

Ancaq eyni zamanda biz də görürük:

logstash_one_channel | [2019-04-29T11:28:59,790][SƏHV][logstash.licensechecker.licensereader] Lisenziya serverindən lisenziya məlumatını almaq mümkün deyil {:message=>"Elasticsearch Unreachable: [http://elasticsearch:9200/][Manticore ::ResolutionFailure]elasticsearch", ...

logstash_one_channel | [2019-04-29T11:28:59,894][INFO ][logstash.pipeline ] Boru kəməri uğurla başladı {:pipeline_id=>".monitoring-logstash", :thread=>"# »}

logstash_one_channel | [2019-04-29T11:28:59,988][INFO ][logstash.agent ] Çalışan boru kəmərləri {:count=>2, :running_pipelines=>[:HABR, :".monitoring-logstash"], :non_running_pipelines=>[ ]}
logstash_one_channel | [2019-04-29T11:29:00,015][SƏTƏ][logstash.inputs.metrics ] X-Pack Logstash-da quraşdırılıb, lakin Elasticsearch-də deyil. Monitorinq funksiyasından istifadə etmək üçün X-Pack-i Elasticsearch-ə quraşdırın. Digər funksiyalar mövcud ola bilər.
logstash_one_channel | [2019-04-29T11:29:00,526][INFO ][logstash.agent ] Logstash API son nöqtəsi uğurla başladı {:port=>9600}
logstash_one_channel | [2019-04-29T11:29:04,478][INFO ][logstash.outputs.elasticsearch] Elasticsearch bağlantısının işlədiyini yoxlamaq üçün sağlamlıq yoxlanışı aparılır {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,487][XƏBƏRDARLIQ ][logstash.outputs.elasticsearch] Ölü ES nümunəsi ilə əlaqəni bərpa etməyə çalışdı, lakin xəta aldı. {:url=>"elastik tədqiqat:9200/", :error_type=>LogStash::Çıxışlar::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch Unreachable: [http://elasticsearch:9200/:][Manticore:il] elasticsearch"}
logstash_one_channel | [2019-04-29T11:29:04,704][INFO ][logstash.licensechecker.licensereader] Elasticsearch bağlantısının işlədiyini yoxlamaq üçün sağlamlıq yoxlanışı aparılır {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,710][XƏBƏRDARLIQ ][logstash.licensechecker.licensereader] Ölü ES nümunəsi ilə əlaqəni bərpa etməyə çalışdı, lakin xəta aldı. {:url=>"elastik tədqiqat:9200/", :error_type=>LogStash::Çıxışlar::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch Unreachable: [http://elasticsearch:9200/:][Manticore:il] elasticsearch"}

Və jurnalımız hər zaman sürünür.

Burada boru kəmərinin uğurla başladığı mesajını yaşıl rənglə, qırmızı ilə xəta mesajını və sarı rənglə əlaqə saxlamağa çalışmaq barədə mesajı vurğuladım. elastik tədqiqat: 9200.
Bu, şəkilə daxil olan logstash.conf-da elasticsearch-ın mövcudluğunun yoxlanılması ilə əlaqədar baş verir. Axı, logstash onun Elk yığınının bir hissəsi kimi işlədiyini düşünür və biz onu ayırdıq.

İşləmək olar, amma rahat deyil.

Həll yolu XPACK_MONITORING_ENABLED mühit dəyişəni vasitəsilə bu yoxlamanı deaktiv etməkdir.

Gəlin docker-compose.yml faylına dəyişiklik edək və onu yenidən işə salaq:

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

İndi hər şey qaydasındadır. Konteyner təcrübələr üçün hazırdır.

Qonşu konsolda yenidən yaza bilərik:

echo '13123123123123123123123213123213' | nc localhost 5046

Və baxın:

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

Bir kanalda işləyin

Beləliklə, başladıq. İndi logstash-ı birbaşa konfiqurasiya etmək üçün həqiqətən vaxt ayıra bilərsiniz. Hələlik pipelines.yml faylına toxunmayaq, görək bir kanalla işləməklə nə əldə edə bilərik.

Deməliyəm ki, kanal konfiqurasiya faylı ilə işləməyin ümumi prinsipi rəsmi təlimatda, burada yaxşı təsvir edilmişdir burada
Əgər rus dilində oxumaq istəyirsinizsə, onda biz bundan istifadə etdik məqalə(lakin sorğu sintaksisi orada köhnədir, bunu nəzərə almaq lazımdır).

Gəlin Giriş bölməsindən ardıcıl olaraq gedək. Biz artıq tcp üzərində işi görmüşük. Burada başqa nə maraqlı ola bilər?

Ürək döyüntüsündən istifadə edərək mesajları sınayın

Avtomatik test mesajları yaratmaq üçün belə maraqlı bir imkan var.
Bunun üçün giriş bölməsinə heartbean plaginini daxil etməlisiniz.

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

Onu yandırırıq, dəqiqədə bir dəfə almağa başlayırıq

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

Biz daha tez-tez qəbul etmək istəyirik, interval parametrini əlavə etməliyik.
Beləliklə, hər 10 saniyədən bir mesaj alacağıq.

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

Fayldan məlumatların alınması

Biz də fayl rejiminə baxmaq qərarına gəldik. Faylla yaxşı işləyirsə, heç olmasa yerli istifadə üçün heç bir agent tələb olunmaması mümkündür.

Təsvirə görə, iş rejimi quyruq -f ilə oxşar olmalıdır, yəni. yeni sətirləri oxuyur və ya istəyə görə bütün faylı oxuyur.

Beləliklə, əldə etmək istədiyimiz şey:

  1. Biz bir log faylına əlavə olunan sətirləri qəbul etmək istəyirik.
  2. Biz haradan qəbul edildiyini ayıra bildiyimiz halda, bir neçə log faylına yazılmış məlumatları qəbul etmək istəyirik.
  3. Biz əmin olmaq istəyirik ki, logstash yenidən işə salındıqda bu məlumatları bir daha qəbul etməyəcək.
  4. Yoxlamaq istəyirik ki, logstash söndürülübsə və məlumatlar fayllara yazılmağa davam edirsə, onu işə saldığımız zaman bu məlumatları alacağıq.

Təcrübəni aparmaq üçün faylları yerləşdirdiyimiz kataloqu açaraq docker-compose.yml-ə daha bir sətir əlavə edək.

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

Və habr_pipeline.conf-da giriş bölməsini dəyişdirin

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

Başlayırıq:

docker-compose up

Günlük faylları yaratmaq və yazmaq üçün əmrdən istifadə edəcəyik:


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

Bəli, işləyir!

Eyni zamanda, biz avtomatik olaraq yol sahəsini əlavə etdiyimizi görürük. Beləliklə, gələcəkdə biz bununla bağlı qeydləri süzgəcdən keçirə biləcəyik.

Yenidən cəhd edək:

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

İndi başqa bir fayla:

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

Əla! Fayl götürüldü, yol düzgün göstərildi, hər şey qaydasındadır.

Logstash'ı dayandırın və yenidən başladın. Gəlin gözləyək. Sükut. Bunlar. Bu qeydləri bir daha almırıq.

İndi isə ən cəsarətli təcrübə.

Logstash qoyduq və icra edirik:

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

Logstash-ı yenidən işə salın və baxın:

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

Yaşasın! Hər şey alındı.

Lakin, aşağıdakılar barədə xəbərdarlıq etmək lazımdır. Əgər logstash konteyneri çıxarılarsa (docker stop logstash_one_channel && docker rm logstash_one_channel), heç nə götürülməyəcək. Faylın oxunduğu yer konteynerin içərisində saxlanılırdı. Sıfırdan başlasanız, o, yalnız yeni sətirləri qəbul edəcək.

Mövcud faylların oxunması

Tutaq ki, biz ilk dəfə logstash işlədirik, lakin bizdə artıq qeydlər var və biz onları emal etmək istərdik.
Yuxarıda istifadə etdiyimiz giriş bölməsi ilə logstash işlətsək, heç nə əldə etməyəcəyik. Yalnız yeni sətirlər logstash tərəfindən işlənəcək.

Mövcud fayllardan xətləri çəkmək üçün giriş bölməsinə əlavə bir sətir əlavə edin:

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

Üstəlik, bir nüans var, bu, yalnız logstash'ın hələ görmədiyi yeni fayllara təsir edir. Artıq logstash görünüş sahəsində olan eyni fayllar üçün, o, artıq ölçülərini xatırladı və indi yalnız yeni qeydlər alacaq.

Gəlin giriş bölməsini öyrənərək bununla bağlı dayanaq. Daha bir çox variant var, lakin hələlik əlavə təcrübələr üçün kifayət qədər imkanımız var.

Marşrutlaşdırma və məlumatların çevrilməsi

Gəlin aşağıdakı problemi həll etməyə çalışaq, tutaq ki, bir kanaldan mesajlarımız var, bəziləri məlumat xarakterli, bəziləri isə xəta mesajlarıdır. Onlar etiketdə fərqlənirlər. Bəziləri MƏLUMAT, digərləri isə XƏTAdır.

Çıxışda onları ayırmalıyıq. Bunlar. Bir kanalda məlumat mesajları, digərində isə səhv mesajları yazırıq.

Bunu etmək üçün giriş bölməsindən filtrə və çıxışa keçin.

Filtr bölməsindən istifadə edərək, daxil olan mesajı təhlil edəcəyik, ondan artıq işləyə biləcəyimiz bir hash (açar-dəyər cütləri) alacağıq, yəni. şərtlərə uyğun olaraq təhlil edin. Çıxış bölməsində isə mesajları seçib hər birini öz kanalına göndərəcəyik.

grok ilə mesajın təhlili

Mətn sətirlərini təhlil etmək və onlardan bir sıra sahələr əldə etmək üçün filtr bölməsində xüsusi bir plagin var - grok.

Burada onun ətraflı təsvirini verməyi qarşısına məqsəd qoymadan (bunun üçün istinad edirəm rəsmi sənədlər), sadə misalımı verəcəm.

Bunu etmək üçün giriş xətlərinin formatına qərar verməlisiniz. Məndə bunlar var:

1 MƏLUMAT mesajı1
2 XƏTA mesajı2

Bunlar. Əvvəlcə identifikator, sonra INFO/ERROR, sonra boşluqsuz bəzi sözlər.
Çətin deyil, amma iş prinsipini başa düşmək üçün kifayətdir.

Beləliklə, filtr bölməsində, grok plaginində sətirlərimizi təhlil etmək üçün nümunə müəyyən etməliyik.

Bu belə görünəcək:

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

Əsasən bu, müntəzəm ifadədir. INT, LOGLEVEL, WORD kimi hazır naxışlardan istifadə olunur. Onların təsvirinə, eləcə də digər naxışlara burada baxmaq olar. burada

İndi bu filtrdən keçərək sətirimiz üç sahədən ibarət hash-ə çevriləcək: message_id, message_type, message_text.

Onlar çıxış bölməsində göstəriləcək.

if əmri ilə çıxış bölməsində mesajların yönləndirilməsi

Çıxış bölməsində, xatırladığımız kimi, mesajları iki axına bölmək niyyətində idik. Bəziləri - iNFO olan, biz konsola çıxaracağıq və səhvlərlə bir fayla çıxaracağıq.

Bu mesajları necə paylaşa bilərik? Problemin vəziyyəti artıq həll yolunu təklif edir - axı bizdə artıq seçilmiş mesaj_tipi sahəsi var, o, yalnız iki INFO və ERROR dəyərini qəbul edə bilər. Bunun üzərinə if ifadəsindən istifadə edərək seçim edəcəyik.

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

Sahələr və operatorlarla işin təsviri bu bölmədə tapıla bilər rəsmi təlimat.

İndi nəticənin özü haqqında.

Konsol çıxışı, burada hər şey aydındır - stdout {}

Amma faylın çıxışı - unutmayın ki, biz bütün bunları konteynerdən işlədirik və nəticəni yazdığımız faylın kənardan əlçatan olması üçün bu kataloqu docker-compose.yml-də açmalıyıq.

Ümumi:

Faylımızın çıxış bölməsi belə görünür:


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

Çıxış üçün docker-compose.yml-ə daha bir həcm əlavə edin:

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

Başlayırıq, çalışırıq, iki axına bölünməni görürük.

Mənbə: www.habr.com

Добавить комментарий