کانتینرها ایزوله نیستند؛ آن‌ها نماهای جداگانه‌ای از یک هستهٔ واحدند

کانتینرها شبیه ماشین‌های مجازی کوچک به نظر می‌رسند — درخت فرایند، پشتهٔ شبکه و نام میزبان مشخص — اما ایزولاسیون کامل ندارند. سازوکار ایزولاسیون در لینوکس ترکیبی از چند مؤلفهٔ هسته‌ای است: namespaces، cgroups و لایه‌بندی ذخیره‌سازی مانند OverlayFS. درک دقیق این سازوکارها برای رفع اشکال، ارزیابی ریسک و بهینه‌سازی عملکرد ضروری است.

پشتهٔ زمان اجرا در Docker: از CLI تا هسته

فرمان ساده‌ای مانند docker run nginx مستقیماً ماشین مجازی اجرا نمی‌کند؛ درخواست از چند لایه عبور می‌کند:

  • Docker CLI: فرمان خط‌فرمان را به فراخوانی API تبدیل می‌کند.
  • REST API: رابط بین CLI و موتور Docker.
  • Docker daemon: ایمیج را دانلود، کانتینر را ایجاد، شبکه و ولوم‌ها را پیکربندی و runtime مناسب را راه‌اندازی می‌کند.

در سطح پایین‌تر runtimeهایی مثل containerd و runc فرایندهای نهایی را داخل فضای نام‌ها و با محدودیت‌های cgroups اجرا می‌کنند. نتیجه اجرای کانتینر، یک فرایند کاربر روی همان هستهٔ میزبان با نماهای جداشده از منابع است. مستندات رسمی Docker مرجع خوبی برای جزئیات بیشتر است.

namespaces: چه چیزی را فرایند می‌بیند

namespaces نماهای مجزایی از منابع سیستم ایجاد می‌کنند و پاسخ به این سؤال هستند که «فرایند چه چیزهایی را می‌بیند». کانتینرها معمولاً از مجموعه‌ای از نام‌فضاها استفاده می‌کنند:

PID

درخت فرایند و شماره‌گذاری PID را جدا می‌کند؛ فرایندی که داخل کانتینر PID 1 است، روی میزبان ممکن است PID دیگری داشته باشد. به همین دلیل داخل کانتینر تعداد کمتری فرایند دیده می‌شود در حالی که میزبان می‌تواند صدها فرایند داشته باشد.

NET

به هر کانتینر یک پشتهٔ شبکهٔ مستقل اختصاص می‌دهد — اینترفیس‌ها، آدرس‌های IP و جداول مسیریابی جدا هستند. دو کانتینر می‌توانند هر دو روی پورت 80 گوش دهند بدون تداخل در نام‌فضای شبکهٔ خود.

MNT

نمای مجزایی از نقاط mount و ساختار فایل‌سیستم فراهم می‌کند؛ در زمان اجرا یک لایهٔ نوشتنی روی لایه‌های فقط‌خوان ایمیج قرار می‌گیرد و توهم یک فایل‌سیستم محلی ایجاد می‌شود.

IPC، UTS و User namespaces

IPC صف‌ها و حافظهٔ مشترک را جدا می‌کند، UTS نام میزبان و دامنه را ایزوله می‌کند، و User namespaces شناسه‌های کاربری را بین کانتینر و میزبان نگاشت می‌کند؛ به‌عنوان مثال root داخل کانتینر می‌تواند به UID غیرمتمایز روی میزبان نگاشته شود. برای مرجع بیشتر به صفحهٔ ویکی دربارهٔ namespaces مراجعه کنید.

cgroups: کنترل و حسابداری منابع

اگر namespaces محدودهٔ دید را تعیین می‌کنند، cgroups میزان مصرف منابع را کنترل می‌کنند. گروه‌های کنترل برای حسابداری و محدود کردن منابع طراحی شده‌اند تا از اثر «همسایهٔ پرسر و صدا» جلوگیری شود.

مثال‌های عملی

  • محدودیت CPU: با مثال docker run --cpus=0.3 سهم CPU محدود می‌شود.
  • محدودیت حافظه: با --memory=512m حداکثر حافظه تعیین می‌شود؛ در صورت نقض ممکن است هسته فرایند را با OOM-killer پایان دهد.
  • I/O و دیسک: cgroups امکان اعمال محدودیت‌های blkio را برای کنترل عملیات دیسک فراهم می‌کند.

برای مطالعهٔ عمیق‌تر به مستندات cgroups v2 در kernel.org مراجعه کنید.

ذخیره‌سازی و لایهٔ نوشتنی: تبدیل تصویر به فایل‌سیستم

ایمیج‌ها از چند لایهٔ فقط‌خوان تشکیل می‌شوند. در زمان اجرا درایورهایی مانند OverlayFS یک لایهٔ نوشتنی روی این لایه‌ها قرار می‌دهند. این مکانیزم copy-on-write اجازه می‌دهد چند کانتینر از یک ایمیج مشترک استفاده کنند بدون تداخل در داده‌های پایه؛ تغییرات هر کانتینر فقط در همان لایهٔ نوشتنی ذخیره می‌شود. مستندات فنی OverlayFS در kernel.org توضیح داده شده است.

نقاط ضعف ایزولاسیون و نکات امنیتی

  • کانتینرها هسته را مشترک دارند؛ هر آسیب‌پذیری در هسته یا درایورها می‌تواند به فرار از کانتینر منجر شود.
  • اجرای کانتینر با دسترسی privileged یا اعطای capabilities بیش از نیاز، خطر بالایی دارد؛ اصل حداقل امتیاز را رعایت کنید.
  • User namespaces می‌تواند ریسک‌ها را کاهش دهد، اما پشتیبانی و پیکربندی آن در توزیع‌ها و محیط‌های مختلف یکسان نیست.
  • برای ایزولاسیون قوی‌تر راهکارهای مبتنی بر میکروVM مثل Kata Containers یا اجرای کانتینرها در VM مجزا مناسب‌تر هستند.

ابزارها و روش‌های عیب‌یابی

چند بررسی عملی که وضعیت ایزولاسیون و مصرف منابع را نشان می‌دهد:

  • دیدن نام‌فضاهای یک PID: lsns یا readlink /proc/<pid>/ns/*.
  • مشاهدهٔ شبکهٔ کانتینر: ip netns یا docker exec -it <ctr> ip addr.
  • کنترل مصرف منابع: docker stats و مقایسه با محدودیت‌های cgroups.
  • مقایسهٔ دید میزبان و کانتینر از نظر فرایندها: روی میزبان ps auxf و داخل کانتینر ps aux را اجرا کنید تا تفاوت شماره‌گذاری PID مشهود شود.

نگاهی به آینده

پیشرفت‌ها در معماری کانتینر شامل اجرای rootless، ترکیب با میکروVMها و استفاده از WebAssembly برای بارهای سبک‌تر است. این تحولات مدل ایزولاسیون را تغییر می‌دهند. برای مدیریت ایمن و قابل‌پیش‌بینی، مهندسان باید رفتار هسته، پیکربندی runtime و سیاست‌های منابع را به‌خوبی بشناسند و ابزارهای مانیتورینگ و کنترل را پیاده‌سازی کنند.

منابع فنی پیشنهادی: مستندات Docker، صفحات ویکی دربارهٔ کانتینریزاسیون و مستندات رسمی kernel.org.