کانتینرها از صفر با ابزارهای لینوکس (اختیاری)
نکته: این درس کاملاً اختیاری و با هدف آموزشی طراحی شده است. برای کار کردن با Docker نیازی به اجرای روزمرهی این دستورات ندارید؛ اما درک این مفاهیم به شناخت دقیقتر سازوکار کانتینرها و عملکرد هستهی لینوکس کمک میکند.
در درس قبل اشاره کردیم که کانتینرها سیستمعامل جداگانهای نیستند، بلکه پردازشهای لینوکس هستند که با قابلیتهای هسته محدود شدهاند. در این درس با ابزارهای پیشفرض لینوکس و بدون نصب ابزارهایی مانند Docker، یک محیط ایزولهی ساده میسازیم.
ارکان سهگانهی کانتینر در هستهی لینوکس
هر سیستم کانتینری از ۳ مکانیزم بنیادین هستهی لینوکس برای ایزولاسیون استفاده میکند:
| Namespaces | Control Groups (cgroups) | Chroot / Pivot Root |
|---|---|---|
| دیدگاه و ایزولاسیون پردازش | محدودسازی و سنجش منابع | ایزولاسیون فایلسیستم |
| پردازش چه بخشهایی از سیستم را میبیند؟ | پردازش چقدر CPU، RAM و I/O مصرف میکند؟ | پردازش به کدام مسیرها و فایلها دسترسی دارد؟ |
۱. فضاهای نام (Linux Namespaces)
فضای نام زاویهی دید پردازش را محدود میکند. لینوکس چند فضای نام مجزا دارد:
uts(UNIX Timesharing System): جداسازی نام هاست (Hostname) و Domain Name.pid(Process ID): پردازش داخل فضای نام فقط پردازشهای فرزند خود را میبیند و شمارهی ۱ میگیرد.net(Network): اختصاص اینترفیسهای کارت شبکه، جدول مسیربندی (Routing Table) و پورتهای مستقل.mnt(Mount): جداسازی مسیرها و Mount Pointهای سیستم فایل.ipc(Inter-Process Communication): جداسازی حافظهی اشتراکی و صفهای پیام لینوکس.user(User IDs): نگاشت یوزر Root داخل کانتینر به یک یوزر غیر-Root در سیستم میزبان.
۲. گروههای کنترل (Control Groups یا Cgroups)
اگر کانتینری دچار نشت حافظه (Memory Leak) شود، نباید کل سرور از کار بیفتد. Cgroups (بهویژه نسخه مدرن cgroups v2 در /sys/fs/cgroup) تعیین میکند که پردازشها حداکثر چقدر RAM، CPU یا سرعت خواندن/نوشتن از دیسک میتوانند مصرف کنند. هستهی لینوکس پردازشی که بیش از حد مجاز رم مصرف کند را با خطای معروف OOM-Killed (Out of Memory) متوقف میکند.
۳. ایزولاسیون فایلسیستم (chroot و pivot_root)
دستور chroot (مخفف Change Root) دایرکتوری ریشهی (/) سیستم را برای پردازش مشخصی تغییر میدهد تا نتواند به فایلهای حساس سرور میزبان سرک بکشد.
آزمایش عملی: ساخت کانتینر با دستور unshare
ابزار unshare در لینوکس به شما اجازه میدهد تا بدون نیاز به کدنویسی در زبان C، پردازشی را با فضاهای نام جدید اجرا کنید.
بیایید روی سرور اوبونتو این را امتحان کنیم:
گام ۱: اجرای پردازش در فضای نام مجزا
دستور زیر را با دسترسی sudo اجرا کنید:
پارامترها:
--uts: نام هاست اختصاصی--pid: فضای نام پردازش مستقل--mount: فضای نام Mount مستقل--fork: اجرای شل در قالب یک پردازش فرزند جداگانه
گام ۲: بررسی ایزولاسیون نام هاست (UTS)
اکنون در شل جدید هستید. بیایید نام هاست را عوض کنیم:
حالا اگر در یک پنجره یا تب ترمینال دیگر نام هاست سرور اصلی را چک کنید:
نام هاست سرور اصلی دستنخورده باقی مانده است، زیرا پردازش اول در یک UTS Namespace جداگانه قرار دارد!
گام ۳: بررسی ایزولاسیون پردازشها (PID Namespace)
داخل شل ایزولهشده، برای اینکه دستور ps پردازشهای سیستم را از این دیدگاه جدید بخواند، باید فایلسیستم /proc را مجدداً mount کنیم:
خروجی شبیه به این خواهد بود:
میبینید که داخل این فضا، هیچ اثری از پردازشهای سرور اصلی نیست! شل ما پردازش شمارهی ۱ (PID 1) شده است و جز خودش و دستور ps پردازش دیگری در سیستم وجود ندارد.
با زدن دستور exit از این فضای ایزوله خارج شوید:
چرا مستقیماً از این دستورها استفاده نمیکنیم و به Docker نیاز داریم؟
همانطور که دیدید، ساختن یک پردازش ایزوله با دستورات هسته امکانپذیر است، اما در مقیاس صنعتی بسیار دشوار و پرخطاست:
- چگونه فایلسیستم یک برنامه و کتابخانههایش را دانلود و بستهبندی کنیم؟
- چگونه ترافیک شبکه، پورتها و پلهای مجازی (Bridge) را خودکار پیکربندی کنیم؟
- چگونه ایمیجها را به صورت لایهای (Layered Filesystem) ذخیره کنیم تا فضای دیسک هدر نرود؟
- چگونه چرخهی حیات و لاگهای صدها پردازش را مدیریت کنیم؟
Docker و ابزارهای مشابه، مدیریت خودکار Namespaces، Cgroups، فایلسیستم لایهای (OverlayFS) و پیکربندی شبکهها را در قالب دستوراتی یکپارچه و استاندارد مانند docker run انجام میدهند تا نیازی به اجرای دستی این فرایندها نباشد.
منابع یادگیری
ویدیو
- قسمت دوم داکر پیشرفته: ساخت کانتینر بدون استفاده از داکر، تنها با قابلیتهای خود لینوکس — امیرارسلان یاوری — آموزش فارسی ساخت کانتینر با ابزارها و قابلیتهای درونی لینوکس
- Containers from Scratch • Liz Rice • GOTO 2018 — سخنرانی Liz Rice و کدنویسی زنده ساخت کانتینر با فراخوانی مستقیم هستهی لینوکس