امروزه هر پروژه نرمافزاری دارای یک معماری خاص است حتی اگر به معماری آن فکر نشده باشد. معماری این پروژههای نرمافزاری بخشهای مهم و ارتباط بین این بخشها در این نرمافزارها را نشان میدهد. یک دسته از این معماریها موسوم به معماری میکروسرویس هستند که با استفاده از سرویسهای مستقل، امروزه تقسیم کردن بخشهای مختلف یک سیستم یا نرمافزار بزرگ به واحدهای نسبتاً مستقل و قابل توسعه و تست، آسانتر از گذشته کردهاند. داکر ابزاری پرکاربرد است که در معماری میکروسرویس برای جدا کردن واحدهای مستقل با استفاده از مفهوم کانتینرها، تحولی در این راستا ایجاد کرد. این داکرها ممکن است در یک پروژه، پیچیده و زیاد شوند و به همین خاطر ابزارهایی مانند Docker Swarm و Kubernetes نیز وجود دارند که مدیریت داکرها را سادهتر میکنند. در این پروژه ابتدا به بررسی مفاهیم حوزه معماری میکروسرویس و سپس به معرفی و دستهبندی دو ابزار معروفی که در حوزه مدیریت داکرها ذکر شد خواهیم پرداخت.
در این پروژه قرار است ابزارها و فناوریهای مرتبط با معماریهای مبتنی بر میکروسرویس را بررسی و تحلیل کنیم. قبل از این بررسی و تحلیل، ابتدا باید به عنوان پروژه بپردازیم. باید بدانیم هر کدام از واژههای استفاده شده در عنوان پروژه چه معنایی میدهد. باید بدانیم معماریهای مبتنی بر میکروسرویس و کانتینرها به چه معناست. بنابراین برخی واژههای مهمی که در عنوان پروژه از آن استفاده شده را تعریف میکنیم. به ترتیب تعاریف معماری نرمافزار، میکروسرویس و کانتینر را مرور میکنیم. پس از آن میتوانیم بفهمیم معماری میکروسرویس چیست و مزایا و معایب آن را بدانیم. سپس به سمت ابزارها و فناوریها مانند داکر و کوبرنتیز میرویم و رویکرد آنها برای پاسخ به برخی دغدغهها و چالشهایی که در معماری میکروسرویس یا به طور کلی در معماری نرمافزار داریم را بررسی میکنیم.
در قدم اول معماری نرمافزار را باید تعریف کنیم. معماری نرمافزار به گونههای مختلفی قابل تعریف است. میتوان معماری نرمافزار را توصیف واحدهای اصلی سیستم و روابط آنها و فعل و انفعال آنها با یکدیگر دانست. البته معماری را فهم و درک مشترک توسعهدهندگان و طراحان از طراحی سیستم را نیز تعریف میکنند. تصمیمهایی که باید در معماری نرمافزار گرفته شوند، ممکن است هر چه دیرتر گرفته شوند هزینههای بیشتری برای تیم توسعه و طراحی نرمافزار به بار آورد.
میکروسرویس به واحدهای مستقل نرمافزار گفته میشود که هر کدام از این واحدها میتوانند توسعه و استقرار (deploy) داده شوند. این واحدها که از این به بعد به آنها میکروسرویس میگوییم میتوانند از طریق رابطها با میکروسرویسهای دیگر میتوانند ارتباط برقرار کنند. یک میکروسرویس قابلیت نگهداری آسانتری نسبت به یک نرمافزار بزرگ با واحدهای متعدد دارد و میتواند مستقلاً توسط تعدادی از توسعهدهندگان سیستم، توسعه و تست شود و سپس استقرار یابد.
یک کانتینر (Container)، واحد استانداردی از نرمافزار است که کد و وابستگیهای آن را به صورت یک بسته (Package) در خود دارد و به صورت ایزوله قابل استفاده است. بنابراین میتوان یک میکروسرویس را در یک یا تعدادی کانتینر توسعه داد و تست و نگهداری کرد. همچنین جابجایی کانتینرها بین محیطهای مختلف و زیرساختهای گوناگون بسیار آسان است. امروزه داکر (Docker) برای استفاده از قابلیتهای کانتینرها استفاده میشود.
کانتینرها یک بسته نرمافزاری شامل وابستگیهای خود بودند که میتوانستند مستقلاً اجرا شوند. تفاوت اصلی کانتینرها با ماشین مجازی در اینجاست که تعداد زیادی کانتینر میتوانند در یک سیستم عامل و یک ماشین اجرا شوند در حالی که ماشین مجازی یک سیستم عامل کامل مخصوص به خود را دارد. در واقع کانتینرهایی که در یک سیستمعامل در حال اجرا شدن هستند هسته (Kernel) سیستم عامل را با دیگر کانتینرهای موجود در آن ماشین، به اشتراک میگذارند. این کانتینرها به صورت فنی مانند پروسههای مستقل از هم در فضای کاربر (user space) هستند. کانتینرها فضای بسیار کمی در حد چند ده مگابایت به خود اختصاص میدهند که در مقایسه با فضایی که VM ها نیاز دارند بسیار کمتر است. از طرف دیگر VM ها یک ماشین مجازی هستند که هر یک سیستمعامل مخصوص به خود را دارند و در واقع این قابلیت را به توسعهدهندگان میدهند که یک سرور فیزیکی خود را به چندین سرور مجازی تبدیل کنند. هر یک از VM ها یک سیستمعامل کامل مخصوص به خود، اپلیکیشن و وابستگیها و کتابخانههای مخصوص به خود را دارند. VM ها فضایی در حد چندین گیگابایت نیاز دارند.
در این بخش معماری نرمافزار مبتنی بر میکروسرویس و کانتینر را تعریف و بررسی میکنیم. بهتر است ابتدا بدانیم تفاوت آن با مدلهای مرسوم دیگر و معماریهای رایجی که استفاده میشود چیست. در ابتدا معماری یکتکه و سپس معماری میکروسرویس را مرور و بررسی میکنیم. در نهایت تفاوتها و مزایا و معایب آنها را میبینیم.
در معماری یکتکه، نرمافزار و سیستم مبتنی بر کدبیس واحد است. در معماری مونولیتیک یا یکتکه، سیستم معمولاً به سه بخش back-end، front-end و دیتابیس تقسیم میشود. در این معماری، این سه بخش سیستم ما را میسازند. در این معماری، این بخشها به صورت یکپارچه توسعه داده میشوند و معمولاً هر چه سیستم بزرگتر شود کدبیس نیز بزرگتر و پیچیدهتر شده و توسعهدهندگان باید قسمتهای بیشتری از سیستم را تغییر دهند. در این معماری ممکن است که به صورت منطقی، ماژولهای مختلفی داشته باشیم اما کل نرمافزار به عنوان یک بسته و یکتکه، استقرار مییابد.
در معماری میکروسرویس، سیستم یا نرمافزار به تعدادی میکروسرویس کوچکتر تقسیم میشود که با یکدیگر در ارتباط هستند. این ارتباط میتواند مثلاً با استفاده از پروتکلهای معروفی مانند HTTP انجام شود. در معماری میکروسرویس، هر میکروسرویس بخشی از سیستم را در خود دارد که باید تا حد امکان یک وظیفه مهم را انجام دهد. هر میکروسرویس به طور مستقل میتواند قابل توسعه باشد و با پیچیدهشدن یکی از آنها، بقیه میکروسرویسها لزوماً پیچیده نخواهند شد. هر میکروسرویس میتواند خود به صورت یک معماری یکتکه باشد.
در این بخش به تفاوتهای معماریهای یکتکه و میکروسرویس و مزایا و معایب آنها نسبت به یکدیگر خواهیم پرداخت.
همانطور که از تعاریف هر کدام از معماریها یکتکه و میکروسرویس مشخص است، معماری یکتکه به صورت سنتی استفاده میشود و برای سیستمهای نه چندان پیچیدهای که بخشهای متعددی ندارند، قابل استفاده است اما معماری میکروسرویس برای سیستمهای پیچیده و بزرگی که دارای بخشهای مختلف هستند که هر یک وظیفه و نقش مهمی در سیستم ایفا میکنند، بسیار مفیدتر است.
در معماری یکتکه، یک دیتابیس واحد وجود دارد که هر بخش با آن دیتابیس ارتباط برقرار میکند اما در معماری میکروسرویس، هر میکروسرویس معمولاً یک دیتابیس مربوط به خود را داراست. در ادامه به صورت موردی تفاوتهای این دو نوع معماری را به صورت خلاصه بیان میکنیم.
معماری یکتکه
معماری میکروسرویس
مزایای معماری یکتکه را مرور میکنیم. معماری یکتکه، به صورت آسان قابل توسعه است. استقرار آن معمولاً به صورت واحد قابل انجام است و نیازی به استقرار سرویسهای متعدد نیست. همچنین چون معمولاً به صورت یکپارچه است پس نیازمند پروتکل و راهی برای اتصال سرویسهای گوناگون با هم نیست و ممکن است سرعت بالاتری داشته باشد.
اکنون به معایب معماری یکتکه میپردازیم. در معماری یکتکه، اگر سیستم بزرگ و پیچیده شود و بخواهیم سیستم را مقیاسپذیر (Scalable) کنیم، کار سخت و دشواری داریم و مدیریت یک واحد کلی و مقیاسپذیری آن بسیار مشکلزا خواهد بود. به ازای هر تغییر در سیستم باید کل سیستم استقرار یابد. همچنین احتمالاً توسعهدهندگان به کل سیستم مسلط نخواهند بود و این ممکن است به بخشهای منطقی معماری یکتکه آسیب یا مشکل یا باگ وارد کند. همچنین این معماری برای تیمهای چابک، مناسب نخواهد بود چون کل سیستم در یک واحد قابل استقرار خلاصه شده و نمیتوان به خوبی تقسیم وظایف انجام داد و مشخص کرد که یک بخش از سیستم دقیقاً یک کار انجام دهد.
معماری میکروسرویس مشکلات معماری یکتکه را تا حد خوبی میتواند حل کند. میکروسرویس کردن معماری، مزایایی مانند کوچکتر شدن واحدهای نرمافزار، مشخص بودن وظیفه هر میکروسرویس برای انجام یک کار واحد، کمک به چابک بودن تیمهای توسعه با انتساب هر میکروسرویس به یک تیم نسبتاً مستقل، استقرار مستقل هر میکروسرویس بدون نگرانی زیاد نسبت به در حال توسعه بودن بقیه میکروسرویسها، مقیاسپذیری بالای سیستم، رفع خطا، باگ و مشکلات آسانتر و داشتن باگهای کمتر، امکان پایش (Monitoring) راحتتر، بخشهای مستقل و قابل فهمتر و کوچکتر و به همین دلیل سریعتر و بسیاری موراد دیگر را دارد.
البته معماری میکروسرویس ممکن است معایب و مشکلاتی مانند پیچیدهکردن سیستم، مدیریت ارتباط میکروسرویسها، توانایی استقرار هر میکروسرویس و پیچیدگی مستقل بودن این استقرار، کاهش سرعت نسبت به معماری یکتکه به علت ارتباط درونی میکروسرویسها با هم، استفاده از زبانهای برنامهنویسی و تکنولوژیهای مختلف در هر میکروسرویس، سینککردن داده و دیتابیسهای مختلف که توسط هر میکروسرویس استفاده میشود، مدیریت پیچیده کانتینرها و مواردی دیگر از این دست را به سیستم تحمیل کند.
تاکنون فهمیدیم که معماری نرمافزار و معماریهای یکتکه و میکروسرویس به چه معنا هستند. سوالی که باید اکنون از خود بپرسیم این است که استفاده از معماری میکروسرویس همیشه به تیم نرمافزار و به خود نرمافزار کمک میکند؟ اگر همیشه کمک نمیکند در چه شرایطی معماری میکروسرویس برای ما نامناسب خواهد بود؟
برای پاسخ به این سوال (و اکثر سوالهایی که در این حوزه پرسیده میشود!) باید بگوییم که بستگی دارد که میخواهیم نرمافزار و معماری آن چگونه باشد. اگر تیم نرمافزاری کوچکی داریم و نرمافزارمان به گونهای است که قرار نیست مقیاس زیادی داشته باشد و توسط تیمهای مختلف توسعه داده شود، میتوانیم از معماری یکتکه استفاده کنیم و نگران نباشیم. چه بسا اگر با چنین نرمافزاری به سمت میکروسرویس برویم، صرفاً به پیچیدگیهای معماری خود افزوده باشیم و سودی برایمان نداشته باشد.
اگر نرمافزاری داریم که قرار است توسعهپذیری آسانتر داشته باشد و توسط تیمهای مختلف با حداقل وابستگی به یکدیگر و با هدف مینیمم کردن مشکلات عدم تطابق تیمهای مختلف با یکدیگر باشد و هر یک از واحدهای سیستم را بتوانیم بشکنیم و به صورت جدا توسعه و تولید و استقرار دهیم، پس بهتر است به سمت معماری میکروسرویس برویم.
میکروسرویسها چالشهایی را حل میکنند و چالشهایی را به نرمافزار تحمیل میکنند. طبق این مقاله تا سال 2016 توزیع چالشهای مهمی که در 33 مقالهای که بررسی شده و مربوط به میکروسرویس بودهاند در نمودار زیر آمده است.
در نمودار بالا در هر قطعه تعداد مقالههای مرتبط با هر کلیدواژه در هر قطاع از نمودار دایرهای نوشته شده است.
طبق نمودار بالا، مواردی مانند ارتباط و یکپارچگی، کارایی، تحمل خطا، امنیت، لاگ و پایش و همچنین عملیاتهای توسعه از جمله مهمترین چالشها و کلیدواژههای مرتبط با میکروسرویس هستند که در ادامه نیز بعضی از آنها را بررسی میکنیم.
از زمانی که معماری میکروسرویس محبوب شد، شرکتهای زیادی در ایران و سطح جهان به سمت آن مهاجرت کردند تا بتوانند چالشهایی که قبلاً با آن دست و پنجه نرم میکردند را تا حد خوبی برطرف کنند. به عنوان مثال اضافه کردن یک ویژگی جدید و مقیاسپذیری نرمافزار همیشه جزو مشکلات بزرگ این شرکتها بود که باعث میشد با حذف صورت مسئله یا استفاده از راه حلهای سختتر مشکل خود را حل کنند. موارد زیر از جمله چالشهایی است که معماری میکروسرویس میتواند تا حد خوبی آنها را به چالشهایی کمخطرتر تبدیل کند:
حرکت به سمت معماری میکروسرویس همیشه فقط سود نخواهد داشت. قطعاً در این مسیر باید منتظر چالشها و عواقب آن نیز بود. به عنوان مثال فرض کنید که قرار باشد داده در تمام میکروسرویسها با هم تطابق داشته باشد. اگر در معماری خود عملیات و انتقال پیام غیر همزمان (async) داشته باشیم، این تطابق و پایداری داده بسیار چالش برانگیز خواهد شد. چالشهایی که معماری میکروسرویس به نرمافزار اضافه میکند به طور خلاصه شامل موارد زیر است:
ویژگیهای کیفی (Quality attributes) برخی ویژگیهای غیرکارکردی نرمافزار مانند دردسترس بودن (Availability)، کارایی (Performance)، مقیاسپذیری (Scalability)، امنیت (Security) و چنین مواردی هستند که معمولاً با ارائه یک معیار میتوان بررسی کرد که تا چه میزان در معماری سیستم به آنها توجه شده و باید به این نیازمندیها پاسخ داده شود. حرکت از سوی معماری یکتکه به سوی معماری میکروسرویس، معمولاً باعث میشود به علت جدا بودن میکروسرویسها، مقیاسپذیری سیستم آسانتر شود، امنیت هر میکروسرویس افزایش یابد و قابلیت نگهداری سیستم نیز بهبود پیدا کند. ممکن است کمی سرعت پاسخگویی کاهش یابد اما اگر معماری میکروسرویس درست چیده شود و به تاکتیکهای درست توجه شود سرعت پاسخگویی افزایش نیز خواهد یافت. آزمونپذیری و قابلیت استقرار سیستم بهتر میشود چون هر میکروسرویس را میتوان جداگانه تست کرد و استقرار داد. دسترسیپذیری سیستم نیز اگر معماری با تاکتیکهای مناسب مانند استفاده از سرورهای پشتیبان طراحی شود، بهبود خواهد یافت.
در تیمهای نرمافزاری، امروزه معماری میکروسرویس بسیار محبوب شده است. با توجه به اینکه هر میکروسرویس میتواند به صورت مستقل، تولید، تست، نصب و مستقر شود، وابستگی میان تیمهای مختلف موجود در یک سامانه به حداقل میرسد و به چابک (Agile) بودن تیمهای نرمافزاری کمک میشود. دیگر تیمها به صورت سنتی معطل بقیه تیمهای نرمافزاری برای توسعه نخواهند ماند و دغدغه آنها معمولاً میکروسرویسی است که با آن سروکار دارند نه میکروسرویسهای دیگر. هر تیم نرمافزاری مرتبط با سیستم که معمولاً با یک یا حداکثر چند میکروسرویس کار میکنند، متخصصان DevOps مربوط به خود را خواهد داشت تا فرایندهای CI/CD (یکپارچهسازی و تحویل مستمر) را نیز بهبود ببخشند. مواردی که ذکر شد قبل از وجود معماری میکروسرویس بسیار سختتر و در واقع تا حد خوبی نشدنی بود.
یکی از مسائلی که برای تیمهای نرمافزاری و معماران نرمافزار در هنگام مهاجرت به سمت میکروسرویسها وجود دارد نحوه طراحی و یا استخراج هر میکروسرویس است. به تصویر زیر توجه کنید:
در تصویر بالا همان طور که مشخص است کد و واحدهایی که می توانند به طور غیروابسته و با وظیفهای مستقل کار کنند از هم جدا شدهاند. همچنین از API Gateway برای ارسال درخواست کلاینتها به سمت هر سرویس استفاده شده است. همچنین برای هر سرویس، دیتابیس مخصوص به خود استفاده شده است. پس میتوان از این مثال نتیجه گرفت که یکی از روشها به این صورت است که ابتدا کد و بخشهایی که میتوانند وظیفه مستقل و واحدی داشته باشند از هم جدا شوند، سپس برای هر کدام از آنها دیتابیس مجزا درنظر گرفته شود و دیتابیس قبلی به چند دیتابیس به ازای هر میکروسرویس تبدیل شود، اگر واحدهایی که تبدیل به میکروسرویس تبدیل میشوند وابستگی یا ارتباطی با هم دارند برای آن راه حلی مانند استفاده از پروتکل ارتباطی بین دو سرویس طراحی شود، سپس یک API Gateway در بین کلاینت و میکروسرویسها و واحدها قرار داده شود. همچنین در تمامی این مراحل باید به محدودههایی که برای هر میکروسرویس درنظر داریم (Bounded Context) کاملاً توجه شود. نکته مهم دیگر این است که باید بدانیم که میکروسرویسهای ما لزوماً به شکل بالا نخواهند بود و شاید در شبکههای مختلف وجود داشته باشند. در این حالت باید یک رجیستری سرویس (Service Registry) داشته باشیم که در واقع یک دیتابیس است که شامل آدرس شبکه از هر یک از میکروسرویسهای نرمافزار است. با گذراندن این مراحل میتوانیم تا حدودی اطمینان یابیم که میکروسرویسها را درست استخراج کردهایم.
همچنین برای طراحی میکروسرویسها، یکی از روشهای محبوب دیگر، استفاده از مفهوم DDD یاDomain Driven Design است. در روش DDD که ابتدا توسط Eric Evans معرفی شد باید متخصصانی به دامنه نرمافزار و سیستمی که قرار است توسعه داده شود تا حد خوبی مسلط باشند. در این رابطه خواندن این مقاله توصیه میشود.
برای استفاده از معماری میکروسرویس، یکی از مهمترین ابزارها و مفاهیم، داکر است که برای ساخت کانتینرها جهت استفاده در هر میکروسرویس به کار میرود. در ادامه بررسی میکنیم که داکر چیست.
میخواهیم کمی فنیتر به سمت بررسی معماری میکروسرویس برویم. چون گفتیم که امروزه داکر برای ایجاد و استفاده از کانتینرها استفاده میشود ابتدا باید بدانیم داکر در این حوزه چه نقشی دارد و چه ابزاری است.
داکر ابزاری است که امکان استفاده از کانتینرها (که قبلاً آن را تعریف کردیم) را به تیمهای نرمافزاری میدهد. در واقع داکر میتواند برای ما کانتینرهایی بسازد و اجرا کند تا ما بتوانیم کدها و وابستگیهای واحدهای نرمافزاری خود را به صورت مستقل و ایزوله از محیط سیستم، تولید و تست کنیم و سپس استقرار دهیم و در نهایت بتوانیم به راحتی داکرهای خود را با کمترین درد (!) یعنی بدون نیاز به نصب تعداد زیادی کتابخانه و وابستگی برای هر محیط، بین واحدها و سرورهای مختلف جابجا کنیم. البته باید بدانیم تا قبل از داکر نیز مفهوم کانتینرها وجود داشته اما این داکر بود که ساختن، جابجایی و اجرای کانتینرها را بسیار آسانتر از گذشته کرد.
اکنون میخواهیم پا را کمی فراتر بگذاریم. میخواهیم بدانیم خود داکر چه قسمتهایی دارد و چگونه از این قسمتها برای ساخت یک کانتینر بهره میبرد. پس باید با اجزای مختلف یک داکر آشنا شویم.
موتور داکر (Docker Engine)
موتور داکر قسمتی از داکر است که کانتینر را میسازد و اجرا میکند. این موتور به صورت یک اپلیکیشن کلاینت و سرور کار میکند یعنی یک سرور میسازد که یک پروسه که به آن daemon میگوییم (و در ادامه در موردش توضیح میدهیم) را پیوسته اجرا میکند و کلاینت که مثلاً میتواند در ترمینال کاربر باشد به وسیله REST API ای که داکر دارد میتواند با آن daemon ارتباط برقرار کند.
پروسه پسزمینه (Docker Daemon)
داکر یک پروسه پسزمینه موسوم به daemon دارد که به ریکوئستهای فرستاده شده از کلاینت داکر، گوش میدهد و اجزای مختلف داکر را مدیریت میکند. همچنین یک daemon میتواند با daemon های دیگر در ارتباط باشد.
کلاینت داکر (Docker Client)
کلاینت داکر، راه اصلی برای استفاده از داکر توسط کاربرها است. در واقع وقتی کاربر، دستور docker run را در ترمینال مینویسد، کلاینت داکر به سمت daemon درخواستی برای ارتباط با آن میفرستد. کلاینت داکر میتواند با چند daemon در ارتباط باشد.
ایمیج داکر (Docker Image)
ایمیج داکر در واقع یک فایل و قالب غیرقابل تغییر است که شامل دستورهایی است برای ساخت یک کانتینر داکر استفاده میشود. برای ساختن یک ایمیج نیاز است که یک فایل داکر (Docker file) بسازیم که در آن توسط یک سینتکس ساده میتوانیم مراحل و دستورات ساخت آن ایمیج و نحوه اجرا شدن آن را بنویسیم.
حال میتوانیم بفهمیم که یک کانتینر در داکر در واقع یک نسخه قابل اجرا از یک ایمیج است. با استفاده از API ای که داکر ارائه میدهد، میتوان یک کانتینر را ساخت، start یا stop کرد، آن را منتقل نمود و یا آن را حذف کرد.
رجیستری داکر (Docker Registry)
رجیستری داکر، جایی است که ایمیجهای داکر را ذخیره میکند. مثلاً Docker Hub یک رجیستری عمومی است که دارای داکر ایمیجهای متعددی است و هر کاربری میتواند از آن استفاده کند. البته میتوان رجیستریهای خصوصی نیز تعریف کرد.
اگر تعداد داکرها برای توسعه یک نرمافزار افزایش یابد چگونه آنها را میخواهیم مدیریت و سازماندهی کنیم؟ به صورت دستی آنها را میخواهیم استقرار دهیم؟ اگر داکرهای مختلفی که در نرمافزار خود استفاده کردهایم با داکرهای دیگر در ارتباط بودند چه؟ اگر در مقیاس بزرگ، تعداد بسیار زیادی داکر داشتیم آیا میخواهیم دستی مدیریت آنها را انجام دهیم یا ابزارهایی جهت خودکارسازی مدیریت داکرها وجود دارد؟ اینجاست که ابزارهای سازماندهی کانتینرها (Container Orchestration) برای خودکارسازی این فرایند کمک بسیاری به ما میکنند.
ابزارهای مدیریت و سازماندهی کانتینرها که لغت "ارکستراسیون کانتینرها" نیز برای آنها به کار میرود، فرایند مدیریت، مقیاسپذیری، نگهداری و استقرار کانتینرها را خودکارسازی میکنند. این ابزارها میتوانند برای زمانبندی اجرا و ساخت کانتینرها، نحوه اختصاص منابع به آنها، میزان سلامت (health) هر یک از کانتینرها، نحوه مقیاسپذیری آنها و راهاندازی دوباره هر کانتینر، نحوه توزیع بار (load balancing)، کاهش خطای انسانی در مدیریت داکرها، سادهسازی عملیاتهای مرتبط با داکرها و بسیاری موارد دیگر به کار روند.
دو مورد از مهمترین و پرکاربردترین ابزارهای ارکستراسیون کانتینرها Docker Swarm و Kubernetes هستند. در ادامه در مورد هر یک از این دو ابزار صحبت میکنیم و بررسی میکنیم هر کدام از چه مکانیزمها و روشهایی برای مدیریت استفاده از کانتینرها استفاده میکنند و ارتباط آن با معماری میکروسرویس را بررسی خواهیم کرد.
ابزار kubernetes یا کوبرنتیز یک ابزار متنباز برای ارکستراسیون کانتینرهاست که با استفاده از آن میتوان کانتینرها را مدیریت و اسکیل کرد و استقرار داد. این ابزار توسط گوگل ساخته شده است. به این ابزار به صورت مخفف k8s نیز گفته میشود.
این ابزار وقتی به کار میآید که تعداد زیادی کانتینر که ممکن است در سرورهای مختلفی مستقر باشند داریم و میخواهیم آنها را مدیریت کنیم. به این منظور کوبرنتیز به توسعهدهندگان و متخصصان دوآپس، یک API ارائه میدهد که میتوان با آن کنترل کرد که هر کانتینر چگونه و کجا ران شود.
این ابزار با توجه به میزان منابع موجود در هر سرور و اینکه هر کانتینر به چه میزان از منابع احتیاج دارد، آنها را بین سرورها و ماشینهای مجازی مختلف پخش و پیکربندی میکند. به گروهی از کانتینرها در ادبیات کوبرنتیس، نام pod داده میشود که در واقع واحد عملیاتی برای کوبرنتیز است یعنی کوبرنتیز یک یا چند کانتینر که در یک pod قرار گرفتهاست را میتواند اجرا کند نه اینکه کانتینر به صورت مستقل اجرا شود. کانتینرهای داخل یک pod میتوانند منابع (resource) ها را با هم به اشتراک بگذارند. البته باید توجه کرد که کماکان کانتینرهای داخل یک pod از دیگر pod ها ایزوله هستند. همچنین ابزار کوبرنتیز میتواند به صورت اتوماتیک مواردی مانند میزان منابع اختصاص دادهشده و load سرورها را track کند. همچنین میتواند بر این اساس عملیات پیکربندی کانتینرها را انجام دهد. همچنین کوبرنتیز به صورت اتوماتیک میزان سلامت هر منبع را چک میکند و میتواند مثلا با restart کردن یک کانتینر سلامت آن را به حالت عادی برگرداند.
در کوبرنتیز، یک گره یا node در واقع یک ماشین مجازی یا فیزیکی است که کوبرنتیز روی آن نصب شده است. در واقع یک یک گره جایی است که کانتینرهای داخل pod ها توسط کوبرنتیز اجرا میشوند.
یک خوشه (Cluster) مجموعهای از چندین گره است که در کنار هم قرار میگیرند. معمولاً اگر یکی از گرهها دچار مشکل شود، نرمافزار از طریق بقیه گرهها همچنان میتواند بدون مشکل کار کند.
این ابزار نیز مانند kubernetes برای مدیریت و پیکربندی و اسکیل container هاست. در واقع Docker Swarm یک گروه از VM ها یا ماشینهای فیزیکی است که روی هر کدام از آنها چندین داکر (کانتینر) اجرا میشود. این ابزار برای موتور داکر نوشته شده و API مخصوص به خود را دارد. تمام امکاناتی که در کانتینرهای داکر وجود دارد در Swarm نیز قابل استفاده است. در مقایسه با کوبرنتیز، کاستوم کردن موارد مختلف در Swarm ممکن است مشکل زا باشد و همه امکانات کوبرنتیز را نیز ندارد.
یک گره، یک نمونه از موتور داکر است. دو نوع گره در Swarm وجود داره. گره مدیر (Manager Node) که در واقع واحدهای کاری که به آن وظیفه (Task) گفته میشود را به گرههای کارگر اختصاص میدهد. گره کارگر (Worker Node) وظایف را از گره مدیر دریافت میکند و به اجرای آن وظایف میپردازد.
یک سرویس در واقع وظایفی است که روی یک گره مدیر یا کارگر باید اجرا شود.
این مطلب، بخشی از تمرینهای درس معماری نرمافزار در دانشگاه شهیدبهشتی است.