Skip to main content
صادق محبی

کار و بار های یک نیمچه برنامه نویس

سنت‌ های اصیل مدیریت و انتقال لاگ‌ها - بخش اول

معرفی و بررسی پروتکل syslog , RELP و ابزار rsyslog

چند وقت پیش در یکی از جلسات tehlug نشسته بودم و آخرین ارائه‌ نیز در خصوص پیاده سازی logstash و ذخیره سازی لاگ ها در الستیک سرچ بود تا با kibana بتوان روی آن کوئری زد و داشبورد ساخت. یکی از حاظران در زمان پرسش و پاسخ انتهای جلسه ابتدا از معایب انتقال لاگ بر بستر HTTP گفت و سپس به RELP اشاره کرد که به عنوان یک پروتکل انتقال لاگ قابل استفاده است. از آن موقع که حدود ۴ ماه گذشته، گوشه‌ی ذهنم در خصوص کارکرد RELP سوالات زیادی بود و تحقیقاتی نیز کردم. در ادامه‌ی این مقاله با ذوق زدگی از تعاریف و کارکرد ها تا اجرای یک پروژه‌ی عملی براتون می‌گم.

فلسفه‌ی چیستی و چرایی وجود #

به طور کلی پروتکل RELP یا مخفف reliable event logging protocol روشی است برای انتقال لاگ ایونت های سیستم و نرم افزار بر بستر شبکه که می تواند با سرعت زیاد و در مقیاس و اتکاپذیری بالا به خوبی عمل کند. به گفته‌ی خالق RELP ، ایجاد این پروتکل به علت نواقصی بود که syslog پوشش نمی داد و در دنیای ابری امروز قابل استفاده نبود و RELP بر اساس syslog توسعه یافته است. پس در اینجا لازم است ابتدا نگاهی به syslog بیاندازیم.

برای مطالعه جزئیات پروتکل syslog پیشنهاد می‌کنم که حتما نگاهی به RFC5424 بیاندازید ولی در ادامه با همدیگه مروری سریع روی آن خواهیم داشت.

اگر در پروتکل http ما مفاهیمی مثل client و server و proxy داریم، در syslog نیز مفاهیم تقریبا مشابه ای وجود دارد:

  1. content
  2. syslog application -> originator , collector , rely
  3. syslog transport -> transport sender or receiver

لایه‌ی اول محتوای پیامی است که قرار است نوشته و ضبط شود. لایه‌ی دوم برنامه هایی هستند که عملا آن پیام را می نویسند یا می خوانند و لایه‌ی سوم صرفا پیام را روی شبکه منتقل می‌کند.

محتوای پیام در پروتکل syslog اجزای مختلفی دارد که در RFC5424 نیز مفصل با مثال های کاربردی به آن‌ها پرداخته است ولی در بین تمامی پارامتر ها ، یک پارامتر خیلی دقیق به اسم PRI یا Priority توجهم رو جلب کرد. این پارامتر در پیام های syslog الزامی است و به فرمت خاص عدد یک تا سه رقمی پر می‌شود. پارامتر فوق از دو مقدار Facility و Severity محاسبه می‌شود و فرمول محاسبه آن به صورت زیر است:

Priority = (Facility * 8) + Severity

نکته‌ی جالب تر لیست مقادیر Facility و Severity هست که دید خیلی خوبی در طراحی سیستم های لاگ و مانیتورینگ می‌دهد. تعاریف و ظرافتی که در این سطوح دو جدول زیر خواهید دید هیجان انگیزه!

Numerical CodeFacility درجه وقوع
0kernel messages
1user-level messages
2mail system
3system daemons
4security/authorization messages
5messages generated internally by syslogd
6line printer subsystem
7network news subsystem
8UUCP subsystem
9clock daemon
10security/authorization messages
11FTP daemon
12NTP subsystem
13log audit
14log alert
15clock daemon (note 2)
16local use 0 (local0)
17local use 1 (local1)
18local use 2 (local2)
19local use 3 (local3)
20local use 4 (local4)
21local use 5 (local5)
22local use 6 (local6)
23local use 7 (local7)
Numerical CodeSeverity درجه شدت
0Emergency: system is unusable
1Alert: action must be taken immediately
2Critical: critical conditions
3Error: error conditions
4Warning: warning conditions
5Notice: normal but significant condition
6Informational: informational messages
7Debug: debug-level messages

اگر بخواهیم یک تعریف کتابی ارائه بدهیم؛ درجه اولویت یک هشدار ، لاگ یا هر چیزی در ایونت های سیستم نرم‌افزاری به درجه وقوع و درجه شدت آن بستگی دارد. مثلا درجه اولویت یک لاگ با درجه وقوع ۲۰ و شدت ۱ به میزان ۱۶۱ اهمیت دارد. درجه‌ی اولویت در زمانی که می خواهیم قوانین هشدار سمت مانیتورینگ تنظیم کنیم یا لاگ ها را مدیریت کنیم و بخوانیم و یا در بسیاری از جاهای مرتبط دیگر بسیار بسیار کارآمد است.

البته اگر همه‌ی این قواعد را نیز رعایت کنیم (که خیلی جاها دیدم که رعایت نمی کنیم!)، بازم می‌دانیم که فرقی به حال آقای اختاپوس نمی‌کند :)

haha no matter to me

یک مثال عملی #

یکی از ابزار های متداول و رسمی کار با پروتکل syslog و RELP ابزار rsyslog است. همین الآن که این مقاله را می‌خوانید میلیون ها instance از rsyslog در بسیاری از سرور های لینوکسی وظیفه انتقال و مدیریت لاگ ایونت های سیستمی و کرنل لینوکس را بر عهده دارند.

آیا می‌دانستید که داکر به صورت پیش فرض از درایور syslog پشتیبانی می‌کند؟ این در حالی است که برای پشتیبانی داکر از Grafana-Loki باید پلاگین و درایور آن را نصب کنیم.

ما در اینجا می‌خواهیم با استفاده از rsyslog لاگ های یک کانتینر پیش فرض nginx را به دیتابیس برادر دوقلوی متن‌باز ردیس یعنی ValKey استریم کنیم و تلاش می‌کنیم تمامی این سناریو را در یک فایل docker compose ساده پیاده‌سازی کنیم تا صرفا لذت استفاده از rsyslog رو بچشیم.

ابتدا فایل داکر کامپوز زیر را ایجاد می کنیم. در اینجا سه تا سرویس تنظیم و اجرا کردیم که لاگ های nginx توسط rsyslog به صورت استریم در valkey ذخیره شود.

services:
  valkey: 
    image: valkey/valkey:7.2-alpine

  rsyslog:
    build: ./rsyslog/
    ports:
      - 514:514

  nginx:
    image: nginx:1.27-alpine
    ports:
      - 8080:80
    logging:
      driver: syslog
      options:
        syslog-address: "tcp://127.0.0.1:514"

داکر با استفاده از درایور پیش فرض syslog لاگ های کنسول یا stdout سرویس nginx را به پورت ۵۱۴ مربوط به سرویس rsyslog فوروارد می‌کند. این عملکرد را خود rsyslog نیز می تواند به تنهایی با ماژول های فراوانی که دارد انجام دهد. در واقع rsyslog ماژول های جداگانه‌ای برای ورودی و خروجی لاگ ها دارد که برخی از آن‌ها را در ادامه خواهیم دید.

داکرفایل سرویس rsyslog را نیز به صورت زیر نوشتیم که پکیج های لازم را در لینوکس alpine نصب و اجرا کند.

FROM alpine:3

RUN	apk --no-cache update && \
  apk add --no-cache rsyslog rsyslog-hiredis

COPY rsyslog.conf /etc/rsyslog.conf

CMD [ "rsyslogd", "-n" ]

فایل تنظیمات rsyslog نیز از دو بخش کلی ورودی و خروجی و تنظیمات پایه ای تشکیل شده است.

global(processInternalMessages="on")

module(load="impstats")
module(load="imptcp")
module(load="imudp" TimeRequery="500")
module(load="omstdout")
module(load="omhiredis")

input(type="imptcp" port="514")
input(type="imudp" port="514")

# we emit our own messages to docker console:
syslog.* :omstdout:

# finally all forwarded logs xadd stream to valkey db
action(
  type="omhiredis"
  server="valkey"
  serverport="6379"
  mode="stream"
  key="stream_output"
  stream.outField="data")

include(text=`echo $CNF_CALL_LOG_TO_LOGFILES`)
include(text=`echo $CNF_CALL_LOG_TO_LOGSENE`)

در ابتدا ماژول هایی که لازم داشتیم import شده است. همچنین لاگ های داخلی خود rsyslog نیز فعال شده که در بخش بعدی آن را در stdout خروجی دهیم. در نهایت با استفاده از template پیش فرض تمامی لاگ هایی که روی tcp یا udp پورت ۵۱۴ می آیند را به دیتابیس valkey استریم کرده‌ایم و این کار توسط ماژول omhiredis انجام می‌شود.

برای مشاهده‌ی نتیجه‌ی کار می‌توان کامند های مربوط به خواندن استریم valkey (بخوانید ردیس!) را به صورت زیر اجرا کرد و همان طور که مشخص است لاگ nginx را در valkey می‌بینیم.

valkey-cli "XRANGE stream_output - +"

rsyslog valkey nginx lab result screenshot

هنوز نرسیدیم #

این نوشته تنها بخش اول ماجراجویی مان در دریای rsyslog بود. سوالات زیادی همچنان باقی مانده است:

اصلا به relp نپرداختیم؛ در موردش صحبت نکردیم و دمو ای ازش ندیدیم. چه تفاوتی با پروتکل syslog دارد و relp چه نقاط ضعفی از syslog را پوشش داده است؟

ابزار rsyslog در بازار سیستم های log management چه جایگاهی دارد؟ به لحاظ کارکرد و عملکرد چه تفاوت هایی دارند و چگونه تصمیم بگیریم که از چه ابزاری استفاده کنیم؟

حالا که تا اینجا اومدی، یه فنجون قهوه مهمون مون کن ☕ پرداخت آنلاین دونیت