یک ریبیلد معمولی nginx در هفتهی گذشته، مدرکی را پاک کرد که نمیدانستیم بهش نیاز داریم. فیکس فقط دو خط بود، ولی فهمیدن اینکه بهش نیاز داریم بیشتر از حد لازم طول کشید.
چیزی که متوجه شدیم
هنگام بررسی آمار Google Analytics برای ترافیک ارگانیک، یک چیز عجیب به چشم خورد: تقریباً یک چهارم سشنهای کانال «Direct» روی آدرس /customer/login?returnTo=/payment/<plan>/<period> فرود میآمدند، برای تقریباً همهی پلنهای قیمتگذاری ما، نه فقط دو یا سه تا از آنها. هر بار همان اثرانگشت مرورگر: مرورگر ناشناس، دسکتاپ، یک کشور خاص. تعامل صفر روی تکتکشان.
این رفتار یک مشتری که دارد پلنها را نگاه میکند نیست. این یک اسکریپت است که دارد همهی آدرسهای خرید قابلکشف را یکییکی بررسی میکند، تقریباً حتماً با استخراج مستقیم از همان صفحهی قیمتگذاری خودمان.
مدرک از قبل نابود شده بود
رفتیم سراغ لاگ access نجینکس تا IP منبع را پیدا کنیم و هیچچیزی نبود. کانتینر چند روز قبل برای یک فیکس نامرتبط ریبیلد شده بود، و access_log به یک فایل داخل کانتینر اشاره میکرد نه stdout. ریبیلد آن را کاملاً پاک کرده بود. docker logs هیچچیزی نشان نمیداد، چون چیزی روی stdout نبود که نشان بدهد. پایپلاین لاگی که از قبل داشتیم و خروجی کانتینرها را به یک مخزن لاگ مرکزی میفرستاد، حتی یک خط از این ماجرا را ندیده بود، چون آن پایپلاین فقط چیزی را جمعآوری میکند که کانتینرها روی stdout و stderr مینویسند.
آدرس IP بات از بین رفته. دیگر راهی برای برگرداندنش نیست.
فیکس
access_log /dev/stdout main;
error_log /dev/stderr warn;nginx به /dev/stdout و /dev/stderr مثل فایلهای معمولی نگاه میکند که میتواند رویشان بنویسد، پس این یک یکپارچهسازی خاص نیست. همان خطوط لاگی که قبلاً داخل یک فایل مینشستند، حالا از طریق خروجی استاندارد کانتینر عبور میکنند، همان چیزی که سیستم ارسال لاگ ما از قبل از تمام کانتینرهای دیگرمان میخواند.
درس واقعی
خودِ بات چیز جالبی نبود. بررسی کمسرعت آدرسهای عمومی قیمتگذاری به تنهایی تهدید بزرگی نیست. چیزی که مهم بود این بود که ما یک استک مانیتورینگ داشتیم که کامل به نظر میرسید، درحالیکه یک کانتینر بیسروصدا از آن بیرون مانده بود، چون کانفیگ پایهاش هنوز مثل ده سال پیش روی یک سرور فیزیکی، پیشفرضش نوشتن فایل لاگ بود. اگر آن کانتینر ماه بعد دوباره ریبیلد شود، هر کاری آنوقت انجام بدهد، واقعاً میتوانیم ببینیمش.
اگر nginx را داخل Docker اجرا میکنید، ارزش دارد دایرکتیوهای access_log و error_log خودتان را چک کنید. یک استک مانیتورینگ فقط بهاندازهی کانتینرهایی کامل است که واقعاً رویش مینویسند.
این شکاف را هنگام دنبال کردن یک ناهنجاری در آنالیتیکس پیدا کردیم که شرحش در یک چهارم ترافیک «Direct» ما یک بات بود آمده است.
پرسشهای متداول
چرا nginx داخل داکر باید لاگ را روی stdout بنویسد؟
چون ابزارهای لاگ کانتینر فقط stdout و stderr را میبینند. اگر access_log به فایلی داخل کانتینر اشاره کند، docker logs چیزی نشان نمیدهد، ابزار ارسال لاگ هرگز آن را جمع نمیکند و با بازسازی کانتینر فایل پاک میشود. نوشتن access_log روی /dev/stdout و error_log روی /dev/stderr همان خطها را از مسیر استاندارد لاگ کانتینر عبور میدهد.
لاگ nginx را چطور به stdout بفرستم؟
دو دستور را در تنظیمات nginx بگذارید: access_log /dev/stdout main; و error_log /dev/stderr warn;. nginx با /dev/stdout و /dev/stderr مثل فایل معمولی رفتار میکند، پس افزونه یا یکپارچگی خاصی لازم نیست و docker logs و هر ابزار ارسال لاگ که خروجی کانتینر را میخواند، همهٔ درخواستها را میبیند.
با بازسازی کانتینر، فایلهای لاگ داخل آن چه میشوند؟
از بین میروند. فایلی که در فایلسیستم خود کانتینر نوشته شده با ساخته شدن دوبارهٔ کانتینر ناپدید میشود، مگر روی یک volume متصل باشد. ما همینطور نشانی IP رباتی را که همهٔ لینکهای پرداخت صفحهٔ قیمت ما را میپیمود از دست دادیم: کانتینر چند روز قبل برای اصلاحی نامرتبط بازسازی شده بود.


