توی قسمت دوم مسیر Observability میریم سراغ استک ELK و بعد از معرفیش چنتا از کامپوننتهاش رو هم بررسی میکنیم و احتمالا یه پست دیگه هم هفته بعد داریم ازش که بقیه کامپوننتهایی که میمونه رو بررسی کنیم.

استک ELK:
- چیه و چرا لازمه
در واقع ELK سرنام سه تا ابزار Elasticsearch و Logstash و Kibana هست. که به ترتیب برای سرچ و آنالیز لاگها، جمع آوری دیتا از سورس های مختلف و پردازش اونها، و نهایتا نمایش دیتا به صورت چارت و گراف استفاده میشن که در ادامه هر کامپوننت این استک رو بیشتر بررسی میکنیم. مجموعهی این ابزارها در کنار یه سری ابزار دیگه راهحلی رو برای Observability سیستمها و سرویسها حتی در ابعاد شرکتهای خیلی بزرگ ارائه میدهد. این ابزارها بر پایه یک تکنولوژی هست و خیلی با هم به خوبی ادغام شدن. این استک به صورت کامل و جامع میتونه راهحلی به شما ارائه کنه که بتونید به خوبی تمام شهودی که نیاز دارید رو بدست بیارید. البته بگم خودم یوزرش نیستم و دلایل کافی هم برای این موضوع دارم. اما به شدت به سازمانهای بزرگی که میخواهند یه راه حل جامع برای این کار داشته باشند توصیه میکنم. فقط دقت کنید که استک سنگین و گرونی هست برای همین باید توان تامین موارد مورد نیاز آن را داشته باشید.
کامپوننتهای استک زیبا و بزرگ ELK:
Elasticsearch:
الستیکسرچ یک موتور جستجو و آنالیز قدرتمند برای انواع دیتای متنی، عددی، جغرافیایی و … به صورت توزیع شده هست و متن باز توسعه یافته. دیتای الستیک هم میتونه به صورت ساختارمند باشه و هم میتونه اصطلاحا بدون استراکچر باشه. الستیک بر پایه Apache Lucene ساخته شده و اولین بار سال ۲۰۱۰ منتشر شد. الستیک ابزار مرکزی استک ELK هست و به داشتن ویژگیهایی مثل REST API ساده، ذات دیستریبیوتد، سرعت بالا و قابلیت اسکیل پذیری بالا، معروف هست. به زبون دیگه قلب این استک است. امکان سرچ به صورت real-time و یا پیدا کردن الگوها و ترند و پترنها از کنار هم قراردادن دیتا یا حتی استفاده از هوش مصنوعی برای این کار، از قابلیتهای دیگهی الستیک هست. این ابزار به صورت کلی هرجایی که نیاز باشه سرچ کنیم، توصیه میشه! یعنی بهترین گزینهی ما برای پوشش نیاز سرچ میتونیم بگیم هست و واقعا تو این کار کامل هست.

همانطور که گفتیم به خوبی میتونیم این دیتابیس رو توزیع کنیم و براش راهکار وجود داره و نودهای الستیک میتونند هرکدوم یک role مشخص داشته باشند که در ادامه انواع اونها رو بررسی میکنیم:

Master Nodes:
معمولا توی الستیک همهی نودها master-eligible هستن به صورت دیفالت. در هر لحظه فقط یک نود مستر باید توی کلاستر باشه که طی یک فرآیند اجماع و رای گیری که بین نودهای master-eligible انجام میشه، انتخاب میشه. نود مستر وظایفی مثل ساخت و حذف ایندکسها، ترک کردن نودها و اختصاص دادن شاردها به اونها رو بر عهده داره. در ادامه مسیرمون با مفهوم ایندکس و شارد آشنا میشیم.
Data Nodes:
نودهای دیتا مسئول نگهداری دیتا و انجام عملیات مرتبط با دیتا هستن. مواردی مثل:
- CRUD operations
- Indexing
- Search
- aggregations
همهی نودها به صورت دیفالت نقش دیتا نود رو دارند و برای کم کردن لود این نودها میتونید اونها رو کانفیگ کنید که فقط سرچ و اگریگیشن رو انجام بدن.
Coordinating Nodes:
این نودها در واقع کار لود بالانس رو به صورت هوشمند انجام میدن و درخواستها رو به صورت مستقیم سمت نودهای دیتا و مستر میفرستن. این نودها کمک میکنن تا لود روی نود مستر یا یکی از نودهای دیتا بالا نره که نقش بسیار مهمی هست توی کلاستر های بزرگ. به نودهای کوردینیت بعضا client node هم میگن و به صورت دیفالت همهی نودها این نقش رو هم دارند.
Ingest Nodes:
این نودها کمک میکنن تا پیش پردازش روی دیتا انجام بشه. داکیومنتها قبل از اینکه تبدیل به ایندکس بشن نیاز به یک پردازشی دارند که کار نودهای ingest هست به همین دلیل به اونها نود transform هم میگن چون دیتا توی اونها از داکیومنت تبدیل میشه به ایندکس. بعضی سازمان ها از نودهای ingest به جای Logstash برای پایپ کردن و پردازش دیتا استفاده میکنن. به صورت دیفالت همه ی نود ها نقش ingest رو هم دارن.

Hot data Node:
نمیتونیم همه دیتای لاگ و … رو برای همیشه و با اهمیت یکسان بخواهیم نگه داریم کارمون خیلی سخت میشه. اینجا سر و کله مفهوم Tiering پیدا میشه، میاییم یه سری مرحله برای دیتامون تعریف میکنیم که به مرور با گذشت زمان دیتاهایی که دیگه ازشون زیاد استفاده نمیکنیم یا کمتر مورد استفاده هستند رو به سمت این ببریم که حذفشون کنیم یا روی نودهایی ذخیره کنیم که ارزونتر هستند، مشابه این مفهوم رو توی آبجکت استورجها هم داریم. حالا هات دیتا نودها در واقع نودهایی هستن که دیتای ما رو که اخیرا ایجاد شده و بیشترین سرچ رو اون هست رو نگهداری میکنه. این نودها نیاز دارند که سرعت خواندن و نوشتن بالایی داشته باشند به همین علت استفاده از دیسک های SSD توی اونها متداول هست. معمولا نودهای هات ما نودهای گرونتری هستند که ظرفیت کمی دارند اما سرعت خیلی بالایی به ما میدهند.
Warm data Node:
توی Tier بعدی دیتا به نود warm منتقل میشه. دیتایی که توی نودهای هات ایندکس شده رو و معمولا مرتبط با هفتههای اخیر هست، وارد نود وارم میشه و اینجا هم امکان آپدیت دیتا هست اما معمولا به دفعات کمتری نسبت به زمانی که در نود هات بود. یه جورایی دیتاهایی که کمتر از دیتاهای هات دیده میشند اینجا منتقل میشوند و نگهداری میشن. نودهای این tier ارزونتر از نودهای هات هستند و معمولا هاردهایی که دارند ارزونتر است و مثلا هاردهای SAS دارند. ظرفیتی بالاتر در عین حال سرعت کمتری که نسبت به ssdها دارند.
Cold data Node:
توی Tier بعدی که cold هست معمولا دیتایی قرار میگیره که دیگه به شکل معمول نیاز نداریم روی اون سرچ بزنیم، گرچه همچنان امکان اینکه سرچ رو انجام بدیم داریم. توی نودهای کولد معمولا از دیسک های با هزینه کمتر و ظرفیت بیشتر استفاده میشه. مثلا اینجا میریم سراغ دیسکهای HDD که ظرفیتهای خیلی بالایی در اختیار ما قرار میدهند ولی سرعتشون زیاد مطلوب نیست ماهم داریم دیتایی روی آنها قرار میدیم که انتظار داریم نسبت به دیتاهای دیگه کمتر سرچ بشه و سراغشون بریم.
Frozen data Node:
و نهایتا توی Tier بعدی که frozen هست دیگه بقیه طول عمر خودش رو سپری میکنه. معمولا دیتای توی این نودها به ندرت کوئری در موردشون هست.
این مدل ذخیرهسازی و چرخهی Tiering که براتون گفتم برای مواقعی هست که ما باید دیتاها رو برای مدت زیادی نگه داریم و عملا هیچ وقت قرار نیست اونها رو پاک کنیم و عمرشون همیشگی هست. این چرخه آنقدر کارا و خوبه که میتواند در انتهای عمر خود به سمت Tapeها برسه که ظرفیتهای خیلی خیلی زیادی رو با سرعت کمی داریم و مثلا طول عمر دیتا روی آنها به بیش از ۳۰ سال ممکنه برسه. میبینید برای همهی این مسیر راهکار وجود داره و به خوبی میتونیم با الستیک سرچ کامل آن را پوشش بدیم. الله اکبر

دوتا کانسپت اولیه هم توی الستیک داریم که خوبه باهاش آشنا باشید:
Index:
ایندکسهای الستیک دسته بندی های لاجیکی از داکیومنتها هستن که میتونیم اونها رو معادل table دیتابیسها توی دنیای دیتابیسهای رابطهای بدونیم.
Documents:
داکیومنتها توی الستیک سرچ آبجکتها به فرمت JSON هستن که توی ایندکسهای الستیک ذخیره میشن و میتونیم اونها رو واحد پایهای استورج بدونیم. داکیومنتها رو میشه معادل یک ردیف از جدول توی دنیای دیتابیس های رابطه ای دونست.

Logstash:
لاگ استش کامپوننتی هست که نقش صف رو توی کلاستر بازی میکنه و ورودیها از سورسهای مختلف اول سمت لاگ استش میان اونجا از یه سری فیلتر رد میشن و نهایتا خروجی لاگ استش به پلاگینهای خروجی فرستاده میشه برای قرارگیری در کلاستر الستیک سرچ. خب حالا که فهمیدیم دیتا قرار هست توی لاگ استش parsing براش اتفاق بیافته، با دوتا فیلتر مرسوم هم آشنا بشیم: اولی dissect هست که دیتا رو بر اساس یه سری جداکننده یا دلیمیتر فیلتر میکنه و دومی هم grok هست که بر پایه regular expression ها کار میکند. به طور کلی گروک ابزار قدرتمندتری هست و میتونه دیتا متنوعتری رو هندل کنه اما به تبع آن ریسورس بیشتری رو هم استفاده میکنه و میتونه کندتر باشه مخصوصا اگه به خوبی کانفیگ و آپتیمایز نشه.

موقع ساخت یک کانفیگ گروک یه تعداد پترن استاندارد مشخص وجود داره که معمولا استفاده میشن در ادامه یه لیستی از اونها رو براتون میارم:
- WORD – pattern matching a single word
- NUMBER – pattern matching a positive or negative integer or floating point number
- POSINT – pattern matching a positive integer
- IP – pattern matching an IPv4 or IPv6 IP address
- NOTSPACE – pattern matching anything that is not a space
- SPACE – pattern matching any number of consecutive spaces
- DATA – pattern matching a limited amount of any kind of data
- GREEDYDATA – pattern matching all remaining data
یه نمونه Grok پترن رو در ادامه قرار میدم که بتونیم باهاش ارتباط بهتری برقرار کنیم.

در ادامه یک خط از لاگ سرویس traefik رو میبینیم که میخواهیم اون رو با استفاده از grok بررسی و پارسش کنیم.
۱۹۲.۱۶۸.۱۰۰.۲ – – [۱۶/Aug/2024:15:16:46 +0000] “GET /service/rest/v1/user-telemetry/events/rte/v2/kc?s=AP-YFGMCGUNNIFB-2-1723821391781-23826591&p=AP-YFGMCGUNNIFB-2 HTTP/1.0” 200 0 “-” “-” 7750 “repo@docker” “http://172.18.0.3:8081” 289ms
پترن استاندارد برای فیلتر آن به صورت زیر میشه.
%{IPV4:client_ip} - - \[%{HTTPDATE:timestamp}\] "%{WORD:method} %{URIPATHPARAM:request} HTTP/%{NUMBER:http_version}" %{NUMBER:status_code} %{NUMBER:bytes} "-" "-" %{NUMBER:request_time:int} "%{DATA:backend_name}" "%{URI:backend_url}" %{NUMBER:request_duration:int}ms
توضیح هر کدوم از قسمتهای پترن مورد استفاده شده رو در ادامه میتونیم ببینیم.
%{IPV4:client_ip}: Matches the client IP address (۱۹۲.۱۶۸.۱۰۰.۲).-: Matches the hyphen (-) for both the ident and user fields, which are placeholders.%{HTTPDATE:timestamp}: Matches the timestamp ([۱۶/Aug/2024:15:16:46 +0000]).%{WORD:method}: Matches the HTTP method (GET).%{URIPATHPARAM:request}: Matches the request path and query parameters (/service/rest/v1/user-telemetry/events/rte/v2/kc?s=AP-YFGMCGUNNIFB-2-1723821391781-23826591&p=AP-YFGMCGUNNIFB-2).%{NUMBER:http_version}: Matches the HTTP version (۱.۰).%{NUMBER:status_code}: Matches the HTTP status code (۲۰۰).%{NUMBER:bytes}: Matches the size of the response in bytes (۰)."-": Matches the referer and user-agent, which are placeholders.%{NUMBER:request_time:int}: Matches the request time in milliseconds (۷۷۵۰).%{DATA:backend_name}: Matches the backend name (repo@docker).%{URI:backend_url}: Matches the backend URL (http://172.18.0.3:8081).%{NUMBER:request_duration:int}ms: Matches the request duration in milliseconds (289ms).
و در انتها هم کانفیگ لاگاستش ما برای تحلیل این لاگ به صورت زیر خواهد بود.
filter {
grok {
match => { "message" => "%{IPV4:client_ip} - - \[%{HTTPDATE:timestamp}\] \"%{WORD:method} %{URIPATHPARAM:request} HTTP/%{NUMBER:http_version}\" %{NUMBER:status_code} %{NUMBER:bytes} \"-\" \"-\" %{NUMBER:request_time:int} \"%{DATA:backend_name}\" \"%{URI:backend_url}\" %{NUMBER:request_duration:int}ms" }
}
}

همان طور که در مراحل بالا دیدید لاگی که میتونیست برای ما نامفهوم باشه و به صورت raw لاگ داخل الستیک سرچ ذخیره بشه الان به صورت کامل پارس شده و میتونیم روی هر کدوم از قسمتهای آن سرچ کنیم. مثلا اون کلاینتهایی که استتوس کد ۳۰۰ یا ۴۰۰ دارن رو جدا کنیم و پیداشون کنیم.
این میشه یه آشنایی اولیه با استک ELK توی پست بعدی سعی میکنیم بقیه کامپوننت ها رو هم تکمیل کنیم و مسیر Observability رو ادامه بدیم و کنار هم یاد بگیریم.
مراقب خودتون باشید.
- دواپس چیه و چرا لازمه؟ اینجا در مورد دواپس و ضرورت استفاده از آن صحبت کردم.
- چطور اپلیکیشن مناسب کلاد آماده کنیم؟ و اینجا توضیح دادم که چطور میتونیم یه اپلیکیشن مناسب کلاد توسعه بدیم.
- چه عمقی از لینوکس برای دواپس لازمه؟ و اینجا توضیح دادم که کدوم موارد لینوکس برای دواپس الزامی هست که اول سراغ اون موارد بریم.
- خودکارش کن,مشکلاتت حل میشه در اینجا در مورد اتومیشن و اینکه انسیبل چیه و چه کمکی به ما میکنه صحبت کردم.
- در مسیر دواپس اینبار اجزای اصلی انسیبل تو این پست اجزای انسیبل رو معرفی کردم و آنها را شرح دادم.
- در مسیر دواپس به داکر رسیدیم (قسمت اول) تو این پست داکر رو شروع کردیم و اونو معرفی کردیم.
- در مسیر دواپس اینبار: پشت داکر چه خبره؟ (قسمت دوم) توی این پست در مورد تکنولوژی هایی که داکر ازشون استفاده میکنه توضیح دادیم.
- تست نوشتن و شروع مسیر CI/CD (قسمت اول) توی این پست انواع تست رو بررسی کردیم و با ابزارهای CI/CD آشنا شدیم و یه مقایسه بین گیتلب و جنکینز داشتیم.
- در مسیر CI/CD گیت رو بررسی میکنیم (قسمت دوم) توی این پست قبل ورود به گیتلب نیاز بود که گیت و ورژن کنترل سیستم ها رو یه بررسی کنیم.
- در مسیر CI/CD شناخت گیتلب (قسمت سوم) توی این پست اجزای گیتلب رو بررسی کردیم و با کامپوننتهای مختلفی که داره بیشتر آشنا شدیم.
- در مسیر CI/CD پایپلاین و رانر گیتلب (قسمت چهارم) توی این پست پایپلاین و رانر گیتلب رو بررسی کردیم.
- در مسیر CI/CD وریبل، گیتآپس و جمعبندی (قسمت پنجم) توی این پست وریبلهای گیتلب رو بررسی کردیم و یه معرفی کوتاه از گیتآپس و آتودواپس کردیم و در انتها یه مقدار تجربههای خودم رو در گیتلب باهاتون به اشتراک گذاشتم.
- در مسیر Observability، الک (قسمت دوم) توی این پست استک قدرتمند ELK رو بررسی کردیم.
- در مسیر Observability، جمع بندی استک الک (قسمت سوم) توی این پست بقیه کامپوننتهای استک الک رو بررسی کردیم و fluentd و fluentbit رو مقایسه کردیم و نهایتا یه معرفی هم روی opensearch داشتیم.
- در مسیر Observability، استک پرومتئوس (قسمت چهارم) توی این پست یه معرفی اولیه داشتیم روی استک پرومتئوس.
- در مسیر Observability، استک پرومتئوس (قسمت پنجم) توی این پست یه مقدار کامپوننت های استک پرومتئوس رو بیشتر بررسی کردیم.
- در مسیر Observability، استک ویکتوریا (قسمت ششم) توی این پست استک ویکتوریا رو معرفی کردیم و سعی کردیم با پرومتئوس مقایسهاش کنیم.
- در مسیر Observability، میمیر (قسمت هفتم) توی این پست در مورد ابزار میمیر از ابزارهای گرافانا توضیح دادیم و کاربردش رو بررسی کردیم.
- در مسیر Observability، لوکی (قسمت هشتم) توی این پست در مورد ابزار گرافانا برای مدیریت لاگ یعنی لوکی توضیح دادیم و آخرشم یه معرفی کوتاه رو graylog داشتیم.
- در مسیر Observability، تمپو (قسمت نهم) توی این پست در مورد تریسینگ توضیح دادیم و گرافانا تمپو رو بررسی کردیم و یه معرفی کوتاه روی Jaeger داشتیم
- در مسیر Observability، گرافانا (قسمت دهم) توی این پست در مورد گرافانا و HA کردنش و همچنین یه سری از ابزارهاش مثل alloy , incident, on-call توضیح دادیم.
- آغاز مسیر کوبر (قسمت اول) تو این قدم به معرفی ابزارهای ارکستریشن پرداختیم و مدارک کوبرنتیز رو بررسی کردیم.
- کوبر سینگل ( قسمت دوم ) توی این قدم در مورد kubectl , kubeconfig توضیح دادیم و تعدادی ابزار رو معرفی کردیم که به کمک اونها میتونیم یک کوبرنتیز دمهدستی واسه تستهامون داشته باشیم.
- کامپوننتهای کوبر ( قسمت سوم ) توی این پست کامپوننتهای مختلف کوبرنتیز رو بررسی کردیم و اجزای نودهای مستر و ورکر رو دونه دونه بررسی کردیم و توضیح دادیم.
- پادها و مدیریت اونها در کوبرنتیز (قسمت چهارم) توی این پست در مورد پاد توی کوبرنتیز توضیح دادیم و موارد مربوط به اون رو بررسی کردیم.
- ورکلودهای کوبر و مدیریت منابع کوبر (قسمت پنجم) توی این پست در مورد namespaceها توی کوبر توضیح دادیم و انواع ورکلود کوبر رو بررسی کردیم.
- اگه لازم شد کوبر خودش گنده میشه! ( قسمت ششم ) توی این پست در مورد سه نوع ورکلود مرتبط با scaling به صورت خودکار در کوبرنتیز توضیح دادیم.
- نتورک کوبر (قسمت هفتم) توی این قسمت انواع سرویس توی کوبرنتیز رو بررسی کردیم و در مورد مفاهیم اینگرس و نتورک پالیسی توضیح دادیم.
- استورج کوبرنتیز (قسمت هشتم) توی این قسمت در مورد انواع استورج توی کوبرنتیز توضیح دادیم و مفاهیم PV و PVC و Storage Class رو بررسی کردیم.
- پراب، ریکوئست و لیمیت (قسمت نهم) توی این قسمت موارد مربوط به محدود کردن منابع کانتینر توی کوبرنتیز رو بررسی کردیم و در مورد انواع probe ها توی کوبرنتیز توضیح دادیم.
- پاد تو نود (قسمت دهم) توی این قسمت درمورد فرآیند انتقال پاد به نود مناسب مفاهیم پیشرفتهتری مثل affinity و anti-affinity و taint و toleration رو بررسی کردیم.
- اولویت پاد و امنیت (قسمت یازدهم) توی این قسمت در مورد تعیین اولویت برای پادها و جنبههای مختلف امنیت در کوبرنتیز توضیح دادیم.
- کنترل دسترسی به کوبر (قسمت دوازدهم) توی این قسمت در مورد مراحل دسترسی به api کوبرنتیز صحبت کردیم و بعدش مفاهیمی مثل سرویس اکانت رو توضیح دادیم.
- دیزاین کلاستر (قسمت سیزدهم) توی این قسمت در مورد طراحی و دیزاین یک کلاستر و روشهای مختلفی که داره توضیح دادیم و همچنین تفاوت روشهای مختلف تقسیم منابع در کلاسترها را بررسی کردیم.
- مالتی تننسی در کوبر (قسمت چهاردهم) توی این قسمت چالشهای مربوط به داشتن چند مستاجر بر روی کلاستر کوبرنتیز توضیح دادیم.
- هلم (قسمت پانزدهم) توی این قسمت پکیج منیجر معروف کوبرنتیز یعنی Helm رو بررسی کردیم و در موردش ویژگیها و کاربردهاش توضیح دادیم.
- سی آر دی و اُپراتور (قسمت شانزدهم) توی این قسمت در مورد اینکه چطوری یه ریسورس کاستوم شده به کلاستر اضافه کنیم توضیح دادیم و مفهوم اُپراتور رو توی کوبر بررسی کردیم.
- نصب کلاستر با kubeadm (قسمت هفدهم) توی این قسمت قدم به قدم نحوه نصب یک کلاستر کوبرنتیز رو با استفاده از ابزار kubeadm توضیح دادیم.
- نصب کلاستر با kubespray (قسمت هجدهم) توی این قسمت نحوه نصب کلاستر با یه پروژه خیلی خوب به نام کیوب اسپری که یه انسیبل خفن برای ستاپ کلاستر رائه میده رو توضیح دادیم.
- نصب کلاستر با rancher (قسمت نوزدهم) توی این قسمت توضیح دادیم که چطور با استفاده از ابزار RKE یک کلاستر کوبرنتیز راهاندازی کنیم.


