جن را بگیر! گرفتن جن در سرور پروداکشن توسط iotop

  • اصلاً چی شد؟

دیشب روی یکی از سرورهای پروداکشنمون یه مرتبه IO رفت بالا و زبیکس ایمیل اخطار داد. رفتم و لاگ‌های nginx و syslog رو خوندم و چیزی دستگیرم نشد. اما متریک‌های زبیکس چیز دیگه‌ای رو نشون می‌داد. مشخص بود که به مدت ۵ دقیقه بخش قابل توجهی از دیسک اشغال شد و دومرتبه آزاد شد… معمولاً این رفتار رو روی ذخیره لاگ‌ها و rotate شدنشون می‌دیدم… شروع کردم به خوندن سایر لاگ‌ها و چک کردن crontab و logrotateها… اما اونجا هم چیزی نبود…

به نظر می‌رسید چیزی غیر از لاگ‌های سیستم باعث به وجود اومدن این پدیده شده… شاید دامپ حافظه، شاید هر چیز دیگه‌ای که تا این لحظه نتونستم پیداش کنم. (شاید هم جن بوده!) اما چیزی که مشخصه اینه که اگه حتی جن بوده باشه، این پدیده که رو سرور اتفاق افتاد، کار یه پروسه بوده! (به سبک خیابانی! ?)

از اونجایی که هیچ ردی از این اتفاق توی سیستم نداشتم به نظرم رسید که باید یه راهی باشه که بشه IO رو تو پروسه‌ها مانیتور کرد و اون رو جایی ذخیره کرد که اگر دوباره این اتفاق افتاد، نپرم رو سرور سریع ssh بزنم و htop بزنم یا iotop بزنم و… که بفهمم کدوم پروسه‌ها بیشترین منبع رو می‌گیرن و…

ها!؟ گفتم iotop؟؟ راستی! iotop این قابلیت رو نداره که از وضعیت پروسه‌ها گزارش بگیریم و یه جایی ذخیره کنیم؟

…و این شروع ماجرا بود!

  • معرفی iotop و قابلیت‌هایی که زمان کاربرد خودش رو نشون داد

خب، iotop دستوریه که پروسه‌هایی رو که بیشترین IO رو داره به صورت تعاملی نشون میده.

نمایی از ابزار iotop در حالت عادی، بدون سوئیچ
نمایی از ابزار iotop در حالت عادی، بدون سوئیچ

اما چطور می‌شه از این ابزار برای گرفتن لاگ استفاده کرد؟ رفتم man page خوندم و دیدم که از این راه میشه:

# iotop -oPtqqqbk > /var/log/iomonitor/status.log

من نیاز داشتم که مشخص بشه هر پروسه تو چه زمانی درخواست IO می‌ده (t) همینطور نیاز داشتم که پروسه‌های اصلی و نه ترد‌های فرزند اون مانیتور بشن (o) و اینکه فقط پروسه‌هایی که IO دارند لیست بشن، نه همه پروسه‌ها (P) و نیاز نداشتم به ازای هر خط گزارش، بهم یادآوری بشه که کدوم ستون مربوط به read و یا write هست (qqq) و باید میزان IO با واحد یکسانی نمایش داده می‌شد (k) و اینکه من نیاز به محیط تعاملی نداشتم که با یک کلید از اون محیط خارج بشم یا خطوطی رو فیلتر کنم، من می‌خوام لاگ تولید کنم و جایی ذخیره کنم (b).

نمایی از ابزار iotop در حالت استفاده از سوئیچ‌های اشاره شده که معادل لاگ‌های ذخیره شده هست
نمایی از ابزار iotop در حالت استفاده از سوئیچ‌های اشاره شده که معادل لاگ‌های ذخیره شده هست
  • حالا اومدیم و چند ماه گذشت و این اتفاق دوباره نیفتاد، باید همینطوری دیسک مصرف کنیم؟

خیر! اینجا از ابزار logrotate استفاده می‌کنیم که لاگ‌ها رو خودش gzip می‌کنه و قدیمی‌ها رو پاک می‌کنه. برای این کار کافیه یه فایل با این محتوا تو مسیر etc/logrotate.d/ ایجاد کنیم.

/var/log/iomonitor/status.log {  
        daily  
        missingok  
        rotate 5  
        compress  
        delaycompress  
}
  • آیا این کافیه؟

خب، کافی که هست، هر زمان که اراده کنم میرم لاگ‌ها رو مرور می‌کنم… و خب، لاگ‌های قدیمی‌تر از ۵ روز هم اتوماتیک پاک میشن… اما وقتی لاگی تولید میشه چرا یه regex ننویسیم و داخل لاگ سرور ذخیره‌ش نکنیم؟ ?

^(?<TIME>[^\ ]*)\ *(?<PID>[\d]*)\ *(?<PRIO>[^\ ]*)\ (?<USER>[^\ ]*)[^\d]*(?<DISKREAD>[\d]*\.[\d]*)[^\d]*(?<DISKWRITE>[\d]*\.[\d]*)[^\d]*(?<SWAPIN>[\d]*\.[\d]*)[^\d]*(?<IO>[\d]*\.[\d]*)[\ \%]*(?<COMMAND>.*)$

اینم از regex. همین دیگه… این هم از داستان سیس‌ادمینی ما تو فرانش. به سایت ما سر بزنید ?