معماری rsyslog
هر سرور لینوکس پیام لاگ تولید میکند و هر پیام باید جایی برود. rsyslog همان دیمونی است که این پیامها را میگیرد، تصمیم میگیرد با آنها چه کند و تحویلشان میدهد. این راهنما توضیح میدهد این خط لوله چگونه ساخته شده و rsyslog در چه کارهایی از گزینههای دیگر بهتر عمل میکند.
دیمون rsyslog چیست؟
دیمون rsyslog یک برنامهٔ پسزمینه است (نه چیزی که کاربر مستقیم با آن کار میکند) که پیامهای لاگ را از برنامهها و از شبکه میگیرد و هر پیام را به مقصد مفیدی میرساند. روی سرور لینوکس امروزی، این دیمون معمولاً دو نقش متفاوت را همزمان ایفا میکند:
- جمعآوری لاگ محلی: هر چیزی را که سیستمعامل و برنامهها مینویسند میگیرد، بر اساس facility و severity دستهبندی میکند و در فایلهایی مثل
/var/log/messagesو/var/log/secureمینویسد. - ارسال لاگ: پیام سرورهای دیگر را میگیرد و به یک سرور مرکزی میرساند.
به زبان ساده: rsyslog مثل دفتر پستی برای خطوط لاگ است. مرکز تفکیک، همان موتور فیلتر است و مسیرهای تحویل، همان اکشنهای خروجی.
واژهٔ syslog هم به پروتکل شبکه اشاره دارد و هم به خانوادهای از دیمونها که این پروتکل را میفهمند. rsyslog پیادهسازی غالب روی لینوکس است و عملاً مرجع این پروتکل به شمار میرود.
چرا تقریباً همهجا نصب است؟
پکیج rsyslog در تمام توزیعهای بزرگ لینوکس وجود دارد و دیمون بسیاری از دستگاههای اختصاصی هم همان است. این فراگیری دلیلی فراتر از راحتی دارد: دستگاهی که تا حالا پیکربندی نکردهاید هم لاگهایی میفرستد که rsyslog از قبل قالبشان را میشناسد.
اگر دیمون قدیمی syslog را روی Solaris یا AIX یا یک دستگاه قدیمی جایگزین میکنید، rsyslog سازگاری نسبی با پیکربندی کلاسیک BSD را نگه داشته است. مهاجرت معمولاً یعنی ترجمهٔ دستورهای قدیمی با علامت $، نه بازطراحی خط لوله.
معماری خط لوله
هر پیام در rsyslog از یک مسیر ثابت و مشخص عبور میکند. مرحلهها عمداً کلی تعریف شدهاند؛ به همین دلیل یک دیمون میتواند بدون تغییر در نحوهٔ دریافت پیامها، همزمان در فایل محلی بنویسد و به Elasticsearch هم بفرستد.
ماژولهای ورودی
ماژول ورودی (با پیشوند im) افزونهای است که میداند پیام را از یک منبع مشخص بخواند. هیچ چیز بدون عبور از یک ماژول ورودی وارد موتور rsyslog نمیشود.
| ماژول ورودی | منبعی که میخواند |
|---|---|
imjournal | ژورنال systemd، تا rsyslog و journalctl رویدادهای یکسانی ببینند |
imtcp | پیامهایی که از طریق TCP از میزبانهای دیگر میرسند |
imudp | پیامهایی که از طریق UDP از میزبانهای دیگر میرسند |
imuxsock | سوکت یونیکس سنتی /dev/log |
imkmsg | بافر حلقوی کرنل از طریق /dev/kmsg |
imfile | فایلهای لاگ دلخواه، برای دنبال کردن لاگهای موجود |
imrelp | پروتکل RELP که برای هر پیام تأییدیه میگیرد |
در نسخههای فعلی rsyslog، ماژول imtcp ورودی پشتیبانشدهٔ TCP برای محیط عملیاتی است. ماژول قدیمیتر imptcp هنوز وجود دارد اما دیگر گزینهٔ پیشنهادی نیست.
صف اصلی پیام
هر پیامی که وارد موتور میشود، پیش از هر چیز دیگر در یک صف اصلی پیام قرار میگیرد. صف یک فضای انتظار است که تولیدکنندهٔ سریع را از مصرفکنندهٔ کند جدا میکند و همین ایده پشت بیشتر ویژگیهای پایداری rsyslog است.
پس از اینکه رولست پیام را پردازش کرد، پیام از صف اصلی خارج و وارد صف پاییندستی میشود و در همان لحظه از صف اصلی حذف میشود. این جابهجایی مهم است، چون تضمین میکند یک خروجی کند هرگز دریافت پیام را متوقف نمیکند.
رولست و فیلترها
رولست یک بلوک نامدار از قواعد است که هم فیلتر میکند و هم عمل انجام میدهد. داخل هر قاعده، شرط روی فیلدهای ساختاریافتهٔ پیام سنجیده میشود، نه روی متن خام؛ پس تطبیق بر اساس severity یا نام برنامه دقیق است و به قالببندی وابسته نیست.
rsyslog فیلدهای ساختاریافته برای زمان، نام میزبان، نام برنامه، شناسهٔ پروسه، شناسهٔ پیام، facility، severity و دادههای ساختاریافته را نگه میدارد. تحلیل مدرن بر پایهٔ RFC 5424 انجام میشود که استاندارد کنونی syslog است و قالب قدیمی RFC 3164 هم برای فرستندههای قدیمی پذیرفته میشود.
اکشنها و صفها
اکشن (با پیشوند om) کاری با پیام انجام میدهد: نوشتن در فایل، ارسال به میزبان دیگر یا تحویل به پایگاه داده. هر اکشن میتواند صف مخصوص خودش را داشته باشد و این صفها مستقل از هم تنظیم میشوند.
چرا مهم است: همین صفِ جداگانه برای هر خروجی است که به یک نمونهٔ rsyslog اجازه میدهد در برابر کندی یک کلاستر Elasticsearch مقاوم بماند و همزمان فایلهای محلی را با تمام سرعت بنویسد. مقصد کند صف خودش پر میشود و در نهایت پیام دور میریزد، در حالی که بقیهٔ مسیرها بیوقفه کار میکنند.
صف و کنترل جریان
رفتار صف مهمترین تصمیم طراحی در یک استقرار rsyslog است؛ چون تعیین میکند ساعت ۳ بامداد که شبکه قطع شد، صبح چه چیزی از آن شب باقی مانده است.
| نوع صف | محل نگهداری | پس از ریاستارت | کاربرد معمول |
|---|---|---|---|
Direct | بدون ذخیره | ندارد | نوشتن فایل محلی، جایی که تأخیر مهمتر است |
LinkedList / FixedArray | حافظه | ندارد | مسیرهای پرترافیک که افتادن پیام در آنها قابل قبول است |
Disk-Assisted | حافظه با سرریز به دیسک | دارد | ارسال به سرور مرکزی، انتخاب رایج در محیط عملیاتی |
Disk | فقط دیسک | دارد | مسیرهای حسابرسی و بایگانی که هیچ پیامی نباید گم شود |
پارامترهای صف با نحو RainerScript داخل همان آبجکتی نوشته میشوند که صف را در اختیار دارد؛ پس main_queue()، ruleset() و action() هر کدام تنظیمات queue.* مستقل خود را میگیرند.
main_queue(
queue.type="LinkedList"
queue.size="500000"
queue.filename="mainq"
queue.saveOnShutdown="on"
queue.maxDiskSpace="2g"
)
آستانههای بالا و پایین (Watermark)
کنترل جریان از دو آستانه استفاده میکند که به آنها watermark میگویند. وقتی صف به آستانهٔ بالا میرسد، تولیدکننده کند یا متوقف میشود؛ پردازش وقتی ادامه پیدا میکند که صف زیر آستانهٔ پایین تخلیه شود.
فاصلهٔ میان این دو آستانه عمدی است. بدون آن، صفی که مدام نزدیک آستانه نوسان کند بارها بین حالت پر و خالی میلغزد و پردازش را مکرراً متوقف میکند.
صفی که پر شود با صدای بلند شکست نمیخورد. بسته به پیکربندی، rsyslog پیامها را بیسروصدا دور میریزد و در خروجی هم چیزی نشان نمیدهد. نرخ پرشدگی صفها را پایش کنید و تحویل را مفروض نگیرید.
زبان RainerScript
RainerScript زبان پیکربندی rsyslog است که مشخصاً برای پردازش جریان رویدادها طراحی شده. این زبان جایگزین نحو قدیمی با علامت $ شد، هرچند شکل قدیمی هنوز کار میکند و در بسیاری از پیکربندیهای موجود پیدا میشود.
آبجکتهای اصلی که مینویسید global()، module()، input()، action()، template() و ruleset() هستند. کنترل جریان با دستورهای آشنای if و then انجام میشود؛ پس نحو برای هر کسی که یک اسکریپت شل نوشته، خوانا میماند.
global(
workDirectory="/var/spool/rsyslog"
maxMessageSize="64k"
defaultNetstreamDriver="gtls"
)
module(load="imtcp" port="6514")
module(load="imjournal" StateFile="imjournal.state")
template(name="ForwardFormat" type="string"
string="<%pri%>1 %TIMESTAMP:::date-rfc3339% %hostname% %app-name% %procid% %msgid% %structured-data% %msg%\n")
if ($syslogfacility-text == "authpriv") then {
action(type="omfile" file="/var/log/secure" template="RSYSLOG_TraditionalFileFormat")
stop
}
پارامتر workDirectory مشخص میکند صفهای دیسکی و Disk-Assisted پشتیبان انباشتهشدهشان را کجا بنویسند. آن را روی پارتیشنی بگذارید که فضای آزاد واقعی دارد؛ چون صفی که نتواند فایل سرریزش را بنویسد، جایی برای پیامهای ورودی ندارد.
کاربردهای عملی rsyslog
rsyslog در چند دلیل مشخص جای خودش را در یک استک مدرن باز کرده است. دانستن اینکه کدامیک از این دلایل به شما مربوط میشود، تعیین میکند اصلاً به آن نیاز دارید یا نه.
تحمل قطعی شبکه
قویترین دلیل برای انتخاب rsyslog همین است. syslog روی TCP خالص تأییدیه ندارد؛ پس فرستندهای که بافرش هنگام قطعی شبکه پر شود، پیامها را بیسروصدا دور میریزد. صف Disk-Assisted قطعی را روی دیسک جذب میکند و بعد از برگشت لینک تخلیهاش میکند.
| سناریو | TCP خالص با imtcp | RELP با imrelp | صف Disk-Assisted |
|---|---|---|---|
| تأیید تحویل بدون از دست رفتن | ❌ | ✅ | ✅ |
| بافر کردن پیام هنگام قطعی | ❌ | تا حدی | ✅ |
| بقای پیامها پس از ریاستارت | ❌ | ❌ | ✅ |
پروتکل RELP (مخفف Reliable Event Logging Protocol) تأیید بهازایهرپیام را به syslog اضافه میکند. گیرنده هر پیام را تأیید میکند و بعد فرستنده آن را دور میریزد؛ همین تحویلِ «بهدردبخور» را به تحویل تأییدشده تبدیل میکند.
جمعآوری لاگ در یک ناوگان
مرکزی کردن لاگ دلیلی است که بیشتر سازمانها rsyslog را اجرا میکنند. وقتی لاگ فقط روی همان دستگاهی بماند که آن را تولید کرده، دستگاهِ از کار افتاده شاهدِ خودش را هم با خود میبرد.
مسیریابی به مقصدهای متعدد
فهرست ماژولهای خروجی برای یک دیمون سیستمی غیرعادی گسترده است. یک نمونه میتواند از یک جریان پیام واحد، هم فایل محلی بنویسد، هم به rsyslog دیگری بفرستد و هم رویدادهای ساختاریافته را به یک کلاستر جستجو بفرستد.
| ماژول خروجی | مقصد |
|---|---|
omfile | فایل محلی همراه با چرخش |
omfwd | سرور syslog دیگر روی UDP، TCP یا RELP |
omelasticsearch | کلاستر Elasticsearch یا OpenSearch |
omkafka | یک تاپیک در Apache Kafka |
omhiredis | یک لیست یا استریم در Redis |
ommongodb / ompgsql / ommysql | پایگاه دادهٔ سندی یا رابطهای |
omsnmp | ترپ SNMP برای تجهیزات شبکه |
فیلتر کردن پیش از ذخیرهسازی
چون رولست روی فیلدهای ساختاریافته تست میشود نه روی متن، قواعد مسیریابی حتی وقتی برنامه قالب پیامش را عوض کند درست میمانند. جدا کردن رویدادهای احراز هویت در /var/log/secure یک خط شرط است، نه یک عبارت باقاعدهٔ شکننده.
پیامهای لاگ مرتب دادهای را در خود دارند که دوست ندارید منتشر شود: نشانی IP مبدأ، نام کاربری، رشتهٔ پرسوجو همراه توکن و URL کامل. هر مقصد لاگ را انبار حساس در نظر بگیرید و دسترسی نوشتن روی لاگ سرور را محدود کنید.
محدودیتهای rsyslog
ارزیابی صادقانه از هر متن تبلیغاتی مهمتر است؛ چون انتخاب rsyslog به بهانهٔ نادرست، سامانهای میسازد که نگهداریاش سخت است.
- این یک پلتفرم مشاهدهپذیری نیست. rsyslog خطوط لاگ را جابهجا میکند. متریک ذخیره نمیکند، تریس درخواست نمیگیرد و داشبورد نمیسازد؛ پس در کنار ابزارهایی مثل Prometheus مینشیند و جای آنها را نمیگیرد.
- پیچیدگی پیکربندی سریع بالا میرود. یک خط ارسال ساده است؛ اما بهمحض درگیر شدن صف، زنجیرهٔ اعتماد TLS، محدودیت نرخ و مسیریابی بهازای هر برنامه، پیکربندی تبدیل به یک برنامهٔ واقعی میشود که به بازبینی نیاز دارد.
- UDP طبق طراحی ناپایدار است. این پروتکل هیچ تضمینی برای تحویل نمیدهد و پورت پیشفرض ۵۱۴ روی UDP هر وقت حجم ناگهانی از بافر دریافت بگذرد، پیام دور میریزد.
- نحو قدیمی همچنان وسوسهکننده است. دستورهای قدیمی
$ActionQueueTypeو$AllowedSenderکار میکنند و همین باعث میشود دو سبک پیکربندی در یک فایل قاطی شوند و معلوم نشود کدام واقعاً فعال است. - تکرار پیام را پنهان میکند. rsyslog میتواند پیامهای یکسان را محدود کند؛ این برای یک سرویس پرسروصدا خوب است، اما یعنی یک حملهٔ واقعی که همان بستهٔ خراب را هزار بار میفرستد ممکن است به شکل یک خط دیده شود.
روی یک ماشین تنها، برای بررسی تعاملی journalctl معمولاً ابزار بهتری است؛ چون از پیش نمایهبندی شده و به دیمون جداگانه نیاز ندارد. rsyslog وقتی دست به کار میشود که دیگر سؤال دربارهٔ یک میزبان نباشد و دربارهٔ یک ناوگان باشد.
ارتباط rsyslog با ژورنال systemd
این دو سیستم همپوشانی دارند و درک مرزشان از کار تکراری جلوگیری میکند. rsyslog میتواند ژورنال را از طریق imjournal بخواند؛ یعنی هر دو نما از یک منبع حقیقت تغذیه میشوند.
| پرسش | ابزار مناسبتر |
|---|---|
| در یک ساعت گذشته روی این میزبان چه گذشت؟ | journalctl |
| همهی ۲۰۰ میزبان دیشب چه کردند؟ | rsyslog |
| چطور رویدادهای ژورنال را به SIEM ببرم؟ | rsyslog همراه با imjournal |
| لاگها را روی لینک ناپایدار چطور بفرستم؟ | rsyslog با صف Disk-Assisted |
چون imjournal ژورنال را از آخرین موقعیت خواندهشده بازپخش میکند، با ریاستارت شدن rsyslog هیچ رویدادی گم نمیشود؛ به شرطی که فایل state روی ذخیرهسازی دائمی باشد. حذف آن فایل باعث پخش دوباره از ابتدای ژورنال میشود.
خلاصه
- دیمون
rsyslogهمان برنامهای است که پیامهای لاگ را روی لینوکس میگیرد، فیلتر میکند، بافر میکند و تحویل میدهد. - مسیر خط لوله ثابت است: ماژولهای ورودی به صف اصلی میدهند، رولست فیلتر میکند و صف هر خروجی به ماژولهای خروجی میرسد.
- صف Disk-Assisted تعیینکنندهترین ویژگی آن است، چون قطعی شبکه را جذب میکند و بعداً تخلیه میشود و پیامی از دست نمیدهد.
- در مرکزی کردن لاگ یک ناوگان، مسیریابی چندمقصدی و فیلتر روی فیلد ساختاریافته، rsyslog از گزینههای رقیب بهتر عمل میکند.
- پلتفرم مشاهدهپذیری نیست و بهمحض دخالت TLS، محدودیت نرخ و صفهای متعدد، پیکربندی آن به بازبینی جدی نیاز دارد.
- روی یک میزبان تنها، برای بررسی
journalctlرا ترجیح دهید و کار ناوگان را به rsyslog بسپارید.
برای دستورهایی که این لاگها را در کار روزمره خوانا میکنند، دستورات لاگگیری در لینوکس را ببینید و برای رویکرد مسئلهمحور پیدا کردنشان، راهنمای ذهنی لاگگیری را بخوانید.