การประยุกต์ใช้ ELK ในทางปฏิบัติ การตั้งค่าล็อกสตาช

การแนะนำ

ในขณะที่ปรับใช้ระบบอื่น เราต้องเผชิญกับความจำเป็นในการประมวลผลบันทึกต่างๆ จำนวนมาก ELK ได้รับเลือกให้เป็นเครื่องดนตรี บทความนี้จะพูดถึงประสบการณ์ของเราในการตั้งค่ากองนี้

เราไม่ได้กำหนดเป้าหมายเพื่ออธิบายความสามารถทั้งหมด แต่เราต้องการเน้นที่การแก้ปัญหาในทางปฏิบัติ นี่เป็นเพราะเอกสารจำนวนมากเพียงพอและรูปภาพสำเร็จรูปมีข้อผิดพลาดมากมายอย่างน้อยเราก็พบพวกเขา

เราปรับใช้สแต็คผ่านนักเทียบท่า-เขียน ยิ่งไปกว่านั้น เรามี docker-compose.yml ที่เขียนอย่างดีซึ่งทำให้เราสามารถเพิ่มสแต็คได้โดยแทบไม่มีปัญหา และดูเหมือนว่าชัยชนะใกล้เข้ามาแล้วสำหรับเรา ตอนนี้เราจะบิดเล็กน้อยเพื่อให้เหมาะกับความต้องการของเรา แค่นั้น

น่าเสียดายที่ความพยายามปรับแต่งระบบเพื่อรับและประมวลผลบันทึกจากแอปพลิเคชันของเราไม่สำเร็จในทันที ดังนั้นเราจึงตัดสินใจว่าควรศึกษาแต่ละองค์ประกอบแยกกันแล้วกลับไปที่การเชื่อมต่อ

เรามาเริ่มกันที่ logstash

สภาพแวดล้อม การปรับใช้ การเรียกใช้ Logstash ในคอนเทนเนอร์

สำหรับการปรับใช้ เราใช้ docker-compose การทดลองที่อธิบายไว้ที่นี่ดำเนินการบน MacOS และ Ubuntu 18.0.4

อิมเมจ logstash ที่เรามีใน docker-compose.yml ดั้งเดิมคือ docker.elastic.co/logstash/logstash:6.3.2

เราจะใช้สำหรับการทดลอง

ในการเรียกใช้ logstash เราได้เขียน docker-compose.yml แยกต่างหาก แน่นอน มันเป็นไปได้ที่จะเปิดอิมเมจจากบรรทัดคำสั่ง แต่หลังจากนั้น เราได้แก้ไขงานเฉพาะซึ่งทุกอย่างตั้งแต่นักเทียบท่า-คอมโพสิทถูกเปิดใช้งานสำหรับเรา

สั้น ๆ เกี่ยวกับไฟล์คอนฟิกูเรชัน

จากคำอธิบายต่อไปนี้ สามารถเรียกใช้ logstash เป็นหนึ่งแชนเนล ซึ่งในกรณีนี้จำเป็นต้องถ่ายโอนไฟล์ *.conf หรือสำหรับหลายแชนเนล ซึ่งในกรณีนี้จำเป็นต้องถ่ายโอนไฟล์ไปป์ไลน์.yml ซึ่งในทางกลับกัน จะอ้างถึงไฟล์ .conf สำหรับแต่ละช่อง
เราใช้เส้นทางที่สอง ดูเหมือนว่าเราจะมีความหลากหลายและปรับขนาดได้มากขึ้น ดังนั้นเราจึงสร้างไปป์ไลน์ .yml และสร้างไดเร็กทอรีไปป์ไลน์ที่เราจะใส่ไฟล์ .conf สำหรับแต่ละแชนเนล

ภายในคอนเทนเนอร์มีไฟล์กำหนดค่าอื่น - logstash.yml เราไม่ได้สัมผัสมัน เราใช้มันตามที่เป็นอยู่

โครงสร้างไดเร็กทอรีของเราคือ:

การประยุกต์ใช้ ELK ในทางปฏิบัติ การตั้งค่าล็อกสตาช

ในขณะนี้ เราถือว่านี่คือ tcp บนพอร์ต 5046 เพื่อรับข้อมูลอินพุต และเราจะใช้ stdout สำหรับเอาต์พุต

นี่คือการกำหนดค่าอย่างง่ายสำหรับการรันครั้งแรก เพราะงานเริ่มต้นคือการเปิดตัว

ดังนั้นเราจึงมี 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

เราเห็นอะไรที่นี่?

  1. เครือข่ายและไดรฟ์ข้อมูลนำมาจาก docker-compose.yml ดั้งเดิม (อันที่เปิดตัวสแต็กทั้งหมด) และฉันคิดว่าสิ่งเหล่านี้ไม่ส่งผลกระทบต่อภาพรวมที่นี่มากนัก
  2. เราสร้าง logstash หนึ่งบริการ (บริการ) จากอิมเมจ docker.elastic.co/logstash/logstash:6.3.2 และตั้งชื่อว่า logstash_one_channel
  3. เรากำลังส่งต่อพอร์ต 5046 ภายในคอนเทนเนอร์ไปยังพอร์ตภายในเดียวกัน
  4. เราแมปไฟล์คอนฟิกูเรชันไปป์ ./config/pipelines.yml กับไฟล์ /usr/share/logstash/config/pipelines.yml ภายในคอนเทนเนอร์ ซึ่ง logstash จะรับไฟล์และทำให้เป็นแบบอ่านอย่างเดียว ในกรณีนี้
  5. เราแมปไดเร็กทอรี ./config/pipelines ซึ่งเรามีไฟล์คอนฟิกูเรชันไปป์ กับไดเร็กทอรี /usr/share/logstash/config/pipelines และทำให้เป็นแบบอ่านอย่างเดียว

การประยุกต์ใช้ ELK ในทางปฏิบัติ การตั้งค่าล็อกสตาช

ไฟล์ piping.yml

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

ซึ่งอธิบายช่องทางหนึ่งที่มีตัวระบุ HABR และพาธไปยังไฟล์คอนฟิกูเรชัน

และสุดท้ายไฟล์ "./config/pipelines/habr_pipeline.conf"

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

เราจะไม่อธิบายในตอนนี้ เราพยายามเรียกใช้:

docker-compose up

เราเห็นอะไร

คอนเทนเนอร์เริ่มทำงานแล้ว เราสามารถตรวจสอบการทำงานของมันได้:

echo '13123123123123123123123213123213' | nc localhost 5046

และเราเห็นการตอบสนองในคอนเทนเนอร์คอนโซล:

การประยุกต์ใช้ ELK ในทางปฏิบัติ การตั้งค่าล็อกสตาช

แต่ในขณะเดียวกัน เรายังเห็น:

logstash_one_channel | [2019-04-29T11:28:59,790][ERROR][logstash.licensechecker.licensereader] ไม่สามารถดึงข้อมูลใบอนุญาตจากเซิร์ฟเวอร์ใบอนุญาต {:message=>"Elasticsearch ไม่สามารถเข้าถึง: [http://elasticsearch:9200/][Manticore ::ResolutionFailure]elasticsearch", ...

logstash_one_channel | [2019-04-29T11:28:59,894][INFO ][logstash.pipeline ] ไปป์ไลน์เริ่มต้นเรียบร้อยแล้ว {:pipeline_id=>".monitoring-logstash", :thread=>"# »}

logstash_one_channel | [2019-04-29T11:28:59,988][INFO ][logstash.agent ] ไปป์ไลน์ที่ทำงาน {: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 ได้รับการติดตั้งบน Logstash แต่ไม่ได้อยู่ใน Elasticsearch โปรดติดตั้ง X-Pack บน Elasticsearch เพื่อใช้คุณลักษณะการตรวจสอบ อาจมีคุณสมบัติอื่นๆ
logstash_one_channel | [2019-04-29T11:29:00,526][INFO ][logstash.agent ] เริ่มต้นจุดสิ้นสุด Logstash API สำเร็จแล้ว {:port=>9600}
logstash_one_channel | [2019-04-29T11:29:04,478][INFO ][logstash.outputs.elasticsearch] กำลังตรวจสอบความสมบูรณ์เพื่อดูว่าการเชื่อมต่อของ Elasticsearch ทำงานอยู่หรือไม่ {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,487][WARN ][logstash.outputs.elasticsearch] พยายามคืนชีพการเชื่อมต่อกับอินสแตนซ์ ES ที่ไม่ทำงาน แต่พบข้อผิดพลาด {:url=>"ElasticSearch:9200/", :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch ไม่สามารถเข้าถึงได้: [http://elasticsearch:9200/][Manticore::ResolutionFailure] การค้นหาแบบยืดหยุ่น"}
logstash_one_channel | [2019-04-29T11:29:04,704][INFO ][logstash.licensechecker.licensereader] กำลังตรวจสอบความสมบูรณ์เพื่อดูว่าการเชื่อมต่อของ Elasticsearch ทำงานอยู่หรือไม่ {:healthcheck_url=>http://elasticsearch:9200/, :path=> "/"}
logstash_one_channel | [2019-04-29T11:29:04,710][WARN ][logstash.licensechecker.licensereader] พยายามคืนชีพการเชื่อมต่อกับอินสแตนซ์ ES ที่ไม่ทำงาน แต่ได้รับข้อผิดพลาด {:url=>"ElasticSearch:9200/", :error_type=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :error=>"Elasticsearch ไม่สามารถเข้าถึงได้: [http://elasticsearch:9200/][Manticore::ResolutionFailure] การค้นหาแบบยืดหยุ่น"}

และบันทึกของเราก็รวบรวมข้อมูลตลอดเวลา

ที่นี่ฉันเน้นข้อความสีเขียวว่าไปป์ไลน์เริ่มต้นสำเร็จ สีแดงคือข้อความแสดงข้อผิดพลาด และสีเหลืองคือข้อความเกี่ยวกับการพยายามติดต่อ ElasticSearch: 9200
สิ่งนี้เกิดขึ้นเนื่องจากใน logstash.conf ที่รวมอยู่ในรูปภาพมีการตรวจสอบความพร้อมใช้งานของการค้นหาแบบยืดหยุ่น ท้ายที่สุดแล้ว logstash ถือว่ามันทำงานเป็นส่วนหนึ่งของ Elk stack และเราแยกมันออกจากกัน

ทำงานได้แต่ไม่สะดวก

วิธีแก้ไขคือปิดใช้งานการตรวจสอบนี้ผ่านตัวแปรสภาพแวดล้อม XPACK_MONITORING_ENABLED

มาทำการเปลี่ยนแปลง 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
    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

ตอนนี้ทุกอย่างเรียบร้อยดี ภาชนะพร้อมสำหรับการทดลอง

เราสามารถพิมพ์อีกครั้งในคอนโซลที่อยู่ติดกัน:

echo '13123123123123123123123213123213' | nc localhost 5046

และดู:

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

ทำงานภายในช่องทางเดียว

ดังนั้นเราจึงเริ่มต้น ตอนนี้คุณสามารถใช้เวลาในการกำหนดค่า logstash ได้โดยตรง ตอนนี้อย่าเพิ่งแตะต้องไฟล์pipelines.yml มาดูกันว่าเราจะได้อะไรจากการทำงานกับหนึ่งช่องสัญญาณ

ฉันต้องบอกว่าหลักการทั่วไปของการทำงานกับไฟล์การกำหนดค่าช่องนั้นอธิบายไว้อย่างดีในคู่มืออย่างเป็นทางการที่นี่ ที่นี่
หากคุณต้องการอ่านเป็นภาษารัสเซีย เราใช้สิ่งนี้ บทความ(แต่ไวยากรณ์ของแบบสอบถามนั้นเก่า คุณต้องคำนึงถึงสิ่งนี้ด้วย)

ไปตามลำดับจากส่วนอินพุต เราได้เห็นการทำงานบน tcp แล้ว มีอะไรน่าสนใจอีกบ้างที่นี่?

ทดสอบข้อความโดยใช้การเต้นของหัวใจ

มีความเป็นไปได้ที่น่าสนใจในการสร้างข้อความทดสอบอัตโนมัติ
ในการทำเช่นนี้ คุณต้องรวมปลั๊กอิน heartbean ไว้ในส่วนอินพุต

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

เราเปิดใช้งานเราเริ่มได้รับนาทีละครั้ง

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

เราต้องการรับบ่อยขึ้นเราต้องเพิ่มพารามิเตอร์ช่วงเวลา
นี่คือวิธีที่เราจะได้รับข้อความทุกๆ 10 วินาที

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

รับข้อมูลจากไฟล์

เราตัดสินใจดูโหมดไฟล์ด้วย หากทำงานได้ดีกับไฟล์ ก็เป็นไปได้ว่าไม่จำเป็นต้องใช้เอเจนต์ อย่างน้อยก็สำหรับการใช้งานในเครื่อง

ตามคำอธิบาย โหมดการทำงานควรคล้ายกับ tail -f นั่นคือ อ่านบรรทัดใหม่หรืออ่านไฟล์ทั้งหมด

ดังนั้นสิ่งที่เราต้องการได้รับ:

  1. เราต้องการรับบรรทัดที่ต่อท้ายไฟล์บันทึกหนึ่งไฟล์
  2. เราต้องการรับข้อมูลที่เขียนลงในล็อกไฟล์หลายๆ ไฟล์ ในขณะที่สามารถแยกข้อมูลที่ได้รับจากที่ใดได้
  3. เราต้องการให้แน่ใจว่าเมื่อรีสตาร์ท logstash จะไม่ได้รับข้อมูลนี้อีก
  4. เราต้องการตรวจสอบว่าหากปิดใช้งาน logstash และข้อมูลยังคงถูกเขียนลงในไฟล์ เมื่อเราเรียกใช้ เราจะได้รับข้อมูลนี้

ในการดำเนินการทดสอบ ให้เพิ่มอีกหนึ่งบรรทัดใน 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
    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

และเปลี่ยนส่วนอินพุตใน habr_pipeline.conf

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

เราเริ่ม:

docker-compose up

ในการสร้างและเขียนไฟล์บันทึก เราจะใช้คำสั่ง:


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

ใช่มันใช้งานได้!

ในเวลาเดียวกัน เราเห็นว่าเราได้เพิ่มช่องเส้นทางโดยอัตโนมัติ ดังนั้นในอนาคต เราจะสามารถกรองบันทึกตามนั้น

ลองอีกครั้ง:

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

และตอนนี้ไปที่ไฟล์อื่น:

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

ยอดเยี่ยม! ไฟล์ถูกหยิบขึ้นมา, เส้นทางถูกระบุอย่างถูกต้อง, ทุกอย่างเรียบร้อยดี.

หยุด logstash และเริ่มต้นใหม่ มารอกัน ความเงียบ. เหล่านั้น. เราไม่ได้รับบันทึกเหล่านี้อีก

และตอนนี้เป็นการทดลองที่กล้าหาญที่สุด

เราใส่ logstash และดำเนินการ:

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

เรียกใช้ logstash อีกครั้งและดู:

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

ไชโย! ทุกอย่างหยิบขึ้นมา

แต่จำเป็นต้องเตือนเกี่ยวกับสิ่งต่อไปนี้ หากนำคอนเทนเนอร์ logstash ออก (นักเทียบท่าหยุด logstash_one_channel && นักเทียบท่า rm logstash_one_channel) จะไม่มีการดึงข้อมูลใดๆ ตำแหน่งของไฟล์ที่อ่านถูกเก็บไว้ภายในคอนเทนเนอร์ หากคุณเริ่มต้นจากศูนย์ ระบบจะยอมรับเฉพาะการขึ้นบรรทัดใหม่เท่านั้น

อ่านไฟล์ที่มีอยู่

สมมติว่าเรากำลังเรียกใช้ logstash เป็นครั้งแรก แต่เรามีบันทึกอยู่แล้วและต้องการประมวลผล
ถ้าเราเรียกใช้ logstash ด้วยส่วนอินพุตที่เราใช้ด้านบน เราจะไม่ได้อะไรเลย เฉพาะการขึ้นบรรทัดใหม่เท่านั้นที่จะถูกประมวลผลโดย logstash

ในการดึงบรรทัดจากไฟล์ที่มีอยู่ ให้เพิ่มบรรทัดเพิ่มเติมในส่วนอินพุต:

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

ยิ่งไปกว่านั้น มีความแตกต่างกันเล็กน้อย ซึ่งมีผลเฉพาะกับไฟล์ใหม่ที่ logstash ยังไม่เห็นเท่านั้น สำหรับไฟล์เดิมที่อยู่ในมุมมองของ logstash ไฟล์ได้จำขนาดไว้แล้วและตอนนี้จะรับเฉพาะบันทึกใหม่เท่านั้น

เรามาหยุดกันโดยศึกษาส่วนอินพุต มีตัวเลือกเพิ่มเติมมากมาย แต่สำหรับตอนนี้ เรามีเพียงพอสำหรับการทดลองเพิ่มเติม

การกำหนดเส้นทางและการแปลงข้อมูล

ลองแก้ปัญหาต่อไปนี้ สมมติว่าเรามีข้อความจากช่องทางหนึ่ง บางข้อความเป็นข้อมูล และบางข้อความเป็นข้อความแสดงข้อผิดพลาด พวกเขาแตกต่างกันในแท็ก บางตัวเป็น INFO บางตัวเป็น ERROR

เราต้องแยกกันที่ทางออก เหล่านั้น. เราเขียนข้อความแสดงข้อมูลในช่องหนึ่ง และข้อความแสดงข้อผิดพลาดในอีกช่องหนึ่ง

ในการดำเนินการนี้ ให้เปลี่ยนจากส่วนอินพุตเป็นตัวกรองและเอาต์พุต

เมื่อใช้ส่วนตัวกรอง เราจะแยกวิเคราะห์ข้อความขาเข้า รับแฮช (คู่คีย์-ค่า) จากมัน ซึ่งเราสามารถทำงานได้แล้ว เช่น แยกวิเคราะห์ตามเงื่อนไข และในส่วนเอาต์พุต เราจะเลือกข้อความและส่งแต่ละรายการไปยังช่องของตัวเอง

แยกวิเคราะห์ข้อความด้วย grok

ในการแยกวิเคราะห์สตริงข้อความและรับชุดฟิลด์จากสตริงเหล่านั้น มีปลั๊กอินพิเศษอยู่ในส่วนตัวกรอง - grok

โดยไม่ตั้งเป้าหมายที่จะให้คำอธิบายโดยละเอียดที่นี่ (สำหรับสิ่งนี้ฉันหมายถึง เอกสารราชการ) ผมจะยกตัวอย่างง่ายๆ

ในการทำเช่นนี้คุณต้องตัดสินใจเลือกรูปแบบของบรรทัดอินพุต ฉันมีพวกเขาเช่นนี้:

1 ข้อความ INFO1
2 ข้อความผิดพลาด2

เหล่านั้น. ตัวระบุก่อน ตามด้วย INFO/ERROR จากนั้นบางคำที่ไม่มีช่องว่าง
ไม่ยากแต่พอเข้าใจหลักการทำงาน

ดังนั้น ในส่วนตัวกรอง ในปลั๊กอิน grok เราจำเป็นต้องกำหนดรูปแบบสำหรับแยกวิเคราะห์สตริงของเรา

มันจะมีลักษณะดังนี้:

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

โดยพื้นฐานแล้ว มันเป็นนิพจน์ทั่วไป ใช้รูปแบบสำเร็จรูป เช่น INT, LOGLEVEL, WORD สามารถดูคำอธิบายและรูปแบบอื่นๆ ได้ที่นี่ ที่นี่

เมื่อผ่านตัวกรองนี้ สตริงของเราจะกลายเป็นแฮชของสามฟิลด์: message_id, message_type, message_text

พวกเขาจะแสดงในส่วนผลลัพธ์

กำหนดเส้นทางข้อความในส่วนเอาต์พุตด้วยคำสั่ง if

ในส่วนเอาต์พุต อย่างที่เราจำได้ เราจะแบ่งข้อความออกเป็นสองสตรีม บางอย่าง - ซึ่งเป็น iNFO เราจะส่งออกไปยังคอนโซล และเมื่อมีข้อผิดพลาด เราจะส่งออกไปยังไฟล์

เราจะแบ่งปันข้อความเหล่านี้ได้อย่างไร? เงื่อนไขของปัญหาแนะนำวิธีแก้ไขแล้ว - เรามีฟิลด์ message_type เฉพาะอยู่แล้วซึ่งสามารถรับเพียงสองค่า INFO และ ERROR อยู่ที่ว่าเราจะเลือกใช้คำสั่ง if

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

คำอธิบายของงานกับฟิลด์และตัวดำเนินการสามารถพบได้ในส่วนนี้ คู่มืออย่างเป็นทางการ.

ตอนนี้เกี่ยวกับข้อสรุปของตัวเอง

เอาต์พุตคอนโซล ทุกอย่างชัดเจนที่นี่ - stdout {}

แต่ผลลัพธ์ไปยังไฟล์ - จำไว้ว่าเรากำลังเรียกใช้ทั้งหมดนี้จากคอนเทนเนอร์ และเพื่อให้ไฟล์ที่เราเขียนผลลัพธ์สามารถเข้าถึงได้จากภายนอก เราจำเป็นต้องเปิดไดเร็กทอรีนี้ใน docker-compose.yml

รวม:

ส่วนผลลัพธ์ของไฟล์ของเรามีลักษณะดังนี้:


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

เพิ่มโวลุ่มอีกหนึ่งรายการใน 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
    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

เราเริ่มต้น เราพยายาม เราเห็นการแบ่งออกเป็นสองกระแส

ที่มา: will.com

เพิ่มความคิดเห็น