لاگ در Kubernetes (و نه تنها) امروز: انتظارات و واقعیت

لاگ در Kubernetes (و نه تنها) امروز: انتظارات و واقعیت

سال 2019 است و ما هنوز راه حل استانداردی برای تجمیع گزارش ها در Kubernetes نداریم. در این مقاله، مایلیم با استفاده از مثال هایی از تمرین واقعی، جستجوهای خود، مشکلات پیش آمده و راه حل های آنها را به اشتراک بگذاریم.

با این حال، ابتدا رزرو می کنم که مشتریان مختلف با جمع آوری سیاهه ها چیزهای بسیار متفاوتی را درک می کنند:

  • کسی می خواهد گزارش های امنیتی و حسابرسی را ببیند.
  • کسی - ورود متمرکز کل زیرساخت؛
  • و برای برخی، کافی است فقط گزارش های برنامه را جمع آوری کنید، به عنوان مثال، متعادل کننده ها را حذف کنید.

در زیر برش زیر در مورد نحوه پیاده‌سازی «لیست‌های آرزو» و مشکلاتی که با آن مواجه شده‌ایم آورده شده است.

نظریه: در مورد ابزار ورود به سیستم

پیشینه اجزای سیستم ورود به سیستم

Logging راه درازی را پیموده است، در نتیجه روش‌هایی برای جمع‌آوری و تجزیه و تحلیل سیاهه‌ها ایجاد شده است، چیزی که امروزه از آن استفاده می‌کنیم. در دهه 1950، فرترن یک آنالوگ از جریان های ورودی/خروجی استاندارد را معرفی کرد که به برنامه نویس کمک کرد تا برنامه خود را اشکال زدایی کند. اینها اولین لاگ های کامپیوتری بودند که زندگی برنامه نویسان آن زمان را آسان تر کردند. امروز ما اولین مؤلفه سیستم ورود به سیستم را در آنها می بینیم - منبع یا "تولید کننده" سیاهههای مربوط.

علوم کامپیوتر ثابت نماند: شبکه های کامپیوتری ظاهر شدند، اولین خوشه ها... سیستم های پیچیده ای متشکل از چندین کامپیوتر شروع به کار کردند. اکنون مدیران سیستم مجبور شدند گزارش‌ها را از چندین ماشین جمع‌آوری کنند و در موارد خاص می‌توانستند پیام‌های هسته سیستم‌عامل را در صورت نیاز به بررسی نقص سیستم اضافه کنند. در اوایل دهه 2000 برای توصیف سیستم‌های جمع‌آوری لاگ متمرکز منتشر شد RFC 3164، که remote_syslog را استاندارد کرد. به این ترتیب یکی دیگر از اجزای مهم ظاهر شد: گردآورنده چوب و ذخیره سازی آنها

با افزایش حجم لاگ ها و معرفی گسترده فناوری های وب، این سوال مطرح شد که چه گزارش هایی باید به راحتی به کاربران نشان داده شوند. ابزارهای کنسول ساده (awk/sed/grep) با ابزارهای پیشرفته تری جایگزین شده اند بینندگان ورود به سیستم - جزء سوم

با توجه به افزایش حجم سیاههها، چیز دیگری مشخص شد: سیاههها مورد نیاز هستند، اما نه همه آنها. و سیاهههای مربوط به سطوح مختلف نگهداری نیاز دارند: برخی را می توان در یک روز از دست داد، در حالی که برخی دیگر باید به مدت 5 سال ذخیره شوند. بنابراین، یک مؤلفه برای فیلتر کردن و مسیریابی جریان های داده به سیستم ورود به سیستم اضافه شد - اجازه دهید آن را صدا کنیم. فیلتر کردن.

Storage نیز جهشی بزرگ داشته است: از فایل‌های معمولی به پایگاه‌های داده رابطه‌ای، و سپس به ذخیره‌سازی اسناد محور (به عنوان مثال، Elasticsearch). بنابراین انبار از کلکتور جدا شد.

در نهایت، خود مفهوم یک سیاهه به نوعی جریان انتزاعی از رویدادها گسترش یافته است که ما می خواهیم آن را برای تاریخ حفظ کنیم. یا بهتر است بگوییم در صورت نیاز به تحقیق یا تهیه گزارش تحلیلی...

در نتیجه، در مدت زمان نسبتاً کوتاهی، مجموعه log به یک زیرسیستم مهم تبدیل شده است که به حق می توان آن را یکی از زیربخش های Big Data نامید.

لاگ در Kubernetes (و نه تنها) امروز: انتظارات و واقعیت
اگر روزی روزگاری چاپ‌های معمولی می‌توانست برای یک "سیستم ورود به سیستم" کافی باشد، اکنون وضعیت بسیار تغییر کرده است.

Kubernetes و سیاهههای مربوط

وقتی Kubernetes به زیرساخت آمد، مشکل موجود در جمع آوری سیاهه ها نیز از آن عبور نکرد. از برخی جهات، حتی دردناک‌تر هم شد: مدیریت پلتفرم زیرساخت نه تنها ساده‌تر، بلکه در عین حال پیچیده‌تر نیز بود. بسیاری از سرویس های قدیمی مهاجرت به میکروسرویس ها را آغاز کرده اند. در زمینه گزارش‌ها، این در تعداد فزاینده منابع گزارش، چرخه حیات خاص آنها و نیاز به ردیابی روابط همه اجزای سیستم از طریق گزارش‌ها منعکس می‌شود.

با نگاهی به آینده، می توانم بگویم که اکنون، متأسفانه، هیچ گزینه ثبت استاندارد شده ای برای Kubernetes وجود ندارد که به خوبی با سایرین مقایسه شود. محبوب ترین طرح ها در جامعه به شرح زیر است:

  • کسی پشته را باز می کند EFK (Elasticsearch، Fluentd، Kibana)؛
  • کسی در حال تلاش است که اخیراً منتشر شده است لکی یا استفاده می کند اپراتور ورود به سیستم;
  • ما (و شاید نه تنها ما؟..) من تا حد زیادی از پیشرفت خودم راضی هستم - خانه چوبی...

به عنوان یک قاعده، ما از بسته‌های زیر در خوشه‌های K8s (برای راه‌حل‌های خود میزبان) استفاده می‌کنیم:

با این حال، من روی دستورالعمل های نصب و پیکربندی آنها نمی پردازم. در عوض، من بر کاستی های آنها و نتیجه گیری های جهانی تر در مورد وضعیت سیاهه ها به طور کلی تمرکز خواهم کرد.

با لاگ ها در K8s تمرین کنید

لاگ در Kubernetes (و نه تنها) امروز: انتظارات و واقعیت

"سیاهه های روزانه"، چند نفر از شما آنجا هستید؟..

جمع آوری متمرکز گزارش ها از یک زیرساخت نسبتاً بزرگ به منابع قابل توجهی نیاز دارد که صرف جمع آوری، ذخیره و پردازش سیاهه های مربوط می شود. در حین بهره برداری از پروژه های مختلف با الزامات مختلف و مشکلات عملیاتی ناشی از آنها مواجه بودیم.

بیایید ClickHouse را امتحان کنیم

بیایید به یک ذخیره سازی متمرکز در یک پروژه با برنامه ای نگاه کنیم که به طور کاملاً فعال لاگ تولید می کند: بیش از 5000 خط در ثانیه. بیایید کار با لاگ های او را شروع کنیم و آنها را به ClickHouse اضافه کنیم.

به محض اینکه حداکثر زمان واقعی مورد نیاز باشد، سرور 4 هسته ای با ClickHouse قبلاً روی زیرسیستم دیسک بارگذاری می شود:

لاگ در Kubernetes (و نه تنها) امروز: انتظارات و واقعیت

این نوع بارگذاری به این دلیل است که ما سعی می کنیم هر چه سریعتر در ClickHouse بنویسیم. و پایگاه داده به این با افزایش بار دیسک واکنش نشان می دهد که می تواند باعث خطاهای زیر شود:

DB::Exception: Too many parts (300). Merges are processing significantly slower than inserts

واقعیت این است که جداول MergeTree در ClickHouse (آنها حاوی داده های ورود به سیستم هستند) در طول عملیات نوشتن مشکلات خاص خود را دارند. داده های درج شده در آنها یک پارتیشن موقت ایجاد می کند که سپس با جدول اصلی ادغام می شود. در نتیجه، ضبط بر روی دیسک بسیار سخت است، و همچنین مشمول محدودیتی است که در بالا دریافت کردیم: بیش از 1 پارتیشن فرعی را نمی توان در 300 ثانیه ادغام کرد (در واقع، این 300 درج است. در هر ثانیه).

برای جلوگیری از این رفتار، باید به ClickHouse بنویسد در قطعات بزرگ تا حد امکان و حداکثر 1 بار در هر 2 ثانیه. با این حال، نوشتن به صورت انفجاری بزرگ نشان می دهد که باید کمتر در ClickHouse بنویسیم. این به نوبه خود می تواند منجر به سرریز بافر و از بین رفتن لاگ ها شود. راه حل این است که بافر Fluentd را افزایش دهید، اما پس از آن مصرف حافظه نیز افزایش می یابد.

یادداشت: یکی دیگر از جنبه های مشکل ساز راه حل ما با ClickHouse مربوط به این واقعیت است که پارتیشن بندی در کیس ما (loghouse) از طریق جداول خارجی متصل شده اجرا می شود. جدول ادغام. این منجر به این واقعیت می شود که هنگام نمونه برداری از فواصل زمانی بزرگ، RAM بیش از حد مورد نیاز است، زیرا متاتابل در تمام پارتیشن ها - حتی آنهایی که آشکارا حاوی داده های لازم نیستند - تکرار می شود. با این حال، اکنون می توان با خیال راحت این رویکرد را برای نسخه های فعلی ClickHouse منسوخ اعلام کرد (ج 18.16).

در نتیجه، مشخص می شود که هر پروژه ای منابع کافی برای جمع آوری لاگ ها در زمان واقعی در ClickHouse ندارد (به طور دقیق تر، توزیع آنها مناسب نخواهد بود). علاوه بر این، شما باید استفاده کنید باتری، که بعداً به آن باز خواهیم گشت. موردی که در بالا توضیح داده شد واقعی است. و در آن زمان ما قادر به ارائه راه حل قابل اعتماد و پایداری نبودیم که برای مشتری مناسب باشد و به ما امکان جمع آوری سیاهه ها را با حداقل تاخیر بدهد ...

در مورد Elasticsearch چطور؟

Elasticsearch برای مدیریت بارهای کاری سنگین شناخته شده است. بیایید آن را در همان پروژه امتحان کنیم. اکنون بارگذاری به صورت زیر است:

لاگ در Kubernetes (و نه تنها) امروز: انتظارات و واقعیت

Elasticsearch توانست جریان داده را هضم کند، با این حال، نوشتن چنین حجم هایی در آن به شدت از CPU استفاده می کند. این با سازماندهی یک خوشه تصمیم می گیرد. از نظر فنی، این مشکلی نیست، اما به نظر می رسد که فقط برای راه اندازی سیستم جمع آوری سیاهه ها از حدود 8 هسته استفاده می کنیم و یک جزء اضافی با بارگذاری بالا در سیستم داریم...

خط پایین: این گزینه را می توان توجیه کرد، اما تنها در صورتی که پروژه بزرگ باشد و مدیریت آن آماده باشد که منابع قابل توجهی را برای یک سیستم ثبت متمرکز هزینه کند.

سپس یک سوال طبیعی مطرح می شود:

چه لاگ هایی واقعا مورد نیاز است؟

لاگ در Kubernetes (و نه تنها) امروز: انتظارات و واقعیت بیایید سعی کنیم خود رویکرد را تغییر دهیم: گزارش ها باید به طور همزمان آموزنده باشند و پوشش ندهند همه رویداد در سیستم

فرض کنید یک فروشگاه اینترنتی موفق داریم. چه لاگ ها مهم هستند؟ جمع آوری هر چه بیشتر اطلاعات، به عنوان مثال، از درگاه پرداخت، ایده خوبی است. اما همه گزارش‌های سرویس برش تصویر در کاتالوگ محصول برای ما حیاتی نیستند: فقط خطاها و نظارت پیشرفته کافی است (به عنوان مثال، درصد خطای 500 که این مؤلفه ایجاد می‌کند).

پس به این نتیجه رسیده ایم که ورود به سیستم متمرکز همیشه توجیه پذیر نیست. اغلب مشتری می‌خواهد همه گزارش‌ها را در یک مکان جمع‌آوری کند، اگرچه در واقع، از کل گزارش، فقط 5٪ مشروط پیام‌هایی که برای کسب‌وکار حیاتی هستند مورد نیاز است:

  • گاهی اوقات کافی است، مثلاً، فقط اندازه فهرست کانتینر و جمع کننده خطا (مثلاً Sentry) را پیکربندی کنید.
  • یک اعلان خطا و یک گزارش محلی بزرگ ممکن است اغلب برای بررسی حوادث کافی باشد.
  • ما پروژه‌هایی داشتیم که منحصراً به آزمایش‌های کاربردی و سیستم‌های جمع‌آوری خطا بسنده می‌کردند. توسعه‌دهنده به گزارش‌ها نیازی نداشت - آنها همه چیز را از ردیابی خطا دیدند.

تصویری از زندگی

داستان دیگری می تواند به عنوان مثال خوبی باشد. ما درخواستی از تیم امنیتی یکی از مشتریانمان دریافت کردیم که قبلاً از یک راه حل تجاری استفاده می کرد که مدت ها قبل از معرفی Kubernetes ایجاد شده بود.

لازم بود "دوستان" سیستم جمع آوری گزارش متمرکز با سنسور تشخیص مشکل شرکت - QRadar. این سیستم می تواند لاگ ها را از طریق پروتکل syslog دریافت و از FTP بازیابی کند. با این حال، بلافاصله امکان ادغام آن با افزونه remote_syslog برای fluentd وجود نداشت. (آنطور که مشخص شد، ما تنها نیستیم). مشکلات راه‌اندازی QRadar از طرف تیم امنیتی مشتری بود.

در نتیجه، بخشی از گزارش‌های حیاتی تجاری در FTP QRadar آپلود شد و بخش دیگر از طریق syslog از راه دور مستقیماً از گره‌ها هدایت شد. برای این ما حتی نوشتیم نمودار ساده - شاید به کسی کمک کند مشکل مشابهی را حل کند... به لطف طرح به دست آمده، خود مشتری گزارش های بحرانی را دریافت و تجزیه و تحلیل کرد (با استفاده از ابزارهای مورد علاقه خود)، و ما توانستیم هزینه سیستم ثبت را کاهش دهیم و فقط در هزینه صرفه جویی کنیم. ماه گذشته.

مثال دیگر کاملاً نشان دهنده این است که چه کاری را نباید انجام داد. یکی از مشتریان ما برای پردازش از هر کدام رویدادهای ناشی از کاربر، چند خطی ساخته شده است خروجی بدون ساختار اطلاعات در لاگ همانطور که ممکن است حدس بزنید، چنین گزارش‌هایی هم برای خواندن و هم برای ذخیره کردن بسیار ناخوشایند بودند.

معیارهای لاگ

چنین مثال هایی به این نتیجه می رسند که علاوه بر انتخاب سیستم جمع آوری سیاهه ها، نیاز به خود لاگ ها را نیز طراحی کنید! الزامات اینجا چیست؟

  • گزارش‌ها باید در قالب قابل خواندن توسط ماشین (به عنوان مثال، JSON) باشند.
  • لاگ ها باید فشرده و دارای قابلیت تغییر درجه ثبت به منظور رفع اشکالات احتمالی باشند. در عین حال، در محیط‌های تولیدی باید سیستم‌هایی را با سطح ورود به سیستم اجرا کنید هشدار یا خطا.
  • لاگ ها باید نرمال شوند، یعنی در یک شی log، همه خطوط باید یک نوع فیلد داشته باشند.

گزارش‌های بدون ساختار می‌توانند منجر به مشکلاتی در بارگیری گزارش‌ها در ذخیره‌سازی و توقف کامل پردازش آن‌ها شوند. به عنوان مثال، در اینجا یک مثال با خطای 400 آورده شده است، که بسیاری قطعاً در لاگ های روان با آن مواجه شده اند:

2019-10-29 13:10:43 +0000 [warn]: dump an error event: error_class=Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError error="400 - Rejected by Elasticsearch"

خطا به این معنی است که شما فیلدی را که نوع آن ناپایدار است با یک نقشه برداری آماده به ایندکس ارسال می کنید. ساده ترین مثال یک فیلد در لاگ nginx با یک متغیر است $upstream_status. می تواند شامل یک عدد یا یک رشته باشد. مثلا:

{ "ip": "1.2.3.4", "http_user": "-", "request_id": "17ee8a579e833b5ab9843a0aca10b941", "time": "29/Oct/2019:16:18:57 +0300", "method": "GET", "uri": "/staffs/265.png", "protocol": "HTTP/1.1", "status": "200", "body_size": "906", "referrer": "https://example.com/staff", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36", "request_time": "0.001", "cache_status": "-", "upstream_response_time": "0.001, 0.007", "upstream_addr": "127.0.0.1:9000", "upstream_status": "200", "upstream_response_length": "906", "location": "staff"}
{ "ip": "1.2.3.4", "http_user": "-", "request_id": "47fe42807f2a7d8d5467511d7d553a1b", "time": "29/Oct/2019:16:18:57 +0300", "method": "GET", "uri": "/staff", "protocol": "HTTP/1.1", "status": "200", "body_size": "2984", "referrer": "-", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36", "request_time": "0.010", "cache_status": "-", "upstream_response_time": "0.001, 0.007", "upstream_addr": "10.100.0.10:9000, 10.100.0.11:9000", "upstream_status": "404, 200", "upstream_response_length": "0, 2984", "location": "staff"}

گزارش‌ها نشان می‌دهند که سرور 10.100.0.10 با خطای 404 پاسخ داده و درخواست به ذخیره‌سازی محتوای دیگری ارسال شده است. در نتیجه، مقدار در گزارش‌ها به این صورت شد:

"upstream_response_time": "0.001, 0.007"

این وضعیت آنقدر رایج است که حتی مستحق یک جداگانه است ارجاعات در اسناد.

در مورد قابلیت اطمینان چطور؟

مواقعی وجود دارد که همه لاگ ها بدون استثنا حیاتی هستند. و با این، طرح‌های جمع‌آوری گزارش‌های معمول برای K8s پیشنهادی/مورد بحث در بالا با مشکلاتی مواجه هستند.

به عنوان مثال، fluentd نمی تواند سیاهههای مربوط را از ظروف با عمر کوتاه جمع آوری کند. در یکی از پروژه های ما، کانتینر انتقال پایگاه داده کمتر از 4 ثانیه زنده ماند و سپس حذف شد - طبق حاشیه نویسی مربوطه:

"helm.sh/hook-delete-policy": hook-succeeded

به همین دلیل، گزارش اجرای مهاجرت در حافظه گنجانده نشد. سیاست می تواند در این مورد کمک کند. before-hook-creation.

مثال دیگر چرخش لاگ Docker است. فرض کنید برنامه ای وجود دارد که به طور فعال در لاگ ها می نویسد. در شرایط عادی، ما موفق به پردازش همه گزارش‌ها می‌شویم، اما به محض ظاهر شدن مشکل - به عنوان مثال، همانطور که در بالا با فرمت نادرست توضیح داده شد - پردازش متوقف می‌شود و Docker فایل را می‌چرخاند. نتیجه این است که سیاهههای مربوط به تجارت ممکن است از بین بروند.

به همین دلیل است جدا کردن جریان های گزارش مهم است، تعبیه ارسال با ارزش ترین آنها به طور مستقیم به برنامه برای اطمینان از ایمنی آنها. علاوه بر این، ایجاد برخی از آنها اضافی نخواهد بود "انباشته کننده" سیاهههای مربوط، که می تواند از در دسترس نبودن فضای ذخیره سازی کوتاه و در عین حال ذخیره پیام های مهم جان سالم به در ببرد.

در نهایت، ما نباید این را فراموش کنیم نظارت صحیح بر هر زیرسیستم مهم است. در غیر این صورت، به راحتی می توان در موقعیتی قرار گرفت که در آن fluentd در وضعیتی قرار دارد CrashLoopBackOff و چیزی ارسال نمی کند و این نوید از دست دادن اطلاعات مهم را می دهد.

یافته ها

در این مقاله، ما به راه حل های SaaS مانند Datadog نگاه نمی کنیم. بسیاری از مشکلاتی که در اینجا توضیح داده شد قبلاً توسط شرکت‌های تجاری متخصص در جمع‌آوری سیاهه‌ها به روشی حل شده است، اما همه نمی‌توانند به دلایل مختلف از SaaS استفاده کنند. (اصلی ترین آنها هزینه و مطابقت با 152-FZ است).

جمع آوری لاگ متمرکز در ابتدا کار ساده ای به نظر می رسد، اما اصلاً اینطور نیست. یادآوری این نکته ضروری است که:

  • فقط اجزای حیاتی باید با جزئیات وارد شوند، در حالی که نظارت و جمع آوری خطا را می توان برای سیستم های دیگر پیکربندی کرد.
  • سیاهههای مربوط به تولید باید حداقل نگه داشته شود تا بار غیر ضروری اضافه نشود.
  • گزارش‌ها باید قابل خواندن، نرمال‌سازی و دارای فرمت دقیق باشند.
  • لاگ های واقعا بحرانی باید در یک جریان جداگانه ارسال شوند که باید از اصلی ها جدا شوند.
  • ارزش در نظر گرفتن یک انباشته چوب را دارد که می تواند شما را از انفجار بار زیاد نجات دهد و بار روی انبار را یکنواخت تر کند.

لاگ در Kubernetes (و نه تنها) امروز: انتظارات و واقعیت
این قوانین ساده، اگر در همه جا اعمال شوند، به مدارهایی که در بالا توضیح داده شد اجازه می دهند تا کار کنند - حتی اگر اجزای مهمی (باتری) را از دست داده باشند. اگر به چنین اصولی پایبند نباشید، این کار به راحتی شما و زیرساخت را به یکی دیگر از اجزای بسیار بارگذاری شده (و در عین حال ناکارآمد) سیستم هدایت می کند.

PS

در وبلاگ ما نیز بخوانید:

منبع: www.habr.com

اضافه کردن نظر