🔧 چطور یک داکر برای خودمون بسازیم؟ – قسمت اول
در این مجموعه پستها قصد داریم با کنار هم گذاشتن اجزای پایه های لینوکس، یک container runtime مینیمال مشابه Docker بسازیم. تو این مسیر، با مفاهیم کلیدی مثل namespaceها، cgroups، mount isolation، و root filesystem کار میکنیم تا پایه لینوکس خودمون رو تقویت کنیم.
🧩 cgroups چیست و چرا مهم هست؟
در ساختار یک کانتینر، این قابلیت باعث میشه که:
1️⃣ یک کانتینر بیش از سهم خود از CPU یا RAM استفاده نکنه.
2️⃣ فشار زیاد از سوی یک کانتینر باعث اختلال در کل سیستم نشه.
3️⃣ مدیریت منابع میان چند کانتینر با دقت بیشتری انجام بشه.
✅ چه چیزهایی را میشه با اون کنترل کرد؟
در cgroup نسخه ۲ میتونیم انواع مختلفی از منابع رو محدود کنیم. به طور مثال:
1️⃣ با memory.max میتونیم حداکثر میزان RAM قابل استفاده رو تعیین کنیم. مثلاً مقدار 536870912 یعنی محدودیت ۵۱۲ مگابایت.
2️⃣ گزینه cpu.max برای کنترل میزان مصرف CPU استفاده میشه. مثلاً مقدار 50000 100000 به معنی استفاده از ۵۰٪ ظرفیت CPU هست.
3️⃣ با pids.max میتونیم تعداد پراسس هایی که داخل یک cgroup ایجاد میشن رو محدود کنیم. مثلاً مقدار 50 یعنی فقط ۵۰ پراسس مجاز هستن.
4️⃣ و در نهایت، با io.max میتونیم سرعت دسترسی به دیسک رو کنترل کنیم. مثلاً rbps=1048576 یعنی حداکثر سرعت خواندن از دیسک یک مگابایت بر ثانیه خواهد بود.
🧪 ایجاد یک cgroup
در این مرحله میخوایم بهصورت دستی یک cgroup بسازیم و محدودیت RAM را روی پراسس فعلی اعمال کنیم:
از این لحظه به بعد، پراسس فعلی فقطمجازه که از ۵۱۲ مگابایت RAM استفاده کنه.
🐳 و containerd کجای ماجراست؟
ابزارهای مدرنی مثل Docker، در پشت صحنه از
✍️ جمع بندی
در پست بعدی، در مورد namespaceها توضیح میدیم؛ ابزاری که باعث میشه پراسس ها بتونن محیط مجزای خودشون رو داشته باشن (مثلاً PID یا network مجزا).
اگر سوالی درباره cgroups یا محدودسازی منابع داشتید توی کامنتها با ما در میون بزارید.
➖➖➖➖➖➖➖➖➖➖
در این مجموعه پستها قصد داریم با کنار هم گذاشتن اجزای پایه های لینوکس، یک container runtime مینیمال مشابه Docker بسازیم. تو این مسیر، با مفاهیم کلیدی مثل namespaceها، cgroups، mount isolation، و root filesystem کار میکنیم تا پایه لینوکس خودمون رو تقویت کنیم.
🧩 cgroups چیست و چرا مهم هست؟
Control Groups
یا بهاختصار cgroups
مکانیزمی در لینوکس هست که اجازه میده میزان منابع مصرفی یک یا چند پراسس را محدود کنیم.در ساختار یک کانتینر، این قابلیت باعث میشه که:
1️⃣ یک کانتینر بیش از سهم خود از CPU یا RAM استفاده نکنه.
2️⃣ فشار زیاد از سوی یک کانتینر باعث اختلال در کل سیستم نشه.
3️⃣ مدیریت منابع میان چند کانتینر با دقت بیشتری انجام بشه.
✅ چه چیزهایی را میشه با اون کنترل کرد؟
در cgroup نسخه ۲ میتونیم انواع مختلفی از منابع رو محدود کنیم. به طور مثال:
1️⃣ با memory.max میتونیم حداکثر میزان RAM قابل استفاده رو تعیین کنیم. مثلاً مقدار 536870912 یعنی محدودیت ۵۱۲ مگابایت.
2️⃣ گزینه cpu.max برای کنترل میزان مصرف CPU استفاده میشه. مثلاً مقدار 50000 100000 به معنی استفاده از ۵۰٪ ظرفیت CPU هست.
3️⃣ با pids.max میتونیم تعداد پراسس هایی که داخل یک cgroup ایجاد میشن رو محدود کنیم. مثلاً مقدار 50 یعنی فقط ۵۰ پراسس مجاز هستن.
4️⃣ و در نهایت، با io.max میتونیم سرعت دسترسی به دیسک رو کنترل کنیم. مثلاً rbps=1048576 یعنی حداکثر سرعت خواندن از دیسک یک مگابایت بر ثانیه خواهد بود.
🧪 ایجاد یک cgroup
در این مرحله میخوایم بهصورت دستی یک cgroup بسازیم و محدودیت RAM را روی پراسس فعلی اعمال کنیم:
# ساخت دایرکتوری برای cgroup
sudo mkdir /sys/fs/cgroup/mycontainer
# تنظیم محدودیت حافظه (۵۱۲ مگابایت)
echo 536870912 | sudo tee /sys/fs/cgroup/mycontainer/memory.max
# افزودن پراسس جاری به این cgroup
echo $$ | sudo tee /sys/fs/cgroup/mycontainer/cgroup.procs
از این لحظه به بعد، پراسس فعلی فقطمجازه که از ۵۱۲ مگابایت RAM استفاده کنه.
🐳 و containerd کجای ماجراست؟
ابزارهای مدرنی مثل Docker، در پشت صحنه از
containerd
برای اجرای کانتینرها استفاده میکنن. این ابزار مسئولیت تنظیم cgroupها، namespaceها و mountها را بر عهده داره. ما اما در این مجموعه، سعی میکنیم این مفاهیم رو بهصورت مستقیم و بدون واسطه تجربه کنیم.✍️ جمع بندی
در پست بعدی، در مورد namespaceها توضیح میدیم؛ ابزاری که باعث میشه پراسس ها بتونن محیط مجزای خودشون رو داشته باشن (مثلاً PID یا network مجزا).
اگر سوالی درباره cgroups یا محدودسازی منابع داشتید توی کامنتها با ما در میون بزارید.
#️⃣ #linux #containers #cgroups #build_your_own_docker
➖➖➖➖➖➖➖➖➖➖
🐧 CHANNEL | GROUP
🔥4⚡1
🔧 چطور یک داکر برای خودمون بسازیم؟ – قسمت دوم
در قسمت قبل با cgroups آشنا شدیم و دیدیم چطور میتونیم مصرف منابع مثل RAM و CPU رو برای یک پراسس محدود کنیم. حالا وقتشه به سراغ دومین جزء اصلی کانتینرها بریم:
🧩 namespace چیه و چرا مهمه؟
Namespaceها مکانیزمی در کرنل لینوکس هستن که اجازه میدن یک پراسس (یا گروهی از اونها) نمای متفاوتی از بخشهای مختلف سیستم ببینن. به زبان سادهتر، با namespaceها میتونیم یک محیط ایزوله برای پراسسها بسازیم.
مثال:
1️⃣ هر کانتینر PIDهای خودش رو داشته باشه و PIDهای بیرونی رو نبینه.
2️⃣ فضای شبکهی مخصوص خودش رو داشته باشه، با IP و interface جدا.
3️⃣ فقط فایلهای خاصی از سیستم فایل رو ببینه، نه کل چیزی که روی سیستم هست.
📦 چه namespaceهایی به صورت دیفالت وجود داره؟:
-
-
-
-
-
-
-
🧪 چطور با یک namespace جدید پراسس هارو ایزوله کنیم؟
با استفاده از ابزار
حالا توی این شِل جدید اگر
🧩 چطور با cgroup ترکیبش کنیم؟
وقتی namespace رو با cgroup ترکیب کنیم، عملاً داریم پایهی یک کانتینر واقعی رو میسازیم: یه محیط ایزوله که هم منابعش محدوده، هم چیزی از بیرون نمیبینه.
🎯 مثال:
حالا که داخل شل جدید هستیم، میخوایم این پراسس جدید رو به cgroupای که قبلاً ساختیم اضافه کنیم. همونطور که گفتیم، باید این کار از داخل شل انجام بشه چون فقط از داخل میتونیم بهراحتی به PID فعلی (با $$) دسترسی داشته باشیم:
حالا برای اینکه چک کنیم محدودیت ها اعمال شدن از این دستور داخل شل استفاده میکنیم:
با این کار، شل جدید ما (و تمام پراسسهایی که از داخل اون اجرا میشن) تحت محدودیتهایی که برای cgroup تعریف کردیم قرار میگیرن مثل محدودیت RAM، CPU یا I/O. به این ترتیب، کمکم داریم ساختار اولیه یک container ساده رو شکل میدیم.
✍️ جمعبندی
در این پست با namespaceها آشنا شدیم و دیدیم چطور میتونن محیط یک پراسس رو از بقیهی سیستم جدا کنن به صورت عملی یه کانتینر خیلی جمع و جور ساختیم. در قسمت بعد، سراغ root filesystem و mount namespace میریم تا بتونیم فایلسیستم اختصاصی برای کانتینرمون بسازیم.
اگه سوالی درباره namespaceها داشتید توی کامنت ها با ما در میون بزارید.
➖➖➖➖➖➖➖➖➖➖
در قسمت قبل با cgroups آشنا شدیم و دیدیم چطور میتونیم مصرف منابع مثل RAM و CPU رو برای یک پراسس محدود کنیم. حالا وقتشه به سراغ دومین جزء اصلی کانتینرها بریم:
🧩 namespace چیه و چرا مهمه؟
Namespaceها مکانیزمی در کرنل لینوکس هستن که اجازه میدن یک پراسس (یا گروهی از اونها) نمای متفاوتی از بخشهای مختلف سیستم ببینن. به زبان سادهتر، با namespaceها میتونیم یک محیط ایزوله برای پراسسها بسازیم.
مثال:
1️⃣ هر کانتینر PIDهای خودش رو داشته باشه و PIDهای بیرونی رو نبینه.
2️⃣ فضای شبکهی مخصوص خودش رو داشته باشه، با IP و interface جدا.
3️⃣ فقط فایلهای خاصی از سیستم فایل رو ببینه، نه کل چیزی که روی سیستم هست.
📦 چه namespaceهایی به صورت دیفالت وجود داره؟:
-
pid
: برای جداسازی فضای پراسس ها (Process IDs) -
net
: برای جداسازی تنظیمات شبکه مثل interface، routing و ... -
mnt
: برای مدیریت جداگانهی mountها و filesystem -
uts
: برای جداکردن hostname و domainname -
ipc
: برای جداکردن فضای ارتباط بین پردازهها (مثل shared memory) -
user
: برای جداسازی فضای کاربری و دسترسیها -
cgroup
: برای اینکه هر پراسس فقط cgroup خودش رو ببینه 🧪 چطور با یک namespace جدید پراسس هارو ایزوله کنیم؟
با استفاده از ابزار
unshare
میتونیم پراسس جدیدی بسازیم که در namespaceهای جداگانه اجرا میشه. مثلاً برای اجرای یک شِل با PID namespace جداگانه:sudo unshare --pid --fork --mount-proc bash
حالا توی این شِل جدید اگر
ps
بگیریم، فقط پراسس خودمون رو میبینیم و PID ما از دید درون این namespace معمولاً 1
خواهد بود. 🧩 چطور با cgroup ترکیبش کنیم؟
وقتی namespace رو با cgroup ترکیب کنیم، عملاً داریم پایهی یک کانتینر واقعی رو میسازیم: یه محیط ایزوله که هم منابعش محدوده، هم چیزی از بیرون نمیبینه.
🎯 مثال:
# ساخت cgroup با محدودیت RAM
sudo mkdir /sys/fs/cgroup/mycontainer
echo 268435456 | sudo tee /sys/fs/cgroup/mycontainer/memory.max # ۲۵۶ مگابایت RAM
# اجرای یک شِل در namespace جدید با PID مجزا
sudo unshare --pid --fork --mount-proc bash
حالا که داخل شل جدید هستیم، میخوایم این پراسس جدید رو به cgroupای که قبلاً ساختیم اضافه کنیم. همونطور که گفتیم، باید این کار از داخل شل انجام بشه چون فقط از داخل میتونیم بهراحتی به PID فعلی (با $$) دسترسی داشته باشیم:
echo $$ | sudo tee /sys/fs/cgroup/mycontainer/cgroup.procs
حالا برای اینکه چک کنیم محدودیت ها اعمال شدن از این دستور داخل شل استفاده میکنیم:
cat /sys/fs/cgroup/mycontainer/memory.max
با این کار، شل جدید ما (و تمام پراسسهایی که از داخل اون اجرا میشن) تحت محدودیتهایی که برای cgroup تعریف کردیم قرار میگیرن مثل محدودیت RAM، CPU یا I/O. به این ترتیب، کمکم داریم ساختار اولیه یک container ساده رو شکل میدیم.
✍️ جمعبندی
در این پست با namespaceها آشنا شدیم و دیدیم چطور میتونن محیط یک پراسس رو از بقیهی سیستم جدا کنن به صورت عملی یه کانتینر خیلی جمع و جور ساختیم. در قسمت بعد، سراغ root filesystem و mount namespace میریم تا بتونیم فایلسیستم اختصاصی برای کانتینرمون بسازیم.
اگه سوالی درباره namespaceها داشتید توی کامنت ها با ما در میون بزارید.
#️⃣ #linux #containers #namespaces #build_your_own_docker
➖➖➖➖➖➖➖➖➖➖
🐧 CHANNEL | GROUP
🔥5