รวบรวมบันทึกจากโลกิ

รวบรวมบันทึกจากโลกิ

พวกเราที่ Badoo เฝ้าติดตามเทคโนโลยีใหม่ๆ อย่างต่อเนื่องและประเมินว่าจะใช้มันในระบบของเราหรือไม่ เราต้องการแบ่งปันหนึ่งในการศึกษาเหล่านี้กับชุมชน มีไว้สำหรับ Loki ซึ่งเป็นระบบการรวมบันทึก

Loki เป็นโซลูชันสำหรับจัดเก็บและดูบันทึก และสแต็กนี้ยังมอบระบบที่ยืดหยุ่นสำหรับการวิเคราะห์และส่งข้อมูลไปยัง Prometheus ในเดือนพฤษภาคมมีการอัปเดตอื่นซึ่งได้รับการส่งเสริมอย่างแข็งขันจากผู้สร้าง เราสนใจว่า Loki สามารถทำอะไรได้บ้าง มีคุณสมบัติอะไรบ้าง และมันสามารถทำหน้าที่เป็นทางเลือกแทน ELK สแต็คที่เราใช้อยู่ได้มากน้อยเพียงใด

โลกิคืออะไร

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

หน้าแรก, GitHub

ก่อนที่ฉันจะพูดถึงสิ่งที่คุณสามารถทำได้กับ Loki ฉันต้องการชี้แจงความหมายของ "แนวคิดในการจัดทำดัชนีข้อมูลเมตาเท่านั้น" ลองเปรียบเทียบวิธี Loki และวิธีการสร้างดัชนีในโซลูชันดั้งเดิม เช่น Elasticsearch โดยใช้ตัวอย่างบรรทัดจากบันทึก nginx:

172.19.0.4 - - [01/Jun/2020:12:05:03 +0000] "GET /purchase?user_id=75146478&item_id=34234 HTTP/1.1" 500 8102 "-" "Stub_Bot/3.0" "0.001"

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

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

การแลกเปลี่ยนระหว่างดัชนีที่รวดเร็วขนาดใหญ่และดัชนีเดรัจฉานขนานขนาดเล็กนี้ทำให้ Loki สามารถควบคุมต้นทุนของระบบได้ สามารถกำหนดค่าและขยายได้อย่างยืดหยุ่นตามความต้องการของคุณ

Loki stack ประกอบด้วยสามส่วน: Promtail, Loki, Grafana Promtail รวบรวมบันทึก ประมวลผล และส่งให้โลกิ โลกิเก็บพวกมันไว้ และ Grafana สามารถขอข้อมูลจาก Loki และแสดงมันได้ โดยทั่วไปแล้ว Loki สามารถใช้ได้ไม่เฉพาะสำหรับการจัดเก็บบันทึกและการค้นหาเท่านั้น สแต็คทั้งหมดมอบโอกาสที่ดีในการประมวลผลและวิเคราะห์ข้อมูลขาเข้าด้วยวิธีของ Prometheus
สามารถดูรายละเอียดขั้นตอนการติดตั้งได้ ที่นี่.

บันทึกการค้นหา

คุณสามารถค้นหาบันทึกในอินเทอร์เฟซพิเศษ Grafana — Explorer ข้อความค้นหาใช้ภาษา LogQL ซึ่งคล้ายกับ PromQL ที่ Prometheus ใช้มาก โดยหลักการแล้ว มันสามารถคิดได้ว่าเป็น grep แบบกระจาย

อินเทอร์เฟซการค้นหามีลักษณะดังนี้:

รวบรวมบันทึกจากโลกิ

แบบสอบถามประกอบด้วยสองส่วน: ตัวเลือกและตัวกรอง Selector คือการค้นหาโดยข้อมูลเมตาที่ทำดัชนี (ป้ายกำกับ) ที่กำหนดให้กับบันทึก และตัวกรองคือสตริงการค้นหาหรือ regexp ที่กรองระเบียนที่กำหนดโดยตัวเลือก ในตัวอย่างที่กำหนด: ในวงเล็บปีกกา - ตัวเลือก ทุกอย่างตามหลัง - ตัวกรอง

{image_name="nginx.promtail.test"} |= "index"

เนื่องจากวิธีการทำงานของ Loki คุณไม่สามารถส่งคำขอได้หากไม่มีตัวเลือก แต่คุณสามารถสร้างป้ายกำกับทั่วไปได้ตามอำเภอใจ

ตัวเลือกคือคีย์-ค่าของค่าในวงเล็บปีกกา คุณสามารถรวมตัวเลือกและระบุเงื่อนไขการค้นหาต่างๆ โดยใช้ตัวดำเนินการ =, != หรือนิพจน์ทั่วไป:

{instance=~"kafka-[23]",name!="kafka-dev"} 
// Найдёт логи с лейблом instance, имеющие значение kafka-2, kafka-3, и исключит dev 

ตัวกรองคือข้อความหรือ regexp ที่จะกรองข้อมูลทั้งหมดที่ได้รับจากตัวเลือก

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

รวบรวมบันทึกจากโลกิ

สามารถดูคำอธิบายคุณลักษณะทั้งหมดได้ในเอกสารประกอบ LogQL.

การแยกวิเคราะห์บันทึก

มีหลายวิธีในการรวบรวมบันทึก:

  • ด้วยความช่วยเหลือของ Promtail ซึ่งเป็นส่วนประกอบมาตรฐานของสแต็กสำหรับรวบรวมบันทึก
  • โดยตรงจากคอนเทนเนอร์นักเทียบท่าโดยใช้ ไดร์เวอร์การบันทึก Loki Docker
  • ใช้ Fluentd หรือ Fluent Bit ซึ่งสามารถส่งข้อมูลไปยัง Loki ซึ่งแตกต่างจาก Promtail พวกเขามีโปรแกรมแยกวิเคราะห์สำเร็จรูปสำหรับบันทึกเกือบทุกชนิดและสามารถจัดการบันทึกหลายบรรทัดได้เช่นกัน

โดยปกติแล้ว Promtail จะใช้ในการแยกวิเคราะห์ มันทำสามสิ่ง:

  • ค้นหาแหล่งข้อมูล
  • แนบป้ายกำกับกับพวกเขา
  • ส่งข้อมูลให้โลกิ

ปัจจุบัน Promtail สามารถอ่านบันทึกจากไฟล์ในเครื่องและจากวารสาร systemd จะต้องติดตั้งในทุกเครื่องที่รวบรวมบันทึก

มีการผสานรวมกับ Kubernetes: Promtail จะค้นหาสถานะของคลัสเตอร์โดยอัตโนมัติผ่าน Kubernetes REST API และรวบรวมบันทึกจากโหนด บริการ หรือพ็อด โดยติดป้ายชื่อตามข้อมูลเมตาจาก Kubernetes ทันที (ชื่อพ็อด ชื่อไฟล์ ฯลฯ)

คุณยังสามารถแขวนป้ายกำกับตามข้อมูลจากบันทึกโดยใช้ไปป์ไลน์ Promtail ไปป์ไลน์สามารถประกอบด้วยขั้นตอนสี่ประเภท รายละเอียดเพิ่มเติม - in เอกสารราชการฉันจะสังเกตความแตกต่างบางอย่างทันที

  1. ขั้นตอนการแยกวิเคราะห์. นี่คือขั้นตอนของ RegEx และ JSON ในขั้นตอนนี้ เราดึงข้อมูลจากบันทึกลงในแผนที่ที่แยกออกมา คุณสามารถดึงข้อมูลจาก JSON ได้โดยเพียงแค่คัดลอกฟิลด์ที่เราต้องการลงในแผนที่ที่แยกออกมา หรือผ่านนิพจน์ทั่วไป (RegEx) โดยที่กลุ่มที่มีชื่อจะถูก "แมป" ลงในแผนที่ที่แตกออกมา แม็พที่แตกออกมาคือที่เก็บคีย์-ค่า โดยที่คีย์คือชื่อของฟิลด์ และค่าคือค่าจากบันทึก
  2. เปลี่ยนขั้นตอน. ขั้นตอนนี้มีสองตัวเลือก: การแปลงที่เราตั้งกฎการแปลง และแหล่งที่มา - แหล่งข้อมูลสำหรับการแปลงจากแผนที่ที่แยกออกมา หากไม่มีฟิลด์ดังกล่าวในแผนที่ที่แยกออกมา ฟิลด์นั้นจะถูกสร้างขึ้น ดังนั้นจึงเป็นไปได้ที่จะสร้างป้ายกำกับที่ไม่ได้ขึ้นอยู่กับแผนที่ที่แยกออกมา ในขั้นตอนนี้ เราสามารถจัดการข้อมูลในแผนที่ที่ดึงออกมาโดยใช้เครื่องมือที่มีประสิทธิภาพพอสมควร แม่แบบ golang. นอกจากนี้ เราต้องจำไว้ว่าแผนที่ที่แยกออกมาจะถูกโหลดอย่างสมบูรณ์ในระหว่างการแยกวิเคราะห์ ซึ่งทำให้สามารถตรวจสอบค่าในนั้น เช่น “{{if .tag}tag value available{end}}” เทมเพลตรองรับเงื่อนไข การวนซ้ำ และฟังก์ชันสตริงบางอย่าง เช่น แทนที่และตัดแต่ง
  3. ขั้นตอนการดำเนินการ. ในขั้นตอนนี้ คุณสามารถทำบางสิ่งกับสิ่งที่แยกออกมา:
    • สร้างป้ายกำกับจากข้อมูลที่ดึงออกมา ซึ่งโลกิจะจัดทำดัชนี
    • เปลี่ยนหรือตั้งเวลากิจกรรมจากบันทึก
    • เปลี่ยนข้อมูล (ข้อความบันทึก) ที่จะไปยังโลกิ
    • สร้างเมตริก
  4. ขั้นตอนการกรอง. ขั้นตอนการจับคู่ ซึ่งเราสามารถส่งบันทึกที่เราไม่จำเป็นต้อง /dev/null หรือส่งไปประมวลผลเพิ่มเติม

โดยใช้ตัวอย่างการประมวลผลบันทึก nginx ทั่วไป ฉันจะแสดงวิธีแยกวิเคราะห์บันทึกโดยใช้ Promtail

สำหรับการทดสอบ ลองใช้อิมเมจ nginx jwilder/nginx-proxy:alpine ที่แก้ไขแล้ว และ daemon ขนาดเล็กที่สามารถสืบค้นตัวเองผ่าน HTTP เป็น nginx-proxy daemon มีจุดสิ้นสุดหลายจุด ซึ่งสามารถให้การตอบสนองในขนาดต่างๆ กัน โดยมีสถานะ HTTP ต่างกัน และมีความล่าช้าต่างกัน

เราจะรวบรวมบันทึกจากคอนเทนเนอร์นักเทียบท่า ซึ่งสามารถพบได้ตามเส้นทาง /var/lib/docker/containers/ / -json.log

ใน docker-compose.yml เราตั้งค่า Promtail และระบุเส้นทางไปยังการกำหนดค่า:

promtail:
  image: grafana/promtail:1.4.1
 // ...
 volumes:
   - /var/lib/docker/containers:/var/lib/docker/containers:ro
   - promtail-data:/var/lib/promtail/positions
   - ${PWD}/promtail/docker.yml:/etc/promtail/promtail.yml
 command:
   - '-config.file=/etc/promtail/promtail.yml'
 // ...

เพิ่มเส้นทางไปยังบันทึกไปยัง promtail.yml (มีตัวเลือก "นักเทียบท่า" ในการกำหนดค่าที่ทำเหมือนกันในบรรทัดเดียว แต่จะไม่ชัดเจนนัก):

scrape_configs:
 - job_name: containers

   static_configs:
       labels:
         job: containerlogs
         __path__: /var/lib/docker/containers/*/*log  # for linux only

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

proxy:
 image: nginx.test.v3
//…
 logging:
   driver: "json-file"
   options:
     tag: "{{.ImageName}}|{{.Name}}"

แก้ไข promtail.yml และตั้งค่าไปป์ไลน์ บันทึกมีดังนี้:

{"log":"u001b[0;33;1mnginx.1    | u001b[0mnginx.test 172.28.0.3 - - [13/Jun/2020:23:25:50 +0000] "GET /api/index HTTP/1.1" 200 0 "-" "Stub_Bot/0.1" "0.096"n","stream":"stdout","attrs":{"tag":"nginx.promtail.test|proxy.prober"},"time":"2020-06-13T23:25:50.66740443Z"}
{"log":"u001b[0;33;1mnginx.1    | u001b[0mnginx.test 172.28.0.3 - - [13/Jun/2020:23:25:50 +0000] "GET /200 HTTP/1.1" 200 0 "-" "Stub_Bot/0.1" "0.000"n","stream":"stdout","attrs":{"tag":"nginx.promtail.test|proxy.prober"},"time":"2020-06-13T23:25:50.702925272Z"}

ขั้นตอนท่อ:

 - json:
     expressions:
       stream: stream
       attrs: attrs
       tag: attrs.tag

เราแยกฟิลด์ stream, attrs, attrs.tag (ถ้ามี) จาก JSON ที่เข้ามา และใส่ลงในแผนที่ที่แยกออกมา

 - regex:
     expression: ^(?P<image_name>([^|]+))|(?P<container_name>([^|]+))$
     source: "tag"

หากเป็นไปได้ที่จะใส่ช่องแท็กในแผนที่ที่แยกออกมา จากนั้นใช้ regexp เพื่อแยกชื่อของรูปภาพและคอนเทนเนอร์

 - labels:
     image_name:
     container_name:

เรากำหนดป้ายกำกับ หากพบคีย์ image_name และ container_name ในข้อมูลที่แยกออกมา ค่าของคีย์จะถูกกำหนดให้กับเลเบลที่เหมาะสม

 - match:
     selector: '{job="docker",container_name="",image_name=""}'
     action: drop

เราละทิ้งบันทึกทั้งหมดที่ไม่มีป้ายกำกับ image_name และชุด container_name

  - match:
     selector: '{image_name="nginx.promtail.test"}'
     stages:
       - json:
           expressions:
             row: log

สำหรับบันทึกทั้งหมดที่มี image_name เท่ากับ nginx.promtail.test เราจะแยกฟิลด์บันทึกออกจากบันทึกต้นทางและวางไว้ในแผนที่ที่แยกออกมาด้วยปุ่มแถว

  - regex:
         # suppress forego colors
         expression: .+nginx.+|.+[0m(?P<virtual_host>[a-z_.-]+) +(?P<nginxlog>.+)
         source: logrow

เราล้างสตริงอินพุตด้วยนิพจน์ทั่วไป และดึงโฮสต์เสมือน nginx และบรรทัดบันทึก nginx ออกมา

     - regex:
         source: nginxlog
         expression: ^(?P<ip>[w.]+) - (?P<user>[^ ]*) [(?P<timestamp>[^ ]+).*] "(?P<method>[^ ]*) (?P<request_url>[^ ]*) (?P<request_http_protocol>[^ ]*)" (?P<status>[d]+) (?P<bytes_out>[d]+) "(?P<http_referer>[^"]*)" "(?P<user_agent>[^"]*)"( "(?P<response_time>[d.]+)")?

แยกบันทึก nginx ด้วยนิพจน์ทั่วไป

    - regex:
           source: request_url
           expression: ^.+.(?P<static_type>jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$
     - regex:
           source: request_url
           expression: ^/photo/(?P<photo>[^/?.]+).*$
       - regex:
           source: request_url
           expression: ^/api/(?P<api_request>[^/?.]+).*$

แยกคำ request_url ด้วยความช่วยเหลือของ regexp เรากำหนดวัตถุประสงค์ของคำขอ: เป็น statics, to photos, to API และตั้งค่าคีย์ที่เกี่ยวข้องในแผนที่ที่แยกออกมา

       - template:
           source: request_type
           template: "{{if .photo}}photo{{else if .static_type}}static{{else if .api_request}}api{{else}}other{{end}}"

การใช้ตัวดำเนินการตามเงื่อนไขในเทมเพลต เราตรวจสอบฟิลด์ที่ติดตั้งในแผนที่ที่แยกออกมา และตั้งค่าที่จำเป็นสำหรับฟิลด์ request_type: photo, static, API มอบหมายอื่นหากล้มเหลว ตอนนี้ request_type มีประเภทคำขอ

       - labels:
           api_request:
           virtual_host:
           request_type:
           status:

เราตั้งค่าป้ายกำกับ api_request, virtual_host, request_type และสถานะ (สถานะ HTTP) ตามสิ่งที่เราจัดการเพื่อใส่ในแผนที่ที่แยกออกมา

       - output:
           source: nginx_log_row

เปลี่ยนเอาต์พุต ตอนนี้บันทึก nginx ที่ล้างแล้วจากแผนที่ที่แยกออกมาจะตกเป็นของ Loki

รวบรวมบันทึกจากโลกิ

หลังจากเรียกใช้การกำหนดค่าข้างต้น คุณจะเห็นว่าแต่ละรายการมีป้ายกำกับตามข้อมูลจากบันทึก

โปรดทราบว่าการแยกฉลากที่มีค่าจำนวนมาก (จำนวนสมาชิก) อาจทำให้ Loki ช้าลงอย่างมาก นั่นคือ คุณไม่ควรใส่ในดัชนี เช่น user_id อ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ในบทความป้ายกำกับใน Loki สามารถทำให้การค้นหาบันทึกเร็วขึ้นและง่ายขึ้นได้อย่างไร". แต่นี่ไม่ได้หมายความว่าคุณไม่สามารถค้นหาโดยใช้ user_id โดยไม่มีดัชนี จำเป็นต้องใช้ตัวกรองเมื่อค้นหา (“คว้า” ตามข้อมูล) และดัชนีที่นี่ทำหน้าที่เป็นตัวระบุสตรีม

การแสดงภาพบันทึก

รวบรวมบันทึกจากโลกิ

Loki สามารถทำหน้าที่เป็นแหล่งข้อมูลสำหรับแผนภูมิ Grafana โดยใช้ LogQL รองรับคุณสมบัติต่อไปนี้:

  • อัตรา - จำนวนบันทึกต่อวินาที
  • นับตามเวลา - จำนวนบันทึกในช่วงที่กำหนด

นอกจากนี้ยังมีฟังก์ชันการรวม Sum, Avg และอื่นๆ คุณสามารถสร้างกราฟที่ค่อนข้างซับซ้อนได้ เช่น กราฟจำนวนข้อผิดพลาด HTTP:

รวบรวมบันทึกจากโลกิ

แหล่งข้อมูลเริ่มต้นของ Loki ทำงานได้น้อยกว่าแหล่งข้อมูล Prometheus เล็กน้อย (เช่น คุณไม่สามารถเปลี่ยนคำอธิบายแผนภูมิได้) แต่ Loki สามารถเชื่อมต่อเป็นแหล่งข้อมูลประเภท Prometheus ได้ ฉันไม่แน่ใจว่านี่เป็นพฤติกรรมที่บันทึกไว้หรือไม่ แต่ตัดสินโดยคำตอบจากนักพัฒนา "จะกำหนดค่า Loki เป็นแหล่งข้อมูล Prometheus ได้อย่างไร · ฉบับที่ #1222 · กราฟาน่า/โลกิ" ตัวอย่างเช่น มันถูกกฎหมายอย่างสมบูรณ์และ Loki เข้ากันได้กับ PromQL อย่างสมบูรณ์

เพิ่ม Loki เป็นแหล่งข้อมูลด้วยประเภท Prometheus และต่อท้าย URL /loki:

รวบรวมบันทึกจากโลกิ

และคุณสามารถสร้างกราฟได้ราวกับว่าเรากำลังทำงานกับเมตริกจาก Prometheus:

รวบรวมบันทึกจากโลกิ

ฉันคิดว่าความแตกต่างในการทำงานเป็นเพียงชั่วคราวและนักพัฒนาจะแก้ไขในอนาคต

รวบรวมบันทึกจากโลกิ

เมตริก

Loki ให้ความสามารถในการแยกเมตริกตัวเลขจากบันทึกและส่งไปยัง Prometheus ตัวอย่างเช่น บันทึก nginx มีจำนวนไบต์ต่อการตอบกลับ และด้วยการปรับเปลี่ยนรูปแบบบันทึกมาตรฐาน เวลาเป็นวินาทีที่ใช้ในการตอบกลับ ข้อมูลนี้สามารถแยกและส่งไปยัง Prometheus

เพิ่มส่วนอื่นใน promtail.yml:

- match:
   selector: '{request_type="api"}'
   stages:
     - metrics:
         http_nginx_response_time:
           type: Histogram
           description: "response time ms"
           source: response_time
           config:
             buckets: [0.010,0.050,0.100,0.200,0.500,1.0]
- match:
   selector: '{request_type=~"static|photo"}'
   stages:
     - metrics:
         http_nginx_response_bytes_sum:
           type: Counter
           description: "response bytes sum"
           source: bytes_out
           config:
             action: add
         http_nginx_response_bytes_count:
           type: Counter
           description: "response bytes count"
           source: bytes_out
           config:
             action: inc

ตัวเลือกนี้ช่วยให้คุณกำหนดและอัปเดตเมตริกตามข้อมูลจากแผนที่ที่แยกออกมา เมตริกเหล่านี้จะไม่ส่งไปยัง Loki แต่จะปรากฏในปลายทาง Promtail /metrics ต้องกำหนดค่า Prometheus เพื่อรับข้อมูลจากขั้นตอนนี้ ในตัวอย่างข้างต้น สำหรับ request_type="api" เรารวบรวมเมตริกฮิสโตแกรม เมตริกประเภทนี้ทำให้สะดวกในการรับเปอร์เซ็นไทล์ สำหรับภาพนิ่งและภาพถ่าย เรารวบรวมผลรวมของไบต์และจำนวนแถวที่เราได้รับไบต์เพื่อคำนวณค่าเฉลี่ย

อ่านเพิ่มเติมเกี่ยวกับเมตริก ที่นี่.

เปิดพอร์ตบน Promtail:

promtail:
     image: grafana/promtail:1.4.1
     container_name: monitoring.promtail
     expose:
       - 9080
     ports:
       - "9080:9080"

เราตรวจสอบให้แน่ใจว่าเมตริกที่มีคำนำหน้า promtail_custom ปรากฏขึ้น:

รวบรวมบันทึกจากโลกิ

การตั้งค่าโพร เพิ่ม promtail งาน:

- job_name: 'promtail'
 scrape_interval: 10s
 static_configs:
   - targets: ['promtail:9080']

และวาดกราฟ:

รวบรวมบันทึกจากโลกิ

ด้วยวิธีนี้ คุณสามารถค้นหาข้อความค้นหาที่ช้าที่สุดสี่รายการ คุณยังสามารถกำหนดค่าการมอนิเตอร์สำหรับเมทริกเหล่านี้

มาตราส่วน

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

รวบรวมบันทึกจากโลกิ

ชิ้นสามารถจัดเก็บไว้ในที่เก็บข้อมูลที่เข้ากันได้กับ S3 สำหรับการจัดเก็บดัชนี ใช้ฐานข้อมูลที่ปรับขนาดได้ในแนวนอน: Cassandra, BigTable หรือ DynamoDB ส่วนอื่นๆ ของ Loki - ผู้จัดจำหน่าย (สำหรับการเขียน) และ Querier (สำหรับการค้นหา) - เป็นแบบไร้สัญชาติและปรับขนาดตามแนวนอนด้วย

ในการประชุม DevOpsDays Vancouver 2019 หนึ่งในผู้เข้าร่วม Callum Styan ประกาศว่า Loki โครงการของเขามีบันทึกขนาดเพตะไบต์ที่มีดัชนีน้อยกว่า 1% ของขนาดทั้งหมด: “Loki เชื่อมโยงเมตริกและบันทึกอย่างไร — และช่วยคุณประหยัดเงิน"

การเปรียบเทียบโลกิและ ELK

ขนาดดัชนี

เพื่อทดสอบขนาดดัชนีผลลัพธ์ ฉันนำบันทึกจากคอนเทนเนอร์ nginx ซึ่งมีการกำหนดค่าไปป์ไลน์ด้านบน ไฟล์บันทึกมี 406 บรรทัด มีปริมาณรวม 624 MB บันทึกถูกสร้างขึ้นภายในหนึ่งชั่วโมง ประมาณ 109 บันทึกต่อวินาที

ตัวอย่างของสองบรรทัดจากบันทึก:

รวบรวมบันทึกจากโลกิ

เมื่อจัดทำดัชนีโดย ELK จะมีขนาดดัชนี 30,3 MB:

รวบรวมบันทึกจากโลกิ

ในกรณีของ Loki สิ่งนี้ให้ดัชนีประมาณ 128 KB และข้อมูลประมาณ 3,8 MB เป็นชิ้นๆ เป็นที่น่าสังเกตว่าบันทึกถูกสร้างขึ้นโดยปลอมและไม่มีข้อมูลที่หลากหลาย gzip อย่างง่ายบนบันทึก Docker JSON ดั้งเดิมพร้อมข้อมูลให้การบีบอัด 95,4% และเนื่องจากมีเพียงบันทึก nginx ที่ล้างแล้วเท่านั้นที่ส่งไปยัง Loki เอง การบีบอัดถึง 4 MB นั้นเข้าใจได้ จำนวนค่าที่ไม่ซ้ำกันทั้งหมดสำหรับป้ายกำกับ Loki คือ 35 ซึ่งอธิบายถึงขนาดที่เล็กของดัชนี สำหรับ ELK บันทึกจะถูกล้างด้วย ดังนั้น Loki จึงบีบอัดข้อมูลต้นฉบับถึง 96% และ ELK ถึง 70%

การใช้หน่วยความจำ

รวบรวมบันทึกจากโลกิ

หากเราเปรียบเทียบกอง Prometheus และ ELK ทั้งหมด Loki จะ "กิน" น้อยลงหลายเท่า เป็นที่ชัดเจนว่าบริการ Go ใช้พลังงานน้อยกว่าบริการ Java และการเปรียบเทียบขนาดของ Heap Elasticsearch JVM และหน่วยความจำที่จัดสรรสำหรับ Loki นั้นไม่ถูกต้อง แต่อย่างไรก็ตาม ควรสังเกตว่า Loki ใช้หน่วยความจำน้อยกว่ามาก ข้อได้เปรียบของ CPU นั้นไม่ชัดเจนนัก แต่ก็มีอยู่เช่นกัน

ความเร็ว

โลกิ "เขมือบ" บันทึกเร็วขึ้น ความเร็วขึ้นอยู่กับหลายปัจจัย - บันทึกประเภทใด เราแยกวิเคราะห์ซับซ้อนเพียงใด เครือข่าย ดิสก์ ฯลฯ - แต่สูงกว่าของ ELK อย่างแน่นอน (ในการทดสอบของฉัน - ประมาณสองครั้ง) สิ่งนี้อธิบายได้จากข้อเท็จจริงที่ว่าโลกิใส่ข้อมูลลงในดัชนีน้อยลงมาก ดังนั้น จึงใช้เวลาน้อยลงในการจัดทำดัชนี ในกรณีนี้ สถานการณ์จะกลับกันด้วยความเร็วการค้นหา: Loki ช้าลงอย่างเห็นได้ชัดสำหรับข้อมูลที่มีขนาดใหญ่กว่าสองสามกิกะไบต์ ในขณะที่สำหรับ ELK ความเร็วในการค้นหาไม่ได้ขึ้นอยู่กับขนาดข้อมูล

บันทึกการค้นหา

Loki ด้อยกว่า ELK อย่างมากในแง่ของความสามารถในการค้นหาบันทึก Grep ที่มีนิพจน์ทั่วไปนั้นแข็งแกร่ง แต่ก็ด้อยกว่าฐานข้อมูลสำหรับผู้ใหญ่ การไม่มีการค้นหาช่วง การรวมเฉพาะตามป้ายกำกับ การไม่สามารถค้นหาโดยไม่มีป้ายกำกับ ทั้งหมดนี้จำกัดเราในการค้นหาข้อมูลที่น่าสนใจในโลกิ นี่ไม่ได้หมายความว่าจะไม่พบสิ่งใดเลยเมื่อใช้ Loki แต่จะกำหนดขั้นตอนการทำงานกับบันทึก เมื่อคุณพบปัญหาในแผนภูมิ Prometheus เป็นครั้งแรก จากนั้นจึงมองหาสิ่งที่เกิดขึ้นในบันทึกโดยใช้ป้ายกำกับเหล่านี้

อินเตอร์เฟซ

แรกๆ ก็สวย (ขออภัย ทนไม่ได้) Grafana มีอินเทอร์เฟซที่ดูดี แต่ Kibana ใช้งานได้ดีกว่ามาก

ข้อดีและข้อเสียของโลกิ

ในข้อดีสามารถสังเกตได้ว่า Loki ผสานรวมกับ Prometheus ตามลำดับ เราได้รับเมตริกและการแจ้งเตือนนอกกรอบ สะดวกในการรวบรวมบันทึกและจัดเก็บไว้ใน Kubernetes Pods เนื่องจากมีการค้นพบบริการที่สืบทอดมาจาก Prometheus และติดป้ายกำกับโดยอัตโนมัติ

จากข้อเสีย - เอกสารที่ไม่ดี บางสิ่ง เช่น คุณสมบัติและความสามารถของ Promtail ฉันค้นพบเฉพาะในขั้นตอนของการศึกษาโค้ด ประโยชน์ของโอเพ่นซอร์ส ข้อเสียอีกประการหนึ่งคือความสามารถในการแยกวิเคราะห์ที่อ่อนแอ ตัวอย่างเช่น โลกิไม่สามารถแยกวิเคราะห์บันทึกหลายบรรทัดได้ นอกจากนี้ ข้อเสียยังรวมถึงความจริงที่ว่าโลกิเป็นเทคโนโลยีที่ค่อนข้างใหม่ (เปิดตัว 1.0 ในเดือนพฤศจิกายน 2019)

ข้อสรุป

Loki เป็นเทคโนโลยีที่น่าสนใจ 100% ซึ่งเหมาะสำหรับโครงการขนาดเล็กและขนาดกลาง ช่วยให้คุณสามารถแก้ปัญหาต่างๆ ของการรวมบันทึก การค้นหาบันทึก การตรวจสอบและวิเคราะห์บันทึก

เราไม่ใช้ Loki ที่ Badoo เพราะเรามีสแต็ก ELK ที่เหมาะกับเราและมีโซลูชันแบบกำหนดเองมากมายในช่วงหลายปีที่ผ่านมา สำหรับเรา สิ่งที่สะดุดคือการค้นหาในบันทึก ด้วยบันทึกเกือบ 100 GB ต่อวัน จึงเป็นสิ่งสำคัญสำหรับเราที่จะสามารถค้นหาทุกสิ่งและเพิ่มเติมอีกเล็กน้อยและดำเนินการได้อย่างรวดเร็ว สำหรับการสร้างแผนภูมิและการตรวจสอบ เราใช้โซลูชันอื่นๆ ที่ปรับให้เหมาะกับความต้องการของเราและผสานรวมเข้าด้วยกัน Loki stack มีประโยชน์ที่จับต้องได้ แต่จะไม่ได้ให้อะไรมากไปกว่าที่เรามี และประโยชน์ของมันก็ไม่ได้มากไปกว่าค่าใช้จ่ายในการย้ายถิ่น

และแม้ว่าหลังจากการวิจัยเป็นที่ชัดเจนว่าเราไม่สามารถใช้ Loki ได้ แต่เราหวังว่าโพสต์นี้จะช่วยคุณในการเลือก

ที่เก็บพร้อมรหัสที่ใช้ในบทความตั้งอยู่ ที่นี่.

ที่มา: will.com

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