
امروزه اکثر شرکتهای نرمافزاری به نحوی از container ها استفاده میکنند و یا در حال حرکت به سمت استفاده از container ها هستند. تعداد نرمافزارهایی که برای اجرا نیاز به تکنولوژیهای کانتینر دارند روز به روز بیشتر میشود و کمتر برنامهنویسی است که اسم docker یا Kubernetes به گوشش نخورده نباشد. آشنایی به container ها کم کم به پای ثابت آگهیهای شغلی تبدیل شده است. در این مقاله به معرفی containerization و orchestration میپردازیم و برخی از ابزارهای معروف این حوزه را بررسی میکنیم.
به طور کلی کانتینر مجموعهایی ایزوله شده، قابل جابجایی و قابل اجراست که متشکل است از فایل اجرایی برنامه، کتابخانههای سیستمی مورد نیاز و هر فایلی که برای اجرای برنامه مورد نیاز است. یک کانتینر را میتوان به راحتی بین سیستمهای مختلف جابجا کرد و مستقل از محیط اجرا کرد. اما چه نیازی به کانتینر داریم و چرا کانتینرها به وجود آمده اند؟ بهتر است نگاهی به گذشته و فرایند استقرار نرمافزارها در گذشته بیاندازیم.
برای اینکه احتمال رخ دادن خطا در محیط عملیاتی را کمتر کنیم لازم است که محیط توسعه را تا حد امکان با محیط اجرا یک شکل کنیم. اما چرا اینکار باعث کاهش خطا میشود؟ برای مثال فرض کنید که برنامهنویسان نرمافزار را بر روی لپتاپ خود توسعه میدهند پ تست میکنند. به دلیل اینکه سیستمعامل و کتابخوانههای نصب شده در سیستم برنامهنویس با سرور های محیط عملیاتی یکی نیست، ممکن است زمان استقرار برنامه در محیط عملیاتی به خطاهای عجیب و غریب بخوریم. برای اینکه شاهد چنین اتفاقاتی نباشیم دوست داریم که نرمافزار در محیط اجرا و تست شود که تا حد امکان شبیه به محیط عملیاتی باشد.
اما نه تنها سیستمهای برنامهنویسها با سرورها متفاوت است بلکه خود سرورهای محیط عملیاتی نیز ممکن است باهم متفاوت باشند. برای مثال بعضی از سرورها دارای اوبنتو باشند و بعضی دیگر CentOS، بعضی جدیدتر خریداری شده اند و به کلاستر اضافه شده اند و سخت افزار متفاوتی دارند و ... . یا ممکن است سیستمهای محیط staging با production متفاوت باشد. برای مثال تیم امنیت به طور پیوسته سرورها را آپگرید میکند و آخرین پچهای نرمافزاری را نصب میکند و ممکن است فرایند نصب پچ ها در محیط staging همگام با production نباشد.
علاوه بر همهی اینها بر روی هرسرور ممکن است چندین نرمافزار اجرا شوند که هرکدام توسط تیمهای مختلف توسعه داده شده است. یکی کردن محیط توسعه و اجرا در چنین شرایطی بسیار دشوار است.
از طرفی ممکن است برنامههای اجرا شده بر روی یک سرور نیازمندیهای متفاوت و بعضا متناقضی داشته باشند. برای مثال یک نرمافزار به نسخه 5 یک کتابخوانه نیاز دارد اما نرمافزار دیگر به نسخهی 6 آن نیاز دارد. یک نرمافزار به اوبنتو 16 نیاز دارد و دیگری حتما به 18 نیاز دارد. در چنین شرایطی برای اینکه بتوانیم برنامهها را بر روی یک سرور اجرا کنیم لازم است که آنها را ایزوله کرده و به صورت ایزوله شده اجرا کنیم.
قابلیت جابجایی از دیگر نیازمندیهای مهم نرمافزار است. اگر یکی از سرورها خراب بشود لازم است که بتوانیم به سرعت آن را جابجا کرده و در سرور دیگری اجرا کنیم. اگر برنامه به صورت مستقل قابل اجرا باشد و همهی نیازمندیهای خود را داشته باشد اینکار بسیار ساده خواهد بود اما اگر لازم باشد که تمامی نیازمندیها از ابتدا روی سرور جدید نصب بشوند زمان زیادی را از دست خواهیم داد. همچنین اگر بخواهیم نرمافزار را به برنامهنویسان دیگر بدهیم تا اجرا یا تست کنند قابلیت جابجایی یا همان Portability برای ما بسیار مهم خواهد بود. به همین دلیلی نرمافزاری که به صورت ایزوله شده تمامی وابستگیهای مورد نیاز و سازگار با خودش را دارد بسیار ارزشمند است.
نکتهی بسیار مهم دیگر تاثیر پذیری نرمافزارها از یکدیگر و بحث امنیت است. برای مثال اگر یکی از نرمافزارهای درحال اجرا دچار fault شود آیا این fault باید روی بقیهی نرمافزارهای در حال اجرا اثر بگذارد؟ مسلماً خیر. یا اگر یکی از نرمافزارها دچار مشکل امنیتی شود ما دوست داریم محدوهی این حمله تا حد امکان کوچک بوده و بر روی خود سرور یا دیگر نرمافزارهای درحال اجرا اثر نگذارد.
به تمامی دلایل گفته شده در بالا نیاز داریم تا نرمافزارما به صورت ایزوله و مستقل از محل اجرا باشد و قابلیت جابجایی داشته باشد. تمامی مواردی که در بالا گفته شد را میتوان با استفاده از ماشین مجازی هم برطرف نمود، پس مزیت استفاده از کانتینر چیست و فرق آن با ماشین مجازی در چیست؟
هر ماشین مجازی در داخل خودش یک سیستمعامل کامل و مجزا دارد. زمانی که شما چند ماشین مجازی را روی یک سرور اجرا میکنید، چندین سیستمعامل کاملا مجزا بر روی سرور اجرا میشوند که هرکدام هسته و فرایندهای مخصوص به خود را دارند. در زیر این ماشین های مجازی قسمتی به اسم Hypervisor قرار دارد که وظیفهی آن تقسیم سختافزار موجود بین ماشینهای مجازی اجرا شده میباشد.
برنامههایی که درون ماشینمجازی اجرا شده اند فراخوانیهای سیستمی خود را از طریق هستهی سیستمعامل موجود در ماشین مجازی انجام میدهند و آن هسته از طریق Hypervisor دستورات را مستقیما بر روی CPU ی موجود در سرور اجرا میکند. همچنین CPU ی استفاده شده نیز باید قابلیت Virtualization را دارا باشد و بتواند مجازی سازی را به خوبی انجام دهد. در هر ماشین مجازی علاوه بر برنامهی مورد نظر، تمامی فرایندهای یک سیستمعامل به صورت همزمان در حال اجرا هستند و همین باعث میشود که ماشینهای مجازی بسیار سنگینتر و حجیمتر از کانتینر باشند.
از طرف دیگر هر کانتینر چیزی نیست جز فرایندی که بر روی سیستمعامل اصلی سرور درحال اجراست و تنها تفاوت آن با دیگر فرایندها این است که کرنل این فرانید را به صورت ایزوله اجرا کرده است. در واقع کانتینرها همگی از هستهی سیستمعامل موجود استفاده میکنند و این هسته بین تمامی کانتینرها مشترک است. فرایندی که داخل کانتینر در حال اجراست تمامی فراخوانیهای سیستمی خود را از طریق هستهی سیستمعامل سرور انجام میدهد و خبری از سیستمعامل جدیدی در این بین نیست. تنها تفاوت فرایندهای داخل کانیتر این است که هستهی سیستمعامل این فرایندها را به صورت ایزوله اجرا کرده است و برای هرکدام namespace مخصوص به خود را در نظر گرفته است.
چون کانتینرها در داخل خود فایلهای یک سیستمعامل کامل(از جمله هستهی سیستمعامل) را ندارند، به طور چشم گیری نسبت به ماشینهای مجازی سبکتر هستند و به همین دلیل جابجایی آنها آسانتر است. از طرفی چون تمامی فرایندهای داخل هر کانتینر در سیستمعامل اصلی اجرا میشوند، اجرا کردن آنها نیز بسیار سریعتر است. علاوه بر همهی اینها در کانتینرها CPU لازم نیست مجازیسازی انجام بدهد و در کل سربار بسیار کمتر است.
البته ناگفته نماند که از نظر امنیت کانیترها ممکن است ریسک بیشتری داشته باشند چراکه همگی سیستمعامل اصلی سرور را به اشتراک میگذارند و از یک هستهی واحد استفاده میکنند اما در ماشینهای مجازی همهچیز به صورت کامل ایزوله است حتی هستهی سیستمعامل.
اگر سیستم ما از تعداد کمی قسمت مستقل ولی بزرگ و سنگین تشکیل شده باشد استفاده از ماشین مجازی ممکن است توجیه داشته باشد اما هرچقدر تعداد قسمتهای مختلف یک سیستم بیشتر میشود آنها کوچک تر میشوند، استفاده از ماشین مجازی پرهزینهتر و غیرقابل توجیه میشود. باتوجه به مطالب گفته شده در بالا امروزه بسیاری از برنامهنویسان به جای ماشین مجازی از کانتینر استفاده میکنند.
زمانی که شما چندین سرور و مولفهی قابل اجرا دارید(مثل معماری مایکروسرویس)، تعداد دفعاتی که باید استقرار را انجام دهید بسیار بیشتر خواهد شد. همچنین مدیریت تعدادی زیادی کانتینر به مراتب سخت تر خواهد بود. برای مثال ما میخواهیم اگر یکی از سرورها خاموش شد به صورت خودکار نرمافزارهای آن سرور به دیگر سرورها انتقال یابند و با downtime بسیار کمی نرمافزار دوباره قابل استفاده باشد. انجام چنین عملهایی به صورت دستی بسیار سخت است. به همین دلیل سیستمهایی برای Container Orchestration به وجود آمدهاند که به ما در مدیریت و نگهداری کانتینرها کمک میکنند.
در واقع ابزارهای Orchestration به ما این امکان را میدهند که تمرکز خود را بر روی توسعهی محصول بگذاریم و کمتر درگیر زیرساخت باشیم. با استفاده از این ابزارها ما میتوانیم تمامی سختافزارها و زیرساخت را به صورت یکپارچه و به عنوان یک منبع پردازشی نگاه کنیم.
ابزارهای Orchestration به ما کمک میکنند که بین کانتینرهای مختلف load balancing انجام بدهیم تا درخواستها بین کانتینرهای مختلف تقسیم شوند. این ابزارها معمولا برای بروزرسانی و و یا مقایسپذیری نیز امکانات گستردهایی را دارند. یکی دیگر از امکانات بسیار مهم این ابزارها قابلیت های مربوط به تحمل خطا و یا recovery است. این ابزارها میتوانند در صورت بروز خرابی در هر یک از سرورها، آن سرور را به صورت خودکار از کلاستر خارج کرده و برنامهها را بر روی سرور جدیدی انتقال دهند. همچنین میتوانند مولفههای در حال اجرا را به طور پیوسته پایش کنند و در صورتی که هرکدام از آنها قابلیت پیشروی نداشت، آن را دوباره راهاندازی کنند.
داکر یکی از معروفترین ابزارهای تولید و اجرای کانتینر است. قبل از داکر تکنولوژیهای مختلفی برای Containerazion وجود داشت اما داکر اولین ابزاری بود که امکان جابجایی کانتینرها بر روی سیستمهای مختلف را به راحتی فراهم میکرد. همچنین داکر فرایند ساخت کانتینر را بسیار سادهتر میکرد و همهی اینها باعث موفقیت چشمگیر داکر شد. تا حدی که امروزه بسیاری تا اسم از کانتینر میشود داکر را به خاطر میآورند.
ابزار rkt یکی دیگر از تکنولوژیهای مدیریت کانتینر در لینوکس است و به نوعی یکی از جایگزینهای داکر به حساب میآید. بعد از موفقیت داکر گروهی به اسم OCI به وجود آمد و استانداردهایی را برای کانتینرهای لینوکس تدوین کرد. داکر و rkt هردو عضو این مجموعه هستند و از این استانداردها تبعیت میکنند. تمرکز اصلی rkt بر امنیت، ترکیبپذیری و تبعیت از استانداردهاست.
کوبرنتیز معروفترین ابزار Container Orchestration در حال حاضر است که توسط شرکتهای مختلفی در جای جای دنیا استفاده میشود. این ابزار در ابتدا توسط گوگل توسعه داده شده و سپس به صورت OpenSource منتشر شده است. امروزز community بسیار بزرگی از کوبرنتیز پشتیبانی میکنند و ابزار قابل اتکایی به شمار میآید.
کوبرنتیز به شما این امکان را میدهد تا وضعیت مورد نظر خود را از طریق فایل های YAMLیا JSON تعریف کنید(declare). این وظیفهی کوبرنتیز است تا وضعیت را به حالت دلخواه شما درآورد و همانگونه نگهداری کند. در صورت خرابی یا هر اتفاقی کوبرنتیز سعی میکند تا حد امکان خطا را مدیریت کرده و وضعیت را به حالت خواسته شده درآورد.
در کوبرنتیز کوچیکترین واحد قابل استقرار pod نام دارد. هر pod میتواند شامل چندین کانتینر باشد که باهم در ارتباط هستند. این کانتینرها به پورتها و filesystem یکدیگر دسترسی دارند و بین آنها isolation کمتری وجود دارد. به همین دلیل فقط و فقط کانتینرهایی که لازم هست همیشه کنارهم باشند و ارتباط تنگاتنگی باهم دارند را باید در یک pod قرار دهید. اکثر اوقات هر pod شامل یک کانتینر است.
شرکت همروش یکی از شرکتهای معروف در ایران است که به شما کمک میکند کانتینرهای خود را مستقر کنید. این شرکت با ارائهی پلتفرم ابری «دارکوب» به شما اجازه میدهد که کانتینرهای خود را مستقر کنید و منابعی که نیاز دارید را مشخص کنید. همچنین درصورت نیاز میتوانید از سرویسهای آماده مانند پایگاه داده نیز استفاده کنید. این شرکت امکانات مختلفی برای جمعآوری لاگها و پایش را نیز در اختبار شما قرار میدهد.
ابرآروان از دیگر ارائه دهندههای سرویس کانتیر ابری است که به شما کمک میکند کانتینرهای خود را بر فضای ابری اجرا و مدیریت کنید. علاوه بر امکان اجرا، ابرآروان به شما یک private repo برای نگهداری کانتینرها و مدیریت آنها نیز میدهد.
این مطلب، بخشی از تمرینهای درس معماری نرمافزار در دانشگاه شهیدبهشتی است.
Kubernetes In Action Book Edition 1