تو قسمت دهم از مسیر بلاگ پستهای کوبرنتیز، میریم سراغ مفاهیم فرآیند pod to node و دقیق تر بررسی میکنیم که چجوری اسکجولر تصمیم میگیره که هر کدوم از پادهای ما رو روی کدوم نود کوبرنتیز استقرار بده.
خب یه مروری کنیم پستهای قبلی رو:
- دواپس چیه و چرا لازمه؟ اینجا در مورد دواپس و ضرورت استفاده از آن صحبت کردم.
- مسیر شغلی دواپس اینجا در مورد مسیر شغلی دواپس و موارد پیرامون آن صحبت کردم.
- چطور اپلیکیشن مناسب کلاد آماده کنیم؟ و اینجا توضیح دادم که چطور میتونیم یه اپلیکیشن مناسب کلاد توسعه بدیم.
- چه عمقی از لینوکس برای دواپس لازمه؟ و اینجا توضیح دادم که کدوم موارد لینوکس برای دواپس الزامی هست که اول سراغ اون موارد بریم.
- خودکارش کن، مشکلاتت حل میشه 🙂 در اینجا در مورد اتومیشن و اینکه انسیبل چیه و چه کمکی به ما میکنه صحبت کردم.
- در مسیر دواپس اینبار اجزای اصلی انسیبل تو این پست اجزای انسیبل رو معرفی کردم و آنها را شرح دادم.
- در مسیر دواپس به داکر رسیدم. (قسمت اول) تو این پست داکر رو شروع کردیم و اونو معرفی کردیم.
- در مسیر دواپس اینبار: پشت داکر چه خبره؟ (قسمت دوم) توی این پست در مورد تکنولوژی هایی که داکر ازشون استفاده میکنه توضیح دادیم.
- در مسیر دواپس اینبار: والیوم و نتورک داکر (قسمت سوم) توی این پست در مورد شبکه توی داکر و اینکه چطوری دیتای کانتینر رو میتونیم نگه داریم توضیح دادیم.
- در مسیر دواپس اینبار: داکر فایل ( قسمت چهارم ) توی این پست در مورد اینکه چطور با استفاده از داکر اپلیکیشن مون رو بیلد کنیم و ایمیج بسازیم توضیح دادیم.
- در مسیر دواپس اینبار: کامپوز فایل و داکر کامپوز (قسمت پنجم) توی این پست در مورد اینکه چطور روند دیپلوی کردن سرویسهامون و کانفیگ اونها رو به صورت کد داشته باشیم توضیح دادیم.
- در مسیر دواپس: اینبار داکر سوآرم (قسمت ششم) توی این پست در مورد داکر سوآرم و اینکه چطوری به کمک داکر چنتا سرور رو کلاستر کنیم، توضیح دادیم.
- در مسیر دواپس اینبار: دور و بری های داکر (قسمت هفتم) توی این پست در مورد ابزارهای جانبی که بهمون توی کار با داکر کمک میکنن توضیح دادیم.
- در مسیر دواپس: جمع بندی داکر (قسمت هشتم) توی این پست در مورد امنیت داکر توضیح دادیم و در آخر هم یه سری از بست پرکتیسها و تجربیات خودم رو گفتم.
- تست نوشتن و شروع مسیر CI/CD (قسمت اول) توی این پست انواع تست رو بررسی کردیم و با ابزارهای CI/CD آشنا شدیم و یه مقایسه بین گیتلب و جنکینز داشتیم.
- در مسیر CI/CD گیت رو بررسی میکنیم (قسمت دوم) توی این پست قبل ورود به گیتلب نیاز بود که گیت و ورژن کنترل سیستم ها رو یه بررسی کنیم.
- در مسیر CI/CD شناخت گیتلب (قسمت سوم) توی این پست اجزای گیتلب رو بررسی کردیم و با کامپوننتهای مختلفی که داره بیشتر آشنا شدیم.
- در مسیر CI/CD پایپلاین و رانر گیتلب (قسمت چهارم) توی این پست پایپلاین و رانر گیتلب رو بررسی کردیم.
- در مسیر CI/CD وریبل، گیتآپس و جمعبندی (قسمت پنجم) توی این پست وریبلهای گیتلب رو بررسی کردیم و یه معرفی کوتاه از گیتآپس و آتودواپس کردیم و در انتها یه مقدار تجربههای خودم رو در گیتلب باهاتون به اشتراک گذاشتم.
- مسیر Observability (قسمت اول) توی این پست معرفی observability رو داشتیم و مقایسه اش با مانیتورینگ و یه توضیح مختصر هم در مورد اپنتلهمتری دادیم.
- در مسیر 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 ها توی کوبرنتیز توضیح دادیم.
توصیه میکنم که حتما این پستها رو هم مطالعه کنید. بریم که ادامه بدیم.
مقدمه:
قبلتر دیدیم که اسکجولر پادهایی که جدیدا درست شدن رو بررسی میکنه و برای هرپاد جدیدی که اسکجولر اونو بررسی میکنه، یک نود مناسب پیدا میکنه. در واقع اسکجولر مسئول پیدا کردن بهترین نود برای پاد هست تا روی اون نود ران بشه. اسکجولر این کار رو بر اساس قوانینی که قبلا توضیح دادیم انجام میده در ادامه یه مقدار بیشتر در مورد این فرآیند توضیح میدیم.
راههای مختلفی برای انجام این فرآیند هست اما تمام راه حل هایی که توصیه شده هستند از Label و Selector ها استفاده میکنند برای آسان کردن این فرآیند.
Node Selector Scenario:
سادهترین و توصیهشدهترین روش برای اعمال محدودیت انتخاب نود nodeSelector است.
یک فیلد در PodSpec است که یک Map از جفتهای کلید-مقدار (key-value) را مشخص میکند.
برای اینکه یک پاد واجد شرایط اجرا روی یک نود باشد، نود باید تمام جفتهای کلید-مقداری که در nodeSelector مشخص شده است را به عنوان برچسب (Label) داشته باشد (نود میتواند برچسبهای اضافی دیگری نیز داشته باشد). رایجترین استفاده از nodeSelector شامل یک جفت کلید-مقدار است.
Node Name Scenario:
استفاده از nodeName سادهترین روش برای اعمال محدودیت انتخاب نود است، اما به دلیل محدودیتهایی که دارد معمولاً استفاده نمیشود. nodeName یک فیلد در PodSpec است. اگر این فیلد خالی نباشد، Scheduler پاد را نادیده میگیرد و kubelet در نود مشخصشده سعی میکند پاد را اجرا کند.
بنابراین، اگر nodeName در PodSpec مشخص شده باشد، نسبت به روشهای دیگر برای انتخاب نود اولویت دارد.
Affinity and Anti-affinity Scenario:
تا اینجا متوجه شدیم که اسکجولر میشینه حساب کتاب میکنه که مثلا پاد رو نفرسته جایی که منابع مورد نیازش وجود نداشته باشه و اگه یادتون باشه گفتیم که یه بار فیلترینگ انجام میده که ببینه اصلا روی کدوم نود ها میشه این پاد رو برد و بعدش فرآیند Scoring رو انجام میده که پیدا کنه حالا از بین اینهایی که میشه کدومش بهتر هستند برای این پاد. این مباحث رو تو قسمت اسکجولر توضیح دادم.
آیا اینکه cpu و ram کافی برای اون پاد روی نود باشه کافیه؟ آیا ما میتونیم با جزئیات بیشتری از اسکجولر بخوایم که مقصد پاد رو مشخص کنه؟ مثلا میشه بگیم هرجا یه پاد از backend هست یه پاد از redis هم باشه؟ یا مثلا میتونیم بگیم که تا جای ممکن پادهای فلان سرویس رو پخششون کن که کنار هم توی یک نود نباشن؟
دیدیم که nodeSelector یک روش بسیار ساده برای محدود کردن پادها به نودهایی با برچسبهای خاص فراهم میکند. ویژگی affinity/anti-affinity به طور قابل توجهی انواع محدودیتهایی که میتوانید بیان کنید را گسترش میدهد.
مفهوم affinity شامل دو نوع وابستگی است:
- Node Affinity (وابستگی به نود)
- Inter-Pod Affinity/Anti-Affinity (وابستگی/ضد وابستگی بین پادها)
نوع اول یعنی Node Affinity از نظر مفهومی مشابه nodeSelector است و به شما اجازه میدهد که مشخص کنید پاد شما با توجه به برچسبهای نود، روی کدام نودها واجد شرایط اجرا باشد.
در حال حاضر دو نوع Node Affinity وجود دارد:
۱. RequiredDuringSchedulingIgnoredDuringExecution
این نوع به این معناست که پاد فقط در زمان اسکجولینگ باید قوانین وابستگی را رعایت کند، اما در زمان اجرا نادیده گرفته میشود. یعنی وقتی که پاد دلیور شد روی نود اگر شرط دیگه برقرار نباشه مهم نیست و تنها در زمان اسکجول شدن مهمه که شرط برقرار باشه. دقت کنید اگر اسکجولر نتونه نود مورد نظر رو برای پاد پیدا کنه پاد در حالت pending باقی میمونه تا اسکجولر بتونه نود مورد نظر برای برقراری شرط رو پیدا کنه.
۲. PreferredDuringSchedulingIgnoredDuringExecution
این نوع به Scheduler پیشنهاد میدهد که قوانین وابستگی را رعایت کند، اما تضمینی برای رعایت آنها وجود ندارد. یه جورایی میگیم که بهتره که این پاد مثلا این طوری اسکجول بشه اما اگر شرایط برقرار نبود جای دیگهای هم اومد بالا مشکلی نیست. یه جورایی میگیم بهش که ترجیح میدیم که این طوری پیش بره اما اگر نشد مشکلی نیست.
بخش IgnoredDuringExecution در نام این قوانین نشان میدهد که مشابه nodeSelector، اگر در زمان اجرا برچسبهای یک نود تغییر کنند بهطوری که قوانین وابستگی دیگر رعایت نشوند، پاد همچنان به اجرای خود روی آن نود ادامه میدهد.
مثلا ممکنه پادهایی داشته باشیم که میخوایم فقط روی نودهایی از کلاستر دیپلوی بشن که اونجا gpu هم وجود داشته باشه.
در مثال بالا از required label استفاده شده بنابراین حتما پاد اگر دیپلوی بشه روی نودی که لیبل gpu=true داره، دیپلوی میشه.
در مثال بالا میبینیم که از Preferred labels استفاده شده، یعنی به نوعی ترجیح ما این هست که این پاد روی نودهایی بره که توی zone1 هستند و share اونها به صورت dedicated لیبل زده شده اما اگر به هردلیلی این اتفاق نیافتد کوبرنتیز از اینکه این پاد روی نود دیگری دیپلوی شود جلوگیری نمیکند.
سینتکس جدید Node Affinity از عملگرهای زیر پشتیبانی میکند:
In (در لیست بودن)
این عملگر بررسی میکند که آیا مقدار برچسب نود در لیستی از مقادیر مشخصشده وجود دارد یا نه.
مثال:
key: "environment"
operator: "In"
values: ["production", "staging"]
این تنظیم به پاد اجازه میدهد فقط روی نودهایی اجرا شود که مقدار برچسب environment برابر با production یا staging باشد.
NotIn (در لیست نبودن)
بررسی میکند که مقدار برچسب نود در لیستی از مقادیر مشخصشده نباشد.
مثال:
key: "environment"
operator: "NotIn"
values: ["development", "test"]
این تنظیم به پاد اجازه میدهد روی نودهایی اجرا شود که مقدار برچسب environment برابر با development یا test نباشد.
Exists (وجود داشتن)
بررسی میکند که آیا برچسب مشخصشده روی نود وجود دارد یا خیر.
مثال:
key: "region"
operator: "Exists"
این تنظیم به پاد اجازه میدهد روی نودهایی اجرا شود که برچسب region داشته باشند (بدون توجه به مقدار آن).
DoesNotExist (وجود نداشتن)
بررسی میکند که آیا برچسب مشخصشده روی نود وجود ندارد.
مثال:
key: "region"
operator: "DoesNotExist"
این تنظیم به پاد اجازه میدهد فقط روی نودهایی اجرا شود که برچسب region نداشته باشند.
Gt (بزرگتر بودن)
بررسی میکند که آیا مقدار برچسب نود بزرگتر از مقدار مشخصشده است یا خیر.
مثال:
key: "cpu-count"
operator: "Gt"
values: ["4"]
این تنظیم به پاد اجازه میدهد روی نودهایی اجرا شود که مقدار برچسب cpu-count بیشتر از ۴ باشد.
Lt (کوچکتر بودن)
بررسی میکند که آیا مقدار برچسب نود کوچکتر از مقدار مشخصشده است یا خیر.
مثال:
key: "cpu-count"
operator: "Lt"
values: ["8"]