فصل دوم کتاب "Kubernetes in Action با هدف آشنایی اولیه با مفاهیم داکر و کوبرنتیز شروع میشه. این فصل به موضوعاتی مثل ایجاد و اجرای یک ایمیج کانتینری با داکر، اجرای یک کلاستر تکنودی کوبرنتیز به صورت local، و تنظیم یک کلاستر کوبرنتیز توی Google Kubernetes Engine میپردازه. همچنین، با دستور kubectl آشنا میشیم و نحوه دیپلوی و scale کردن یه اپلیکیشن روی کوبرنتیز را یاد میگیریم.
توی قدم اول با نحوه ایجاد، اجرا و به اشتراکگذاری یک ایمیج کانتینری با داکر آشنا میشیم و کارهایی گه قراره انجام بدیم رو اینجا نوشتم
خب توی قدم اول باید داکر روی سیستمتون نصب باشه چون روش های نصب توی سایت اصلی خودش خیلی خوب توضیح داده من این حرله رو رد میکنم. در نهایت با دستور زیر میتونیم ببینیم داکر روی سیستم ما نصب هست یا نه
docker version
توی اولین قدم میتونیم از یک تصویر آماده در Docker Hub استفاده کنیم که مجموعهای از container image آماده، مثل busybox رو ارائه میده.
ایمیج BusyBox یک ابزار اجرایی ساده است که بسیاری از دستورات استاندارد UNIX مانند echo
، ls
و gzip
رو داره. با اجرای دستور docker run
، میتونیم یه image رو دانلود و یه کانتینر از اون رو اجرا کنیم.
نکته قابل توجه این است که اپلیکیشن شما داخل یک کانتینر اجرا میشود که از سایر فرآیندهای سیستم شما کاملاً ایزوله شده، و این امر به کنترل و امنیت بالاتری منجر میشود.
وقتی دستور docker run
را اجرا میکنیم، مراحل زیر اتفاق میافتد:
اجرای کانتینر های دیگه
با دستور زیر میتونیم کانتینر های دیگه رو اجرا کنیم. حتی خیلی وقتها دستورات مورد نیاز داخل خود image گنجونده شدن و نیاز نیست مثل مثالی بالا echo "Hello world"
اینم بنویسیم.
$ docker run <image>
ورژن بندی container images
همانطور که در بیشتر نرمافزارها نسخههای مختلفی وجود داره، container image هم ممکنه نسخههای متفاوتی داشته باشه. داکر امکان استفاده از چندین نسخه از یه image رو با استفاده از تگهای منحصربهفرد فراهم میکند. در صورتی که تگی مشخص نشه، بهطور پیشفرض داکر تگ latest
را استفاده میکند.
$ docker run <image>:<tag>
خب تو این قسمت شما یه اپلیکیشن وب ساده Node.js رو مینویسن و یه image از اون ایجاد میکنین. اپلیکیشن کارش اینه به درخواستهای HTTP پاسخ میده و نام میزبان (hostname) ماشینی که تو اون اجرا میشه رو برمیگردونه. این به شما نشان میدهد که یک اپلیکیشن درون کانتینر تنها نام خود کانتینر را میبیند، نه نام میزبان اصلی سیستم.
کد اپلیکیشن:
const http = require('http'); const os = require('os'); console.log("Kubia server starting..."); var handler = function(request, response) { console.log("Received request from " + request.connection.remoteAddress); response.writeHead(200); response.end("You've hit " + os.hostname() + "\\\\n"); }; var www = http.createServer(handler); www.listen(8080);
این اپلیکیشن یک سرور HTTP روی پورت 8080 ایجاد میکند که به هر درخواست با پیام "You’ve hit <hostname>" پاسخ میدهد و IP کلاینت را لاگ میکند.
ابتدا باید یه فایل به نام Dockerfile ایجاد کنیم که شامل دستورات لازم برای ساخت Image باشه. این فایل باید توی همون دایرکتوری که app.js قرار داره ساخته بشه و دستورات زیر را شامل میشه:
FROM node:7 ADD app.js /app.js ENTRYPOINT ["node", "app.js"]
این Dockerfile سه بخش اصلی دارد:
در اینجا چون اپلیکیشن با Node.js نوشته شده، از تصویر node استفاده میکنیم که همه چیز لازم برای اجرای اپ رو داره.
خب با دستور زیر یه image به اسم kubia ساخته میشه:
$ docker build -t kubia .
با اجرای این دستور، Docker از محتوای دایرکتوری فعلی استفاده میکنه و بر اساس دستورالعملهای Dockerfile، ایمیج رو میسازه. Docker ابتدا ایمیج پایه رو دانلود میکنه و سپس فایلهای اپلیکیشن شما را به اون اضافه میکند.
تصویر زیر گویای همه چی هست و نشون میده چه اتفاقی میفته وقتی شما درخواست ساخت یه ایمیج رو ارسال میکنین.
یه ایمیج داکر شامل چندین لایه هست و هر لایه توسط دستورات Dockerfile ساخته میشود. این لایهها به صورت مستقل از یکدیگر ایجاد میشن و هر ایمیج ممکنه لایههای مشترکی با ایمیج های دیگه داشته باشه. وقتی داکر یک image رو دانلود میکنه، فقط لایههایی که روی سیستم محلی نیستند، دانلود میشن. این روش به ذخیرهسازی کارآمدتر و انتقال سریعتر ایمیج کمک میکنه. هر لایه با دستورات جدید یک لایهی تازه به تصویر اضافه میکند. و در انتها وقتی همه لایه ها دانلود شدن یه لایه میاد روی همه اونها ایجاد میشه و فایل app.js رو بهش اضافه میکنه و در آخرم یه لایه اضافه میشه و اون کامند هایی که قراره وقتی ایمیج ران شد اجرا بشن رو قرار میده اونجا.
وقتی فرایند ساخت ایمیج تموم میشه، ایمیج جدید تو سیستم محلی ما ذخیره میشه. برای مشاهده تمامی ایمیج های محلی ذخیرهشده، میتوانیم از دستور زیر استفاده کنیم که من اینجا فیلتر کردم و فقط لیستی که میخوایم رو نشون دادم:
$ docker images
این دستور لیستی از image های local رو به همراه اطلاعاتی مثل نام REPOSITORY، برچسب (TAG)، شناسه تصویر (IMAGE ID)، تاریخ ایجاد (CREATED)، و اندازه مجازی (VIRTUAL SIZE) نشون میده.
برای اجرای یه کانتینر میتونیم از دستور زیر استفاده کنیم
$ docker run --name kubia-container -p 8080:8080 -d kubia
این دستور کانتینری به نام kubia-container
از ایمیجkubia
میسازه و اون رو توی پسزمینه اجرا میکند. پورت 8080 ماشین local رو به پورت 8080 داخل کانتینر مپ میشود. میتونیم اپلیکیشن رو از طریق http://localhost:8080
ببینیم.
پاسخی که بهمون میده، شناسهی کانتینری هست که اپلیکیشن روی اون اجرا شده و از ماشین میزبان جدا است.
با دستور زیر هم میتونیم لیست تمام کانتینر های در حال اجرا رو ببینیم
برای دریافت اطلاعات بیشتر در مورد یک کانتینر، دستور docker inspect
را میتوانید اجرا کنید:
$ docker inspect kubia-container
این دستور، اطلاعات سطح پایین و جامعتری از کانتینر رو به صورت یک JSON بلند ارائه میدهد. اطلاعات شامل جزئیاتی مانند شبکه، مسیرها، حجمها، متغیرهای محیطی و موارد دیگر خواهد بود.
بررسی محیط داخلی کانتینر
برای بررسی محیط داخلی یک کانتینر در حال اجرا، میتونیم یک شل (مانند Bash) رو داخل کانتینر اجرا کنیم. به عنوان مثال، چون ایمیجی که برنامه Node.js شما بر اساس آن ساخته شده، حاوی Bash است، با اجرای دستور زیر میتوانیم وارد کانتینر شده و محیط آن را مشاهده کنید:
$ docker exec -it kubia-container bash
این دستور Bash رو توی کانتینر kubia-container
اجرا میکنه. گزینههای i-
و t-
برای اینه که تعاملی باشه و ترمینال بعد اجرای دستور اول بسته نشه
بررسی کانتیتر از داخل
وقتی دستور ps aux
را توی کانتینر اجرا میکنیم، تنها پردازشهایی که درون کانتینر در حال اجرا هستند نمایش داده میشن. توی این مثال، تنها سه فرآیند مشاهده میشود: فرآیند اصلی node app.js
که اپلیکیشن شما را اجرا میکنه، شلbash
که شما اجرا کردهاید، و دستور ps aux
که برای نمایش این فرآیندها استفاده شده است. این نشان میدهد که کانتینر کاملاً از فرآیندهای سیستم عامل میزبان ایزوله شده است و تنها پردازشهای خودش را نمایش میدهد.
درک اینکه Process ها توی یه کانتینر در سیستم عامل میزبان اجرا میشن
وقتی یه process توی یه کانتینر اجرا میشه، در واقع اون process توی سیستم عامل میزبان داره اجرا میشه. با اجرای دستور ps aux | grep app.js
توی سیستم عامل میزبان، میتونیم process های کانتینر رو ببینیم. به طور مثال، در اینجا فرآیند node app.js
هم توی کانتینر و هم داخل سیستم عامل میزبان قابل مشاهده است، اما Process ID در هر دو متفاوت است. دلیل این تفاوت این است که هر کانتینر از فضای نام فرآیند (PID namespace) مخصوص به خود استفاده میکند که فرآیندها را ایزوله نگه میدارد.
سیستم فایل هر کانتینر در داکر نیز ایزوله شده است، به این معنی که کانتینر فقط به فایلها و دایرکتوریهایی که داخل خود کانتینر قرار دارند دسترسی دارد. در واقع، کانتینر فایلهای موجود در تصویر (image) پایهای خود و فایلهای ایجاد شده در زمان اجرا رو میبینه. برای مشاهده وضعیت سیستم فایل داخل کانتینر، میتوان از فرمانهایی مانند \ls
استفاده کرد که فقط فایلهای موجود در کانتینر را نشان میدهد.
برای متوقف کردن یک کانتینر در داکر، میتوانید از دستور زیر استفاده کنید:
docker stop kubia-container
این دستور، main process درون کانتینر رو متوقف میکنه و به همین دلیل کانتینر نیز متوقف میشه. اما کانتینر هنوز موجوده و با دستور docker ps -a
قابل مشاهده است. برای حذف کامل کانتینر و پاک کردن محتویات آن از دستور زیر استفاده میشود:
docker rm kubia-container
این کار کانتینر را کاملاً حذف کرده و نمیتوان آن را دوباره راهاندازی کرد.
اشتراک گذاری ایمیج توی یه image registry
برای به اشتراکگذاری داکر ایمیج خود توی Docker Hub، اول باید یک برچسب (Tag) جدید به ایمیج خودمون اضافه کنیم که شامل شناسه Docker Hub شما باشد. بعدش میتونیم ایمیج رو توی Docker Hub آپلود میکنیم
مرحله اول: Tag گذاری ایمیج:
docker tag kubia <your-dockerhub-id>/kubia
ورود به حساب Docker Hub:
docker login
ارسال تصویر به Docker Hub:
docker push <your-dockerhub-id>/kubia
حالا ایمیج شما در دسترس همه است و از هر جایی میتونیم اونو اجرا کنیم.
خب تا اینجا دید خیلی خوبی نسبت به داکر و کانتینر ها پیدا کردیم توی قسمت بعدی میریم سراغ اجرای دستورات توی کلاستر کوبرنتیز.