در بخش Containerization با کانتینرها و مزایای آنها آشنا شدیم. با ورود کانتینرها، استقرار نرمافزارها بیش از گذشته ساده و سریعتر شد. این اتفاق باعث توسعه سریعتر نرمافزارها و افزایش انتظار کاربران از سرویسهای پر استفاده شد. با افزایش این انتظارات دیگر اجرای نرمافزارها در یک محیط آماده و ایزوله کافی نبود. حالا از آنها انتظار میرفت که بدون تاخیر و قطعی کار کرده، همواره و زیر فشار بالا به درخواستهای کاربران پاسخ داده و سریع بهروز رسانی شوند. برای پاسخ دادن به این نیازمندی، دیگر اجرای نرمافزارها بر روی یک سرور و رها کردن آنها روش کارآمدی نبود و به همین خاطر نیاز بود ابزاری بوجود بیاید که نرمافزارها را بر روی فضای ابری مدیریت کند.
کوبرنیتیز
گفتیم که کانتینرها با ورود داکر، تبدیل به روش استاندارد استقرار نرمافزارها شدند، اما با پیچیدهتر شدن نیازمندیهای بازار، کانتینرها به تنهایی نمیتوانستند پاسخگوی نیازها باشند و نیاز به یک ابزار برای مدیریت آنها در شرایط پیچیده حس میشد. ابزارهایی که از دل این نیاز بوجود آمدند، Orchestratorها بودند.
یکی از این Orchestratorها کوبرنیتیز بود.
ابزارهای دیگری مانند Docker Swarm، Hashicorp Nomad و Apache Mesos نیز وجود دارند که شبیه به کوبرنیتیز عمل میکنند. اما کوبرنیتیز از سایر این ابزارها محبوبتر است.
برای آشنایی بهتر با کوبرنیتیز بهتر است اول مشکلاتی که کوبرنیتیز قصد حل کردن آنها را دارد را بشناسیم و سپس به روش کارکرد آن بپردازیم:
-
مدیریت و استقرار خودکار برنامهها: معمولا بررسی دستی منابع در دسترس و انتخاب بهینه سرورها برای اجرای نرمافزارها کاری پیچیده و احتمالا غیرممکن است. به همین خاطر دوست داریم این انتخابهای بهینه بر اساس نیازمندیهای ما به صورت خودکار انجام شود.
-
مدیریت خودکار ارتباط بین سرویسها: در شرایط و معماریهای پیچیده نر مافزارهای بزرگ، مدیریت شبکه و ارتباط بین آنها چالش آفرین بوده و بدون داشتن یک لایه ابسترکشن، حل مشکلات بسیار پیچیده میشود.
-
خودترمیمی: نرمافزارهای ما ممکن است به دلایل مختلفی دچار مشکل شده و از دسترس خارج شوند، در چنین شرایطی باید سیستمی وجود داشته باشد که آنها را به صورت خودکار بازگردانی کرده و سعی کند مشکل را حل کند.
-
بهروزرسانی خودکار: بهروزرسانی دستی نرمافزارها کاری پیچیده و مستعد خطاست، به همین علت به یک راه خودکار برای بهروزرسانی سریع و بدون مشکل نرمافزارها نیاز داریم.
-
در دسترس بودن: در بخش High Availability با این مفهوم و اهمیت آن در نرمافزار آشنا شدیم. به همین خاطر میدانیم که در نرمافزارهای مدرن باید SPoFهای زیرساختمان را کم کرده و از HA بودن آن مطمئن شویم.
-
مقیاسپذیری: ممکن است که در زمانهای خاصی تعداد کاربرهای نرمافزار ما بیشتر از حد مورد عادی شود. در چنین شرایطی باید با افزایش تعداد کپیهای نرمافزار و یا افزایش منابع در اختیار آن، به این بار بیش از حد عادی به سادگی پاسخ دهیم.
کوبرنیتیز سکویی (Platform) متنباز برای حل این مشکلات و ایجاد یک راهحل خودکار برای مدیریت سیستمهای کانتینری است. حالا که متوجه شدیم کوبرنیتیز سعی در حل چه چالشهایی دارد را ه خود را از دور به سمت شناخت این ابزار باز میکنیم.
Promise Theory
کوبرنیتیز بر اساس یک نظریه به نام Promise Theory کار میکند. برای شناخت این نظریه و اینکه چطور کوبرنیتیز با استفاده از آن به ما کمک میکند که نرمافزارهایمان را بهتر مدیریت کنیم، بهتر است که یک مثال بزنیم.
زمانی که شما میخواهید یک بسته پست کنید، به اداره پست نمیگویید که باید بسته شما با ماشین یا هواپیما جابهجا شود. شما صرفا بسته خود را داخل یک جعبه گذاشته، مبدا و مقصد را مشخص میکنید و آن را به اداره پست میسپارید. در مقابل اداره پست به شما قول میدهد که بسته شما تا یک زمان خاص به مقصد برسد. در چنین شرایطی برای شما مهم نیست که آب و هوا بد باشد یا وسیله نقلیهای که برای انتقال بسته شما استفاده شده چیست یا اگر این وسیله دچار مشکل شود چه اتفاقی میافتد. تنها چیزی که برای شما اهمیت دارد رسیدن صحیح بسته به مقصد است که اداره پست این کار را برای شما انجام میدهد.
کوبرنیتیز هم دقیقا مانند اداره پست عمل میکند. ما برنامههای خود را داخل کانتینرها قرار داده، نیازمندیهای اجرای آنها را توصیف میکنیم و در مقابل کوبرنیتیز به ما قول میدهد که نیازمندیهای نرمافزار ما را برآورده کند.
زیر پوست کوبرنیتیز
تا اینجای کار دیدیم که کوبرنیتیز به چه نیازهایی پاسخ میدهد و از دور چطور این کار را انجام میدهد. حالا بیایید با هم ببینیم که کوبرنیتیز واقعا چطور کار میکند.
کوبرنیتیز یک سیستم توزیعشده است. این به این معنی است که شما کوبرنیتیز را بر روی یک سرور نصب نمیکنید، بلکه هر قسمت از این ابزار را بر روی یک سرور مجزا نصب کرده و مدیریت این دستگاهها را به کوبرنیتیز میسپارید.
در فرهنگ لغت کوبرنیتیز به مجموعه سرورهای تحت مدیریت این ابزار، Cluster و به هر یک از این سرورها Node میگوییم.
اگر بخواهیم با دقت بیشتری به این دسته سرورها نگاه کنیم، دو دسته Node داریم. دسته اول Workerها هستند. این دسته از سرورها وظیفه اجرای کانتینرهای ما و اتصال به دیگر Nodeها برای ایجاد یک شبکه را دارند. در کنار این Node ها، Node های Control Plane را داریم. وظیفه Nodeهای Control Plane دریافت دستورات و خواستههای کاربر، ذخیره و کنترل کردن وضعیت کلاستر برای اجرای خواستههای کاربر است.
برای آشنایی بیشتر با اجزای مختلفی که در نهایت کوبرنیتیز را میسازند، میتوانید این ویدیو را تماشا کنید.
اجرای کوبرنیتیز
نصب و اجرای کوبرنیتیز به صورت آماده برای محیطهای عملیاتی فرایندی تقریبا پیچیده است. برای این کار از Kubeadm یا ابزارهای دیگر استفاده میشود. در اینجا با توجه به اینکه نیازی به استفاده عملیاتی از این ابزار نداریم، میتوانیم از ابزارهایی که کوبرنیتیز را به صورت محلی و برای تست اجرا میکنند استفاده کنیم. دو تا از این ابزارها Kind و Minikube هستند. این ابزارها به ما اجازه میدهند با استفاده از داکر یا ابزارهای مجازیسازی کوبرنیتیز را بر روی دستگاه شخصی خودمان اجرا کنیم. در ادامه راه برای استفاده از کوبرنیتیز ما از ابزار Kind استفاده میکنیم.
پیش از اینکه به سراغ استفاده از کوبرنیتیز برویم، نیاز به ابزاری برای مدیریت کلاستر داریم. این ابزار Kubectl است که به ما اجازه میدهد از طریق محیط خط فرمان کلاستر خود را کنترل کنیم. ابتدا Kubectl و سپس Kind را نصب کرده و سعی کنید یک کلاستر با یک نود Control Plane و یک نود Worker بسازید. برای اطمینان از صحت کلاستر خود میتوانید دستور زیر را اجرا کنید:
kubectl get nodes
اجرای نرمافزار بر روی کوبرنیتیز
کوچکترین شیء در دنیای کوبرنیتیز Pod یا پاد است. هر پاد متشکل از یک یا چند کانتینر است که برخی از من ابع را به صورت اشتراکی و برخی دیگر را به صورت جدا استفاده میکنند. در اینجا برای سادگی میتوانیم فرض کنیم که پاد در دنیای کوبرنیتیز با کانتینرهای داکری تناظر یک به یک داشته و هر پاد معادل یک کانتینر است.
اشیا در کوبرنیتیز بوسیله ساختاری به نام منیفست توصیف میشوند. منیفستها قطعات کدی مانند فایلهای Docker compose هستند که در فاز قبلی با آنها آشنا شدیم. منیفست زیر یک پاد را توصیف میکند. درباره هر یک از بخشهای آن جستوجو کنید و سعی کنید ساختار آن را درک کنید.
برای مدیریت اشیا در کوبرنیتیز با استفاده از ابزار kubectl برای هر نوع شی دستوری با ساختار زیر را اجرا میکنیم:
kubectl {verb} {resource}
مثلا برای مشاهده تمامی پادها از دستور
kubectl get pods
استفاده میشود.
apiVersion: v1
kind: Pod
metadata:
name: Nginx
labels:
app: Nginx
spec:
containers:
- name: nginx-container
image: nginx
منیفست بالا را به صورت یک فایل
yaml
ذخیره کرده و با استفاده از دستور
kubectl apply -f pod.yaml
آن را برای اجرا به کلاستر خود ارسال کنید.
Deployment
همانطور که گفتیم یکی از مشکلاتی که با استفاده از کوبرنیتیز سعی در رفع آنها داریم، مسئله خودترمیمی نرمافزارها است. با توجه به این نیازمندی، میتوان دید که اگر ما یک پاد را به صورت مستقل بر روی کوبرنیتیز اجرا کنیم، با پاک شدن آن پاد نرمافزار ما دچار مشکل میشود. به همین خاطر به چیزی نیاز داریم که با توصیف نوع پادهای مورد نیازمان، کوبرنیتیز پادها را به صورت خودکار ساخته و مدیریت کند.
یکی از چیزهایی که میتواند این نیازمندی ما را رفع کند Deployment است. اطلاعات آن را از منابع اصلی کوبرنیتیز خوانده و سعی کنید یک Deployment برای پاد مرحله قبل بنویسید و بر روی کلاستر قرار دهید.
بجز Deployment راههای دیگری مثل Statefulset و Deamonset نیز برای اجرای کانتینرها بر روی کوبرنیتیز وجود دارد. درباره آنها تحقیق کنید و تفاوتها و شباهتهای آنها را مشخص کنید.
Service
پس از اجرای دیپلویمنت بر روی کوبرنیتیز، نیاز به راهی برای ارتباط با پادها ی مستقر شده داریم. کوبرنیتیز به صورت خودکار به هر پاد یک آدرس IP منحصر به فرد اختصاص میدهد اما با توجه به اینکه ممکن است یک Deployment چندین پاد یکسان را مدیریت کند و نیاز به تقسیم بار بر روی آنها داشته باشیم نمیتوان از آدرس اصلی پادها استفاده کنیم. علاوه بر این با حذف شدن پادها و اجرای دوباره آنها این آدرس ممکن است تغییر کند و از این جهت نیز استفاده از آن منطقی نیست.
کوبرنیتیز برای رفع این مشکل از شی Service استفاده میکند. این شی به ما اجازه میدهد با یک آدرس IP مجازی، با یک گروه از پادها ارتباط برقرار کنیم. همچنین این شی به صورت خودکار بار را بین این پادها تقسیم کرده و در زمان مشکل دار شدن یک پاد درخواستهای ما را به آن نمیفرستد.
اطلاعات Service را از منابع اصلی کوبرنیتیز خوانده و سعی کنید یک سرویس از نوع NodePort و یک سرویس از نوع ClusterIP برای Deployment مرحله قبل بنویسید و بر روی کلاستر قرار دهید. تفاوت این دو نوع سرویس در چیست؟