ELK ning amaliy qo'llanilishi. Logstash sozlanmoqda

kirish

Boshqa tizimni o'rnatishda biz juda ko'p turli xil jurnallarni qayta ishlash zarurati bilan duch keldik. Asbob sifatida ELK tanlangan. Ushbu maqolada ushbu stekni o'rnatish bo'yicha tajribamiz muhokama qilinadi.

Biz uning barcha imkoniyatlarini tavsiflashni maqsad qilib qo'ymaymiz, lekin biz amaliy muammolarni hal qilishga alohida e'tibor qaratmoqchimiz. Buning sababi shundaki, juda ko'p miqdordagi hujjatlar va tayyor tasvirlar mavjud bo'lsa-da, tuzoqlar juda ko'p, hech bo'lmaganda biz ularni topdik.

Biz stekni docker-compose orqali joylashtirdik. Bundan tashqari, bizda yaxshi yozilgan docker-compose.yml bor edi, bu bizga stekni deyarli muammosiz ko'tarish imkonini berdi. Va bizga g'alaba yaqinlashib qolgandek tuyuldi, endi biz o'z ehtiyojlarimizga mos ravishda uni biroz o'zgartiramiz va tamom.

Afsuski, bizning ilovamizdan jurnallarni qabul qilish va qayta ishlash uchun tizimni sozlash urinishi darhol muvaffaqiyatli bo'lmadi. Shuning uchun biz har bir komponentni alohida o'rganishga arziydi va keyin ularning aloqalariga qaytishga qaror qildik.

Shunday qilib, biz logstash bilan boshladik.

Atrof-muhit, joylashtirish, Logstash-ni konteynerda ishga tushirish

Joylashtirish uchun biz docker-compose dan foydalanamiz; bu yerda tasvirlangan tajribalar MacOS va Ubuntu 18.0.4 da amalga oshirildi.

Asl docker-compose.yml da ro‘yxatdan o‘tgan logstash tasviri docker.elastic.co/logstash/logstash:6.3.2

Biz undan tajribalar uchun foydalanamiz.

Logstashni ishga tushirish uchun alohida docker-compose.yml yozdik. Albatta, tasvirni buyruq satridan ishga tushirish mumkin edi, lekin biz ma'lum bir muammoni hal qildik, bu erda hamma narsa docker-compose-dan ishga tushirildi.

Konfiguratsiya fayllari haqida qisqacha

Tavsifdan ko'rinib turibdiki, logstash bir kanal uchun ham ishga tushirilishi mumkin, bu holda u *.conf faylini o'tkazishi kerak yoki bir nechta kanallar uchun, bu holda pipelines.yml faylini o'tkazishi kerak, bu esa o'z navbatida. , har bir kanal uchun .conf fayllariga havola qiladi.
Biz ikkinchi yo'lni tanladik. Bu bizga ko'proq universal va kengaytiriladigan bo'lib tuyuldi. Shuning uchun biz pipelines.yml ni yaratdik va har bir kanal uchun .conf fayllarini joylashtirgan quvur liniyasi katalogini yaratdik.

Konteyner ichida boshqa konfiguratsiya fayli mavjud - logstash.yml. Biz unga tegmaymiz, xuddi shunday foydalanamiz.

Shunday qilib, bizning katalog tuzilishimiz:

ELK ning amaliy qo'llanilishi. Logstash sozlanmoqda

Kirish ma'lumotlarini olish uchun hozircha biz bu 5046 portdagi tcp deb hisoblaymiz va chiqish uchun biz stdout dan foydalanamiz.

Bu erda birinchi ishga tushirish uchun oddiy konfiguratsiya. Chunki dastlabki vazifa ishga tushirishdir.

Shunday qilib, bizda docker-compose.yml mavjud

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

Bu erda nimani ko'ramiz?

  1. Tarmoqlar va hajmlar asl docker-compose.yml (butun stek ishga tushirilgan) dan olingan va menimcha, ular bu erdagi umumiy rasmga unchalik ta'sir qilmaydi.
  2. Biz docker.elastic.co/logstash/logstash:6.3.2 rasmidan bitta logstash xizmati(lar)ini yaratamiz va uni logstash_one_channel deb nomlaymiz.
  3. Biz konteyner ichidagi 5046 portni bir xil ichki portga yo'naltiramiz.
  4. Biz quvur konfiguratsiya faylimiz ./config/pipelines.yml faylini konteyner ichidagi /usr/share/logstash/config/pipelines.yml fayliga joylashtiramiz, u yerda logstash uni olib, faqat o‘qish uchun mo‘ljallangan qiladi.
  5. Biz ./config/pipelines katalogini, bu yerda kanal sozlamalari bo'lgan fayllarni /usr/share/logstash/config/pipelines katalogiga joylashtiramiz va uni faqat o'qish uchun qilamiz.

ELK ning amaliy qo'llanilishi. Logstash sozlanmoqda

Pipelines.yml fayli

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

Bu yerda HABR identifikatoriga ega bitta kanal va uning konfiguratsiya fayliga yo'l tasvirlangan.

Va nihoyat “./config/pipelines/habr_pipeline.conf” fayli

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

Hozircha uning tavsifiga kirmaylik, uni ishga tushirishga harakat qilaylik:

docker-compose up

Biz nimani ko'ramiz?

Konteyner ishga tushdi. Biz uning ishlashini tekshirishimiz mumkin:

echo '13123123123123123123123213123213' | nc localhost 5046

Va biz konteyner konsolida javobni ko'ramiz:

ELK ning amaliy qo'llanilishi. Logstash sozlanmoqda

Ammo shu bilan birga, biz ham ko'ramiz:

logstash_one_channel | [2019-04-29T11:28:59,790][XATO][logstash.licensechecker.licensereader] Litsenziya serveridan litsenziya maʼlumotlarini olib boʻlmadi {:message=>“Elasticsearch bilan bogʻlanib boʻlmaydi: [http://elasticsearch:9200/][Manticore ::ResolutionFailure] elasticsearch", ...

logstash_one_channel | [2019-04-29T11:28:59,894][INFO ][logstash.pipeline ] Quvur muvaffaqiyatli ishga tushirildi {:pipeline_id=>".monitoring-logstash", :thread=>"# "}

logstash_one_channel | [2019-04-29T11:28:59,988][INFO ][logstash.agent ] Ishlayotgan quvurlar {:count=>2, :running_pipelines=>[:HABR, :".monitoring-logstash"], :non_running_pipelines=>[ ]}
logstash_one_channel | [2019-04-29T11:29:00,015][XATO][logstash.inputs.metrics] X-Pack Logstash-ga o'rnatilgan, lekin Elasticsearch-da emas. Monitoring funksiyasidan foydalanish uchun X-Pack-ni Elasticsearch-ga o'rnating. Boshqa xususiyatlar mavjud bo'lishi mumkin.
logstash_one_channel | [2019-04-29T11:29:00,526][INFO ][logstash.agent ] Logstash API so‘nggi nuqtasi {:port=>9600} muvaffaqiyatli ishga tushirildi
logstash_one_channel | [2019-04-29T11:29:04,478][INFO ][logstash.outputs.elasticsearch] Elasticsearch ulanishi ishlayaptimi yoki yoʻqligini tekshirish uchun sogʻliq tekshiruvi oʻtkazilmoqda {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,487][OGOHLANTIRISH ][logstash.outputs.elasticsearch] Oʻlik ES misoliga ulanishni qayta tiklashga harakat qildim, lekin xatolik yuz berdi. {:url=>“elastika:9200/", :error_type=>LogStash::Outputs::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 ulanishi ishlayaptimi yoki yoʻqligini tekshirish uchun sogʻliq tekshiruvi oʻtkazilmoqda {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,710][OGOHLANTIRISH ][logstash.licensechecker.licensereader] Oʻlik ES misoliga ulanishni qayta tiklashga harakat qildim, lekin xatolik yuz berdi. {:url=>“elastika:9200/", :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch Unreachable: [http://elasticsearch:9200/:][Manticore:il] elasticsearch"}

Va bizning jurnalimiz doimo o'rmalab boradi.

Bu erda men yashil rangda quvur liniyasi muvaffaqiyatli ishga tushirilganligi haqidagi xabarni, qizil rangda xato xabarini va sariq rang bilan bog'lanishga urinish haqidagi xabarni ta'kidladim. elastika: 9200.
Buning sababi, rasmga kiritilgan logstash.conf sayti elasticsearch mavjudligini tekshirishni o'z ichiga oladi. Axir, logstash u Elk stekining bir qismi sifatida ishlaydi deb taxmin qiladi, lekin biz uni ajratdik.

Ishlash mumkin, lekin bu qulay emas.

Yechim bu tekshirishni XPACK_MONITORING_ENABLED muhit o‘zgaruvchisi orqali o‘chirib qo‘yishdir.

Keling, docker-compose.yml ga o'zgartirish kiritamiz va uni qayta ishga tushiramiz:

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

Endi hammasi yaxshi. Idish tajribalar uchun tayyor.

Keyingi konsolda yana yozishimiz mumkin:

echo '13123123123123123123123213123213' | nc localhost 5046

Va qarang:

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 ishlash

Shunday qilib, biz ishga tushdik. Endi siz logstash-ning o'zini sozlash uchun vaqt ajratishingiz mumkin. Hozircha pipelines.yml fayliga tegmaylik, keling, bitta kanal bilan ishlash orqali nimaga erishishimiz mumkinligini ko'rib chiqaylik.

Aytishim kerakki, kanal konfiguratsiya fayli bilan ishlashning umumiy printsipi bu erda rasmiy qo'llanmada yaxshi tasvirlangan shu yerda
Agar siz rus tilida o'qimoqchi bo'lsangiz, biz buni ishlatdik maqola(lekin so'rovlar sintaksisi eski, biz buni hisobga olishimiz kerak).

Keling, Kirish bo'limidan ketma-ket ketamiz. Biz allaqachon TCP ustida ishlashni ko'rdik. Bu erda yana nima qiziqarli bo'lishi mumkin?

Yurak urishi yordamida xabarlarni sinab ko'ring

Avtomatik test xabarlarini yaratish uchun shunday qiziqarli imkoniyat mavjud.
Buni amalga oshirish uchun siz kiritish qismida heartbean plaginini yoqishingiz kerak.

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

Uni yoqing, daqiqada bir marta qabul qilishni boshlang

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

Agar biz tez-tez qabul qilishni xohlasak, intervalli parametrni qo'shishimiz kerak.
Shunday qilib, biz har 10 soniyada xabar olamiz.

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

Fayldan ma'lumotlarni olish

Shuningdek, biz fayl rejimini ko'rib chiqishga qaror qildik. Agar u fayl bilan yaxshi ishlasa, hech bo'lmaganda mahalliy foydalanish uchun hech qanday agent kerak emas.

Ta'rifga ko'ra, ish rejimi quyruq -f ga o'xshash bo'lishi kerak, ya'ni. yangi satrlarni o'qiydi yoki variant sifatida butun faylni o'qiydi.

Shunday qilib, biz nimani olishni xohlaymiz:

  1. Biz bitta jurnal fayliga qo'shilgan qatorlarni olishni xohlaymiz.
  2. Biz bir nechta jurnal fayllariga yozilgan ma'lumotlarni olishni istaymiz, shu bilan birga qaerdan olinganini ajrata olamiz.
  3. Logstash qayta ishga tushirilganda, u bu maʼlumotlarni boshqa qabul qilmasligiga ishonch hosil qilmoqchimiz.
  4. Biz tekshirmoqchimizki, agar logstash o'chirilgan bo'lsa va ma'lumotlar fayllarga yozilishda davom etsa, biz uni ishga tushirganimizda, biz ushbu ma'lumotlarni olamiz.

Tajribani o'tkazish uchun docker-compose.yml ga yana bir qator qo'shamiz, biz fayllar joylashtirgan katalogni ochamiz.

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

Va habr_pipeline.conf-dagi kirish qismini o'zgartiring

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

Boshlaylik:

docker-compose up

Jurnal fayllarini yaratish va yozish uchun biz quyidagi buyruqdan foydalanamiz:


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

Ha, ishlaydi!

Shu bilan birga, biz avtomatik ravishda yo'l maydonini qo'shganimizni ko'ramiz. Bu shuni anglatadiki, kelajakda biz u orqali yozuvlarni filtrlay olamiz.

Yana urinib ko'ramiz:

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

Va endi boshqa faylga:

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

Ajoyib! Fayl olindi, yo'l to'g'ri ko'rsatilgan, hammasi yaxshi.

Logstashni to'xtating va qaytadan boshlang. Keling, kutamiz. Sukunat. Bular. Biz bu yozuvlarni boshqa olmaymiz.

Va endi eng jasoratli tajriba.

Logstash-ni o'rnating va bajaring:

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

Logstash-ni qayta ishga tushiring va qarang:

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

Xayr! Hammasi yig'ildi.

Ammo biz sizni quyidagilar haqida ogohlantirishimiz kerak. Agar logstash bo'lgan konteyner o'chirilsa (docker stop logstash_one_channel && docker rm logstash_one_channel), hech narsa olinmaydi. O'qilgan faylning joylashuvi konteyner ichida saqlangan. Agar siz uni noldan ishga tushirsangiz, u faqat yangi qatorlarni qabul qiladi.

Mavjud fayllarni o'qish

Aytaylik, biz logstashni birinchi marta ishga tushirmoqdamiz, lekin bizda allaqachon jurnallar mavjud va biz ularni qayta ishlashni xohlaymiz.
Agar biz logstashni yuqorida ishlatgan kiritish bo'limi bilan ishlatsak, biz hech narsa olmaymiz. Faqat yangi qatorlar logstash tomonidan qayta ishlanadi.

Mavjud fayllardan satrlarni tortib olish uchun siz kiritish bo'limiga qo'shimcha qator qo'shishingiz kerak:

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

Bundan tashqari, bir nuance bor: bu faqat logstash hali ko'rmagan yangi fayllarga ta'sir qiladi. Logstash ko'rish maydonida bo'lgan bir xil fayllar uchun u allaqachon o'z hajmini eslab qolgan va endi faqat yangi yozuvlarni oladi.

Keling, shu erda to'xtab, kirish qismini o'rganamiz. Hali ko'p variantlar mavjud, ammo bu biz uchun keyingi tajribalar uchun hozircha etarli.

Marshrutlash va ma'lumotlarni o'zgartirish

Keling, quyidagi muammoni hal qilishga harakat qilaylik, deylik, bizda bitta kanaldan xabarlar bor, ularning ba'zilari axborot, ba'zilari esa xato xabarlari. Ular teg bo'yicha farqlanadi. Ba'zilari INFO, boshqalari esa ERROR.

Biz ularni chiqishda ajratishimiz kerak. Bular. Biz bir kanalda axborot xabarlarini, boshqasida xato xabarlarini yozamiz.

Buni amalga oshirish uchun kirish qismidan filtrlash va chiqarishga o'ting.

Filtr bo'limidan foydalanib, biz kiruvchi xabarni tahlil qilamiz, undan xeshni (kalit-qiymat juftlari) olamiz, biz allaqachon ishlashimiz mumkin, ya'ni. shartlarga muvofiq qismlarga ajrating. Va chiqish qismida biz xabarlarni tanlaymiz va har birini o'z kanaliga yuboramiz.

Grok bilan xabarni tahlil qilish

Matn satrlarini tahlil qilish va ulardan maydonlar to'plamini olish uchun filtr bo'limida maxsus plagin mavjud - grok.

Bu erda batafsil tavsif berishni o'z oldimga maqsad qilib qo'ymasdan (buning uchun men havola qilaman rasmiy hujjatlar), Men oddiy misolimni keltiraman.

Buning uchun siz kirish satrlarining formati haqida qaror qabul qilishingiz kerak. Menda ular shunday:

1 INFO xabari1
2 Xato xabari2

Bular. Avval identifikator keladi, keyin INFO/ERROR, so'ngra bo'sh joysiz ba'zi so'zlar keladi.
Bu qiyin emas, lekin ishlash tamoyilini tushunish uchun etarli.

Shunday qilib, grok plaginining filtr bo'limida biz satrlarni tahlil qilish uchun naqshni aniqlashimiz kerak.

Bu shunday ko'rinadi:

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

Aslida, bu muntazam ifoda. INT, LOGLEVEL, WORD kabi tayyor naqshlardan foydalaniladi. Ularning tavsifini, shuningdek, boshqa naqshlarni bu erda topishingiz mumkin shu yerda

Endi, ushbu filtrdan o'tib, bizning satr uchta maydondan iborat xeshga aylanadi: message_id, message_type, message_text.

Ular chiqish qismida ko'rsatiladi.

If buyrug'i yordamida xabarlarni chiqish bo'limiga yo'naltirish

Chiqarish bo'limida, biz eslaganimizdek, biz xabarlarni ikkita oqimga ajratmoqchi edik. Ba'zilari - iNFO bo'lib, konsolga chiqariladi va xatolar bilan biz faylga chiqaramiz.

Ushbu xabarlarni qanday ajratamiz? Muammoning holati allaqachon yechimni taklif qilmoqda - axir, bizda faqat ikkita qiymatni qabul qiladigan maxsus xabar turi maydoni mavjud: INFO va ERROR. Aynan shu asosda biz if iborasidan foydalanib tanlov qilamiz.

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

Maydonlar va operatorlar bilan ishlash tavsifini ushbu bo'limda topish mumkin rasmiy qo'llanma.

Endi, haqiqiy xulosaning o'zi haqida.

Konsol chiqishi, bu erda hamma narsa aniq - stdout {}

Ammo faylga chiqish - shuni yodda tutingki, biz bularning barchasini konteynerdan ishga tushiramiz va natijani yozgan faylga tashqaridan kirish mumkin bo'lishi uchun biz ushbu katalogni docker-compose.yml da ochishimiz kerak.

Jami:

Bizning faylning chiqish bo'limi quyidagicha ko'rinadi:


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

Docker-compose.yml da biz chiqish uchun boshqa hajmni qo'shamiz:

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

Biz uni ishga tushiramiz, sinab ko'ramiz va ikkita oqimga bo'linishni ko'ramiz.

Manba: www.habr.com

a Izoh qo'shish