การบันทึกแบบรวมศูนย์

รวมศูนย์การบันทึก Docker ของคุณด้วย Syslog

วิธีที่ดีที่สุดในการทำความเข้าใจระบบของเราและความสำเร็จหรือความล้มเหลวคือการบันทึกข้อมูลที่ยอดเยี่ยม

พื้นหลัง

ในระหว่างหนึ่งในโปรเจ็กต์ที่ฉันทำในช่วงไม่กี่ปีที่ผ่านมา ฉันมีงานบูรณาการระบบการบันทึกแบบรวมศูนย์เข้ากับสแต็กแอปพลิเคชันที่เราใช้ (ตามสถาปัตยกรรมไมโครเซอร์วิส) แนวคิดแรกที่เข้ามาในใจคือการสร้างสแต็ก ELK (Elasticsearch, Logstash, Kibana) เพื่อทำงานนี้ให้สำเร็จ อย่างไรก็ตาม ปรากฎว่านี่ไม่ใช่ทางเลือกเนื่องจากมีข้อจำกัดด้านทรัพยากรของโครงการ

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

  • รวบรวมบันทึกนักเทียบท่าโดยตรง
  • การใช้ Syslog เพื่อรวบรวมบันทึก

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

อีกแนวคิดหนึ่งคือการส่งต่อบันทึกไปยังบริการที่มีการจัดการ เช่น "logz.io" ตัวเลือกนี้ยังทำไม่ได้เนื่องจากเซิร์ฟเวอร์ที่ใช้งานจริงไม่มีอินเทอร์เน็ต—แถมยังมีข้อจำกัดด้านงบประมาณเท่าเดิม

แนวคิดที่สามคือการตั้งค่าสคริปต์ Logrotate ที่ดำเนินการต่อไปนี้เพื่อสร้างไฟล์บันทึก:

  • รวบรวมบันทึกนักเทียบท่าจาก /var/lib/docker/containers/*
  • เปลี่ยนชื่อไฟล์ด้วยชื่อคอนเทนเนอร์แทนรหัส
  • บีบอัดไฟล์บันทึก

ขั้นตอนที่สองของแนวคิดนี้คือการตั้งค่างาน Cron เพื่อคัดลอกไฟล์บันทึกไปยังเซิร์ฟเวอร์ส่วนกลางซึ่งสามารถโหลดและตรวจสอบบันทึกได้

แนวคิดนี้มีข้อเสียมากมายและเหมือนกับการคิดค้นล้อขึ้นมาใหม่มากกว่า ข้อเสียที่สำคัญที่สุดประการหนึ่งคือบันทึกจะสูญหายหากมีการปรับใช้ใหม่และเปลี่ยนคอนเทนเนอร์

นั่นคือเหตุผลที่ฉันเริ่มมองหาโซลูชันทางเลือกที่จะช่วยให้เรารวบรวมบันทึกจากเซิร์ฟเวอร์ไปยังเซิร์ฟเวอร์รวมศูนย์โดยไม่สูญเสียบันทึก โชคดีที่ Docker รองรับไดร์เวอร์บันทึกหลายตัว (ดู รายการทั้งหมด) หนึ่งในไดรเวอร์บันทึกเหล่านี้คือ Syslog ซึ่งตามค่าเริ่มต้นจะติดตั้งบนระบบ Linux (ไม่จำเป็นต้องติดตั้งซอฟต์แวร์เพิ่มเติม) ด้วยเหตุนี้ ฉันจึงตัดสินใจใช้ระบบการบันทึกแบบรวมศูนย์กับ Syslog

การนำไปปฏิบัติ

ด้วยเหตุผลด้านความเรียบง่ายเท่านั้น ให้เราถือว่าโครงสร้างพื้นฐานที่โฮสต์ไมโครเซอร์วิสประกอบด้วยโหนดต่อไปนี้:

  • คลัสเตอร์ Docker สองโหนดที่โฮสต์บริการ
  • หนึ่งโหนดสำหรับจัดเก็บบันทึก

การกำหนดค่าเซิร์ฟเวอร์บันทึก

ในการกำหนดค่าเซิร์ฟเวอร์บันทึกและทำให้พร้อมสำหรับการรวบรวมบันทึกจากโฮสต์ Docker ฉันต้องทำขั้นตอนต่อไปนี้:

  • ตรวจสอบให้แน่ใจว่าติดตั้ง Syslog หรือติดตั้งโดยใช้คำสั่งด้านล่าง:
$> yum update -y
$> sudo yum install rsyslog rsyslog-doc
  • รายการบนพอร์ต TCP ที่ถูกต้อง บรรทัดด้านล่างต้องมีอยู่ในไฟล์กำหนดค่า Syslog /etc/rsyslog.conf:
$ModLoad imtcp $InputTCPServerRun 514
  • อัปเดตการกำหนดค่าขีดจำกัดอัตราสมุดรายวันสำหรับทั้ง Syslog และ journald ควรเพิ่มการกำหนดค่าด้านล่างลงในไฟล์ /etc/rsyslog.conf เพื่อหลีกเลี่ยงการสูญเสียบันทึกในกรณีที่มีข้อความบันทึกมากเกินไป ดู "เอกสารประกอบของ Syslog" สำหรับข้อมูลเพิ่มเติม
$imjournalRatelimitInterval 0
$imjournalRatelimitBurst 0
  • นอกจากนี้ จำเป็นต้องตั้งค่าการกำหนดค่าขีดจำกัดอัตราเป็น 0 ในไฟล์การกำหนดค่า journald /etc/systemd/journald.conf
RateLimitInterval=0

ตามค่าเริ่มต้น Syslog จะจัดเก็บบันทึกทั้งหมดใน /var/log/messages อย่างไรก็ตาม เราต้องการแยกบันทึกตามชื่อคอนเทนเนอร์เพื่อให้ตรวจสอบได้ง่ายขึ้น ในการกำหนดค่าเซิร์ฟเวอร์ Syslog ให้แยกบันทึกจากคอนเทนเนอร์ต่างๆ เป็นไฟล์ต่างๆ เราต้องดำเนินการตามขั้นตอนต่อไปนี้:

  • ตัดสินใจและสร้างโฟลเดอร์เพื่อเก็บบันทึกทั้งหมด
$> mkdir /var/log/dockerlfs
  • รวบรวมบันทึกสำหรับ Docker daemon และบันทึกลงในดิสก์ กฎการกำหนดค่า Syslog ด้านล่าง (เก็บไว้ใน /etc/rsyslog.d/docker_daemon.conf) จะทำให้ Syslog บันทึกบันทึกทั้งหมดที่เป็นของโปรแกรมที่เริ่มต้น docker ถึง /var/log/dockerlfs/daemon.log
  • รวบรวมบันทึกคอนเทนเนอร์ Docker และบันทึกเป็นไฟล์บันทึกแยกกัน กฎการกำหนดค่า Syslog ด้านล่างจะบันทึกบันทึกลงในไฟล์แต่ละไฟล์สำหรับแต่ละคอนเทนเนอร์ที่ทำงานอยู่ตามชื่อคอนเทนเนอร์ กฎควรเก็บไว้ใน /etc/rsyslog.d/docker_container.con กฎนี้อาศัยโฮสต์ Docker เพื่อแท็กบันทึกทั้งหมดด้วย container_name

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

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

$> systemctl restart rsyslog
$> systemctl restart systemd-journald

กำหนดค่าโฮสต์นักเทียบท่า

ตอนนี้เรากำหนดค่าเซิร์ฟเวอร์ Syslog เสร็จแล้ว เราสามารถดำเนินการต่อและเริ่มกำหนดค่าโฮสต์ Docker เพื่อส่งต่อบันทึกจากเซิร์ฟเวอร์ไปยังเซิร์ฟเวอร์ Syslog

สิ่งแรกที่ต้องทำคือกำหนดค่า Docker daemon ใหม่ให้ใช้ไดรเวอร์บันทึก syslog แทน journald และแท็กบันทึกด้วยชื่อคอนเทนเนอร์ เพื่อให้บรรลุเป้าหมายนี้ เราจำเป็นต้องแก้ไขไฟล์การกำหนดค่า Docker daemon ที่อยู่ภายใต้ /etc/docker daemon.json ควรมีเนื้อหาดังต่อไปนี้:

ตัวแปร SYSLOG_SERVER_IP ควรถูกแทนที่ด้วย IP ของเซิร์ฟเวอร์ Syslog ตัวแปร ENV_NAME ควรถูกแทนที่ด้วยชื่อสภาพแวดล้อม (การทดสอบ การจัดเตรียม หรือการใช้งานจริง) ด้วยการกำหนดค่าข้างต้น Docker จะส่งต่อบันทึกโดยตรงไปยังเซิร์ฟเวอร์ Syslog ในกรณีที่เซิร์ฟเวอร์ Syslog หยุดทำงานหรือไม่มีการเชื่อมต่อที่ถูกต้อง เราอาจสูญเสียบันทึกบางส่วนที่มีการกำหนดค่าข้างต้น

เพื่อปรับปรุงระบบการบันทึกของเราและหลีกเลี่ยงการสูญเสียบันทึก เราจะดำเนินการเปลี่ยนแปลงต่อไปนี้:

  • ส่งต่อบันทึกจาก Docker ไปยังเซิร์ฟเวอร์ภายในเครื่อง
  • กำหนดค่า Syslog ภายในเครื่องเพื่อส่งต่อบันทึกไปยังเซิร์ฟเวอร์บันทึกส่วนกลาง

หากต้องการส่งต่อบันทึกจาก Docker ไปยังเซิร์ฟเวอร์ Syslog ภายใน เราเพียงแค่ต้องลบบรรทัดต่อไปนี้ออกจาก /etc/docker/daemon.json หรือแทนที่ SYSLOG_SERVER_IP ด้วย 127.0.0.1:

"syslog-address": "tcp://${SYSLOG_SERVER_IP}:514",

เมื่อเราตั้งค่า Docker เสร็จแล้ว เราจะต้องรีสตาร์ท Docker daemon

$> systemctl restart docker

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

การกำหนดค่า syslog และเจอร์นัล

เราต้องการรายการการกำหนดค่าต่อไปนี้สำหรับ journald ในไฟล์ /etc/systemd/journald.conf: RateLimitInterval=0

เราต้องการรายการการกำหนดค่าต่อไปนี้สำหรับ Syslog ในไฟล์ /etc/rsyslog.conf:

$ActionQueueFileName fwdRule1
$ActionQueueSaveOnShutdown on
$ActionQueueType LinkedList
$ActionResumeRetryCount -1
$imjournalRatelimitInterval 0
$imjournalRatelimitBurst 0
  • ActionQueueFileName:เพิ่มคำนำหน้าชื่อที่ไม่ซ้ำสำหรับสปูลไฟล์
  • ActionQueueSaveOnShutdown:บันทึกข้อความลงดิสก์เมื่อปิดเครื่อง
  • ActionQueueType: เรียกใช้แบบอะซิงโครนัส
  • ActionResumeRetryCount:ฉันลองอีกครั้งไม่สิ้นสุดหากโฮสต์ล่ม

ด้วยการกำหนดค่าข้างต้น Syslog จะพยายามส่งบันทึกไปยังเซิร์ฟเวอร์ส่วนกลางต่อไปจนกว่าเซิร์ฟเวอร์ปลายทางจะบันทึกบันทึก อย่างไรก็ตาม จนถึงขณะนี้ เรายังไม่ได้กำหนดค่าเซิร์ฟเวอร์ Syslog ภายในเครื่องบนโฮสต์ Docker เพื่อส่งต่อบันทึกไปยังเซิร์ฟเวอร์อื่น ดังนั้น บันทึกทั้งหมดที่รวบรวมจาก Docker จะถูกบันทึกไว้ในไฟล์เริ่มต้น /var/log/messages

การส่งต่อบันทึกจาก Syslog ไปยังเซิร์ฟเวอร์อื่นนั้นง่ายมาก คุณจะต้องเพิ่มกฎต่อไปนี้ต่อท้ายไฟล์ /etc/rsyslog.conf และแทนที่ SYSLOG_SERVER_IP ด้วย IP ของเซิร์ฟเวอร์บันทึกที่ถูกต้อง โดยทั่วไปกฎนี้จะตรวจสอบบันทึกทั้งหมดและกรองตามแท็กและชื่อโปรแกรม หากแท็กข้อความมีแท็กชื่อ container_name หรือ programname ให้เริ่มต้นด้วย docker จากนั้นมันจะส่งต่อบันทึกไปที่ SYSLOG_SERVER_IP

เราสามารถปรับปรุงกฎข้างต้นได้โดยเก็บสำเนาของบันทึกไว้ในเซิร์ฟเวอร์ Docker เมื่อมีการเปลี่ยนแปลงด้านล่าง กฎ Syslog ของเราจะส่งบันทึกไปยังเซิร์ฟเวอร์ Syslog ระยะไกล และจะเก็บสำเนาของไฟล์บันทึกไว้ในเครื่องบนเซิร์ฟเวอร์แต่ละตัวที่ใช้ Docker ภายใต้ /var/log/dockerlfs

เนื่องจากขณะนี้เรามีสำเนาของไฟล์บันทึกบนเซิร์ฟเวอร์ Docker จึงสมเหตุสมผลที่จะเพิ่มกฎ Logrotate เพื่อหมุนไฟล์เหล่านี้ด้วย เราสามารถใช้กฎเดียวกันกับที่ใช้สำหรับโหนดเซิร์ฟเวอร์

สุดท้ายนี้ จำเป็นต้องรีสตาร์ทเพื่อให้ทั้ง Syslog และ journald เพื่อรับการกำหนดค่าใหม่

$> systemctl restart rsyslog
$> systemctl restart systemd-journald

บทสรุป

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