🧩 مقدمه: چرا مفاهیم ایزولاسیون در لینوکس اهمیت دارند
در دنیای مدرن فناوری، سیستمعاملها بهویژه لینوکس، قلب زیرساختهای دیجیتال محسوب میشوند. هزاران پردازه (process) بهصورت همزمان روی یک سیستم در حال اجرا هستند؛ برخی متعلق به کاربران مختلف، برخی به سرویسها و برخی به کانتینرها. سؤال این است: چطور ممکن است این همه پردازه بدون تداخل و خطر، روی یک کرنل مشترک کار کنند؟ پاسخ در مفهومی بنیادین به نام ایزولاسیون (Isolation) نهفته است.
🧠 ایزولاسیون یعنی چه؟
ایزولاسیون یعنی جدا کردن محیط اجرایی هر پردازه از دیگری. در واقع هر برنامه در محیطی محدود اجرا میشود و فقط به منابعی که برایش تعیین شده دسترسی دارد. این ایده، جلوی تداخل دادهها، دسترسی غیرمجاز و خرابی سیستم را میگیرد.
در دنیای واقعی، این وضعیت را میتوان به اتاقهای جداگانه در یک هتل تشبیه کرد. همه مهمانان در یک ساختمان زندگی میکنند (یعنی همان کرنل لینوکس)، اما هرکدام کلید مخصوص اتاق خود را دارند و نمیتوانند وارد اتاق دیگران شوند.
🔩 ایزولاسیون در لینوکس چطور انجام میشود؟
در لینوکس، ایزولاسیون در سه سطح اصلی رخ میدهد:
- Namespaceها — برای جداسازی دید پردازهها نسبت به منابع سیستم مثل PID، شبکه، و فایلسیستم.
- Control Groups (Cgroups) — برای محدود کردن مصرف منابع مثل CPU، حافظه و دیسک.
- User Permissions — برای مدیریت سطح دسترسی کاربران و نقشها.
ترکیب این سه مکانیزم باعث میشود که پردازهها «فکر کنند» در سیستم کاملاً مستقل خودشان در حال اجرا هستند، در حالیکه در واقع همهشان درون یک هسته (Kernel) واحد قرار دارند.
🔒 چرا ایزولاسیون مهم است؟
بدون ایزولاسیون، هر پردازه میتوانست به دادههای پردازههای دیگر دسترسی پیدا کند یا حتی آنها را از بین ببرد. بهعنوان نمونه، در یک سرور اشتراکی اگر ایزولاسیون وجود نداشت، کاربر A میتوانست پردازههای کاربر B را متوقف کند، فایلهایش را بخواند یا مصرف CPU کل سرور را در اختیار بگیرد.
ایزولاسیون در لینوکس تضمین میکند که:
- یک باگ در یک کانتینر به سایر کانتینرها آسیب نمیزند.
- پردازههای کاربران مختلف از هم جدا هستند.
- منابع بهطور منصفانه بین پردازهها تقسیم میشوند.
- امنیت سیستم در برابر حملات سطح کاربر بالا میرود.
به همین دلیل، مکانیزمهایی مانند Namespace بهعنوان زیرساخت اصلی امنیت و مقیاسپذیری در لینوکس شناخته میشوند.
⚙️ پیوند ایزولاسیون با مجازیسازی
ایزولاسیون پایهی بسیاری از فناوریهای مدرن از جمله Docker, Kubernetes, Podman, و LXC است. برخلاف ماشینهای مجازی که نیازمند hypervisor جداگانه هستند، در Namespace هر کانتینر مستقیماً روی کرنل میزبان (Host Kernel) اجرا میشود ولی بهصورت مجازیشده از بقیه جداست.
این طراحی باعث میشود کانتینرها:
- بسیار سریعتر از VMها باشند،
- حافظه و CPU کمتری مصرف کنند،
- در عینحال، امنیت مشابه را ارائه دهند.
🌍 یک مثال واقعی از اهمیت ایزولاسیون
فرض کنید روی یک سرور لینوکس، دهها کاربر همزمان وارد شدهاند و هرکدام برنامههایی را اجرا میکنند. اگر هیچ مکانیزم ایزولاسیونی وجود نداشت، همه میتوانستند با دستور سادهی
پردازههای دیگران را ببینند یا حتی با دستور
آنها را از کار بیندازند!
Namespaceها جلوی این فاجعه را میگیرند؛ بهطوریکه هر کاربر یا container فقط «دنیای خودش» را مشاهده میکند — یک جدول پردازه جداگانه، یک فضای شبکه مجزا، و یک مسیر فایلسیستم مستقل.
📊 جمعبندی بخش اول
ایزولاسیون در لینوکس نه فقط یک قابلیت امنیتی، بلکه یک فلسفه طراحی است. بدون آن، لینوکس نمیتوانست زیربنای فناوریهایی مثل Docker، Kubernetes و Cloud-Native شود. Namespaceها به لینوکس قدرت خلق چند «جهان موازی» در درون یک سیستم واحد را میدهند — جهانی که هر container در آن احساس میکند یک سیستم کامل و مستقل است.
📘 Namespace چیست؟ تعریف و ایدهی اصلی در کرنل لینوکس
در سیستمعامل لینوکس، هر پردازه (process) دنیایی از دادهها و منابع را میبیند: فایلها، شبکه، شناسههای پردازه (PIDها)، کاربران و غیره. در حالت عادی، همهی پردازهها در یک فضای مشترک این منابع را میبینند، اما این باعث میشود بین آنها تداخل و خطر امنیتی به وجود آید. برای حل این مسئله، لینوکس مفهومی به نام Namespace را معرفی کرد؛ ابزاری برای ایجاد “جهانهای مجزا” درون یک سیستمعامل واحد.
🧩 تعریف کلی Namespace
Namespace به زبان ساده یعنی ایجاد یک “فضای نامگذاری” مجزا برای گروهی از پردازهها. هر Namespace نوع خاصی از منبع را از بقیهی سیستم جدا میکند — مثلاً جدول پردازهها، آدرسهای شبکه یا فضای فایلسیستم.
به عبارت دیگر، Namespace تعیین میکند که چه چیزی توسط چه پردازهای دیده میشود.
مثلاً در یک سیستم لینوکسی با دو container، هر container میتواند پردازهای با PID=1 داشته باشد، بدون اینکه بین آنها تداخلی پیش بیاید. این کار توسط PID Namespace انجام میشود.
🧠 ایدهی اصلی در پشت Namespace
ایدهی Namespace بر اساس اصل «جداسازی دید» (Separation of View) شکل گرفته است. بهجای اینکه سیستم چند کرنل مختلف برای هر محیط ایجاد کند (مانند ماشین مجازی)، فقط دید هر پردازه نسبت به منابع را تغییر میدهد. بنابراین، تمام پردازهها هنوز از یک کرنل مشترک استفاده میکنند، اما هرکدام فقط بخشی از آن را میبینند که متعلق به Namespace خودشان است.
این مفهوم اولینبار در سال 2002 با معرفی Mount Namespace وارد کرنل لینوکس شد، و سپس انواع دیگر مانند PID، Network، UTS، IPC و User اضافه شدند.
هر Namespace نوع خاصی از منابع را ایزوله میکند و همهی آنها با هم میتوانند یک محیط کاملاً مستقل (مثل container) بسازند.
⚙️ ساختار Namespace در سطح کرنل
در سطح کرنل، هر پردازه در ساختار دادهای به نام task_struct ثبت میشود. این ساختار شامل اشارهگرهایی به Namespaceهایی است که پردازه در آنها قرار دارد:
درون nsproxy، کرنل اشارهگرهایی برای انواع Namespace نگه میدارد:
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
struct pid_namespace *pid_ns_for_children;
struct net *net_ns;
struct user_namespace *user_ns;
};
به این ترتیب، هر پردازه دقیقاً مشخص میکند در چه Namespaceهایی قرار دارد و دیدش از منابع سیستم چگونه است.
🔑 چرا Namespaceها تحولآفرین بودند؟
قبل از معرفی Namespace، جداسازی بین پردازهها بسیار محدود بود. مثلاً همهی پردازهها جدول PID مشترک داشتند، و کنترل منابع بیشتر از طریق کاربر (user permission) انجام میشد. اما Namespace باعث شد لینوکس بهطور ذاتی از چند “محیط مجزا” پشتیبانی کند، بدون نیاز به ماشین مجازی.
این تحول، زیرساخت فناوریهایی مثل Docker، Kubernetes و LXC را ایجاد کرد، زیرا حالا میتوانستیم درون یک سیستم واحد، چند محیط کاملاً ایزوله بسازیم.
🧰 نحوه ایجاد Namespace در عمل
Namespaceها در کرنل از طریق فراخوانیهای سیستمی خاص ایجاد میشوند:
- clone() — برای ایجاد پردازهای در Namespace جدید (با فلگهای CLONE_NEW*).
- unshare() — برای جدا کردن پردازه فعلی از Namespace والد.
- setns() — برای ورود به Namespace دیگر.
برای مثال، دستور زیر یک شل جدید در Namespace شبکهی جداگانه ایجاد میکند:
در این حالت، دستور
فقط اینترفیسهای شبکهی Namespace جدید را نمایش میدهد.
📚 نکته فنی: Namespaceها “سبکتر” از ماشینهای مجازیاند
در ماشینهای مجازی، هر سیستمعامل مهمان کرنل مخصوص خود را دارد، در حالی که Namespaceها فقط دید را تغییر میدهند. این یعنی containerهایی که با Namespace ساخته میشوند، مستقیماً روی کرنل میزبان اجرا میشوند و فقط “توهم مجزا بودن” دارند.
همین تفاوت باعث میشود کانتینرها:
- در عرض چند میلیثانیه اجرا شوند،
- مصرف منابع بسیار پایینی داشته باشند،
- و مقیاسپذیری بالایی برای سرورهای ابری فراهم کنند.
🧭 جمعبندی بخش دوم
Namespace در لینوکس یکی از خلاقانهترین مفاهیم طراحی در تاریخ سیستمعاملهاست. این ویژگی بهجای ساخت سیستمهای کاملاً مجزا، دید هر پردازه را از جهان تغییر میدهد — درست مثل گذاشتن “عینکهای مختلف” بر روی یک واقعیت مشترک.
Namespaceها پایه و اساس همهی فناوریهای container محور هستند و بدون آنها، چیزی به نام Docker یا Kubernetes وجود نداشت.
📜 تاریخچه و سیر تکامل Namespaceها در لینوکس
ویژگی Namespaces یکی از تحولات بنیادی در سیستمعامل لینوکس است که بهتدریج و در طی دو دهه، به یکی از ارکان اصلی مجازیسازی در سطح سیستمعامل تبدیل شد. ایدهی اصلی آن، از نیاز به جداسازی محیطهای اجرایی (Isolation) در سرورهای چندکاربره آغاز شد و امروز پایهی فناوریهایی مانند Docker، Kubernetes و LXC است.
🧩 پیشزمینه: نیاز به ایزولاسیون در سیستمهای چندکاربره
در دههی ۱۹۹۰ میلادی، سرورهای لینوکسی معمولاً بهصورت همزمان توسط چندین کاربر و سرویس مختلف استفاده میشدند. اما همهی پردازهها به منابع مشترک دسترسی داشتند، مثل جدول PIDها، شبکه و فایلسیستم. اگر یکی از کاربران اشتباه میکرد (یا بدتر، اقدام مخرب انجام میداد)، کل سیستم تحتتأثیر قرار میگرفت.
مهندسان کرنل بهدنبال راهی بودند تا بتوانند «دید هر پردازه از سیستم» را محدود کنند، بدون اینکه برای هر کاربر یک ماشین مجازی جدا بسازند. نتیجهی این تفکر، تولد اولین Namespace بود.
🔹 مرحله اول: Mount Namespace (سال 2002 – Linux 2.4.19)
اولین Namespace در لینوکس، Mount Namespace بود که در نسخهی 2.4.19 معرفی شد. این قابلیت به پردازهها اجازه میداد تا دید متفاوتی از فایلسیستم داشته باشند. مثلاً یک container میتوانست دایرکتوری / خودش را جداگانه mount کند، بدون تأثیر بر فایلسیستم اصلی.
mount –make-private /
ایدهی اصلی این بود که هر گروه از پردازهها بتوانند فضای فایلسیستم خود را ببینند، نه کل سیستم.
🔹 مرحله دوم: UTS Namespace (سال 2006 – Linux 2.6.19)
در نسخهی 2.6.19 کرنل لینوکس، نوع دیگری از Namespace معرفی شد: UTS Namespace یا UNIX Time-sharing System Namespace.
این Namespace اطلاعاتی مانند نام میزبان (hostname) و دامنهی سیستم (domainname) را برای هر محیط ایزوله کرد. در نتیجه، هر container میتوانست نام میزبان مخصوص خود را داشته باشد، بدون تداخل با سیستم اصلی.
hostname container1
🔹 مرحله سوم: IPC Namespace (سال 2006 – Linux 2.6.19)
در همان نسخه (۲.۶.۱۹)، کرنل ویژگی IPC Namespace را نیز اضافه کرد. این ویژگی مکانیزمهای ارتباط بین پردازهای (مثل message queue، semaphore و shared memory) را برای هر گروه از پردازهها جدا کرد.
پیش از آن، تمام پردازهها در یک فضای مشترک IPC کار میکردند، که میتوانست باعث برخورد دادهها شود.
ipcs -m
🔹 مرحله چهارم: PID Namespace (سال 2008 – Linux 2.6.24)
یکی از مهمترین تحولات در تاریخ Namespace، معرفی PID Namespace در کرنل ۲.۶.۲۴ بود. با این قابلیت، هر container جدول پردازهی مخصوص به خودش را داشت.
یعنی پردازهای که در سیستم اصلی PID=1000 داشت، ممکن بود در container با PID=1 نمایش داده شود. این ویژگی زیرساخت کلیدی اجرای init یا systemd در داخل containerها شد.
ps -ef
🔹 مرحله پنجم: Network Namespace (سال 2009 – Linux 2.6.29)
تا این مرحله، هنوز همهی containerها از کارت شبکهی میزبان استفاده میکردند. با معرفی Network Namespace، هر container میتوانست پشتهی شبکهی جداگانه داشته باشد: interfaceها، routing table، و حتی firewall خودش.
این ویژگی پایهی ساخت ابزارهایی مانند ip netns و در نهایت Docker networking شد.
sudo ip netns exec testns ip addr
🔹 مرحله ششم: User Namespace (سال 2013 – Linux 3.8)
در نسخهی ۳.۸ کرنل لینوکس، مفهوم User Namespace معرفی شد. این قابلیت انقلابی بود، چون برای اولینبار امکان اجرای container بهصورت غیر ریشهای (unprivileged) را فراهم کرد.
در User Namespace، هر پردازه میتواند UID (شناسه کاربر) متفاوتی در داخل و بیرون container داشته باشد. مثلاً پردازهای که در container با UID=0 (root) اجرا میشود، ممکن است در سیستم اصلی UID=1001 داشته باشد.
id
🔹 مرحله هفتم: Cgroup Namespace (سال 2016 – Linux 4.6)
در ادامه، Cgroup Namespace اضافه شد تا کنترل دقیقتری روی منابع در اختیار container قرار گیرد. این Namespace مشخص میکند که پردازهها چه منابعی (CPU، RAM، Disk I/O و …) را میبینند.
Cgroup در واقع یک سیستم مدیریت منابع است، اما Namespace مربوط به آن تعیین میکند هر پردازه فقط بخش خاصی از سلسلهمراتب Cgroup را مشاهده کند.
cat /proc/self/cgroup
🔹 مرحله هشتم: Time Namespace (سال 2020 – Linux 5.6)
آخرین نوع Namespace تا امروز، Time Namespace است که در نسخهی ۵.۶ معرفی شد. این ویژگی به پردازهها اجازه میدهد تا زمان سیستم (system clock) یا زمان مونوتونیک (monotonic clock) خودشان را داشته باشند.
این قابلیت در محیطهای شبیهسازی (sandbox) و تست نرمافزارهای حساس به زمان بسیار مفید است.
date
📅 جدول تکامل Namespaceها در نسخههای مختلف کرنل
| نوع Namespace | سال معرفی | نسخه کرنل | هدف اصلی |
|---|---|---|---|
| Mount | 2002 | 2.4.19 | ایزولهسازی فایلسیستم |
| UTS | 2006 | 2.6.19 | نام میزبان و دامنه |
| IPC | 2006 | 2.6.19 | ارتباط بین پردازهای |
| PID | 2008 | 2.6.24 | جدول پردازهها |
| Network | 2009 | 2.6.29 | پشته شبکه مجزا |
| User | 2013 | 3.8 | کاربران مستقل |
| Cgroup | 2016 | 4.6 | مدیریت منابع |
| Time | 2020 | 5.6 | زمان سیستم |
🌐 انواع Namespace در لینوکس
در کرنل لینوکس، مفهوم Namespace به هشت نوع اصلی تقسیم میشود که هرکدام یک بخش از سیستم را ایزوله میکنند. این Namespaceها، پایهی اصلی فناوریهای Container و Virtualization در سطح سیستمعامل هستند.
در این بخش، هر نوع Namespace را بهصورت جداگانه بررسی میکنیم: از تعریف تا پیادهسازی و مثال عملی با دستورات واقعی.
1️⃣ UTS Namespace
UTS Namespace (مخفف UNIX Timesharing System Namespace) مسئول جداسازی اطلاعات سطح سیستم مانند hostname و domainname است.
در سیستمهای چندکانتینری، هر container میتواند نام میزبان خود را داشته باشد بدون اینکه روی دیگران تأثیر بگذارد.
hostname containerA
uname -n
این دستور، یک محیط جدید با نام میزبان جداگانه میسازد.
2️⃣ IPC Namespace
IPC Namespace برای جداسازی مکانیزمهای ارتباط بین پردازهای (Inter-Process Communication) طراحی شده است، از جمله shared memory، semaphores و message queues.
این Namespace تضمین میکند که پردازههای containerها فقط به حافظه اشتراکی و صف پیام خودشان دسترسی دارند.
ipcs -m
3️⃣ PID Namespace
PID Namespace یکی از مهمترین بخشهای سیستم container است. این Namespace جدول پردازهها (Process IDs) را جدا میکند، بنابراین هر محیط میتواند پردازههای خودش را با PID مخصوص داشته باشد.
در این حالت، پردازهای که در سیستم اصلی PID=2000 دارد، ممکن است در container با PID=1 نمایش داده شود.
ps -ef
این مکانیزم برای اجرای init، systemd یا supervisor در هر container ضروری است.
4️⃣ Mount Namespace
Mount Namespace اولین نوع Namespace است که در کرنل لینوکس معرفی شد. این Namespace دید هر پردازه نسبت به فایلسیستم را تعیین میکند — یعنی هر گروه از پردازهها میتوانند ساختار mount جداگانهای داشته باشند.
مثلاً container میتواند دایرکتوری /var خودش را mount کند، بدون اینکه میزبان از آن مطلع شود.
mount –make-private /
mount -t tmpfs none /mnt
5️⃣ Network Namespace
Network Namespace یک پشتهی شبکهی جداگانه (network stack) برای هر محیط ایجاد میکند. هر Namespace شبکه، interfaceهای خودش، routing table و حتی firewall مستقل دارد.