ایمان غلامی
ایمان غلامی
خواندن ۱۱ دقیقه·۱ سال پیش

بررسی عمیق تر container ها و namespace ها در کرنل

خب Linux namespaces چیه ؟

راستش چند وقتی هست دارم در مورد مفاهیم پایه ای و به صورت Deep Dive در مورد کانتینر ها مطالعه میکنم اگه شما هم دنبال این هستید که بفهمید اون پایینا چه خبره ? اول بیایید این مفاهیم و حلش کنیم چون همه جا تو بحث کانتینر لازمتون میشه.

اول از همه این دوتا تعریف از container رو از اقای Scott McCarty و julia evans ببینیم :

Containers do not run ON docker. Containers are processes - they run on the Linux kernel. Containers are Linux
The word “container” doesn’t mean anything super precise. Basically there are a few new Linux kernel features (“namespaces” and “cgroups”) that let you isolate processes from each other. When you use those features, you call it “containers”.

پس همونجوری که متوجه شدید از این تعریف ها ، کانتینر چیزی جز یه پراسس ایزوله رو کرنل لینوکس نیست ? و این مقاله هم در مورد namespace ها هست که یه فیچر رو کرنل لینوکس هستند و پراسس ها رو ایزوله میکنن که تو ادامه بیشتر توضیح میدیم.

اینم بگم این لینک اصلی این مقاله هست

[https://www.redhat.com/sysadmin/7-linux-namespaces]

خب اول از همه بریم ببینیم تعریف namespace چیه ؟ تو ویکی پدیا اینو نوشته :

Namespaces are a feature of the Linux kernel that partitions kernel resources such that one set of processes sees one set of resources while another set of processes sees a different set of resources. The feature works by having the same namespace for a set of resources and processes, but those namespaces refer to distinct resources.

من ترجمش هم میکنم فقط اینو بگم که ترجمه بر اساس درک مطلب من بوده اگه ایرادی داشت میتونید بگید درستش کنم ?

خب namespace ها یه ویژگی تو کرنل لینوکس هستن که بخش بندی میکنن منابع کرنل رو . به این صورت که دسته‌ای از فرآیندها دسترسی به یک سری منابع دارند، در صورتی که دسته‌ای دیگر از فرآیندها به منابعی متمایز دسترسی دارند. و این ویژگی اینجوری عمل می کنه که یه namespace برای گروهی از منابع و فرآیندها در نظر گرفته میشه اما این namespace مشترک به منابع متفاوتی ارجاع میده فرآیندها رو.

خب حالا تعریف بالا رو شاید یه سریا خیلی زود بفهمن و متوجه بشن اما واسه این که ما خودمون بهتر بفهمیم آقای Steve Ovensv یکی از خوبای تیم ردهت اومده یه مثال زده: میگه فرض کنید ، که تو یه مجتمع زندگی می کنید و این مجتمع از دوتا ساختمون مجزا تشکیل شده که هر ساختمون ورودی، آدرس خیابون، طبقات و آسانسور مخصوص به خودش رو داره حتی اسم مخصوص خودشون هم دارن مثلا یکی ساختمان یک هست،یکی ساختمون دو هست . اما پارکینگ، سالن بدنسازی، استخر و اتاق های مشترک در هر دو ساختمون مشترک هستند. ساکنان هر دو ساختمان می توانند از این امکانات استفاده کنند. حالا با این که این دوتا ساختمون مجزا از هم هستن اما با این حال جفتشون تو یه مجتمع فیزیکی هستند .

حالا میخوایم هفت مورد پراستفاده namespace ها رو به صورت خلاصه بگیم:

Process isolation (PID namespace)

خب PID or Process ID چی هست ؟ خیلی کوتاه و مختصر بخوام بگم لینوکس به هر پراسس یه شماره اختصاص میده که بهش میگن PID و این میتونه به سیستم کمک کنه تا بهتر بتونه یه تسک خاص و ردیابی کنه ، مثلا شما وقتی یه فایرفاکس و رو سیستم خودتون اجرا می کنید یه PID بهش اختصاص داده میشه .

خب بریم یه مثال بزنیم :

شما فرض کنید دوتا مرورگر رو سیستم خودتون دارید یکی فایرفاکس اون یکی هم گوگل کروم یا هر چیز دیگه ای . و این دوتا مرورگر و همزمان باز می کنید و جفتشون از یه search engine استفاده می کنن تو یکی سرچ میزنید عکس گربه تو یکی هم عکس سگ و حالا هر دوتا مرورگر درخواست مشابهی و سمت یه وبسایت ارسال می کنند . حالا کامپیوتر چی جوری اطمینان حاصل کنه که نتیجه درست و به مرورگر درست برگردونه ؟ یکی از روش‌های اصلی ردیابی درخواست‌های هر PID، ردیابی درخواست‌ها و سپس بازگرداندن نتایج به فرآیند درخواست‌کننده است.

خب ! حالا شاید با خودتون بگید الان این ربطش به ساختمون و namespace چی بود ؟ که الان میگم ?
شما فرض کنید میخواید کپی های یکسانی از یه نرم افزار و رو سیستم خودتون جرا کنید . بعضی نرم افزارها اینجوری نوشته شده اند که شما فقط میتونید همزمان یه نسخه از اونارو روی سیستم اجرا کنید . یعنی وقتی شما یک نسخه از نرم‌افزار را باز می‌کنید، نمی‌توانید نسخه دوم همان نرم‌افزار را باز کنید. نرم‌افزار به گونه‌ای طراحی شده که فقط اجازه می‌دهد یک نسخه از آن در یک زمان اجرا شود.

خب یکی از راه حل های این کار همون کانتینر ها هستند که ما داریم الان در مورد کانسپتش صحبت میکنیم که چی جوری این اتفاق میوفته ، پس برای این کار بهتر هست که اون PID رو ایزوله کنیم تا به اون چیزی که خارج از فرآیند خوش میگذره آگاه نباشه . پس ایزوله کردن فرآیند به این صورت میتونه تو راه حل این کار به ما کمک کنه .

حالا بریم سراغ مثال ما فرض کنید همه واحدها اون ساختمون های مجتمع یه فرآیند هستند که ایزوله شدن و اگه ایزوله نباشن مثلا همزمان هر واحد ساختمونی از داخل یه واحد ساختمون دیگه اگاه باشه ، مثلا همزمان چندین تلوزیون روشن باشه به معنای واقعی کلمه conflict رخ میده. حالا namespace اجازه میده که هر واحد ساختمون ایزوله بشه و هر کی داخل اون هر کاری میخواد بکنه و تداخلی هم صورت نگیره چون افراد اون واحد ساختمون ایزوله شده دیگه واسشون مهم نیست که بیرون از اون فضای ایزوله چه برنامه تلوزیونی داره پخش میشه . برنامه خودشونو مبینن .

Network interfaces (net namespace)

هر کامپیوتری که به یه شبکه متصل هست مثل اینترنت یه IP آدرس نیاز داره . این IP Address یه شماره منحصر به فرد برای کامپیوتر هست. وقتی شما به منابع خاصی دسترسی پیدا می کنید مثل یک وب سرور یا یک سرور بازی یا یک ایمیل سرور همه ی این سرویس ها میتونن روی یک هاست به شما خدمات بدن اما روی پورت های مختلف. مثلا وب سرور روی پورت ۸۰ یا ۴۴۳ ، سرور بازی روی پورت ۸۸۸۸ و یا ایمیل سرور روی پورت ۲۵ . و زمانی که شما داخل مرورگر تایپ می کنید https://websiteaddress کامیپیوتر میاد اونو به صورت xxxx.xxxx.xxxx.xxxx روی یه پورت خاص مثلا 443 ترجمه میکنه . و اون سرور مقصد هم جواب به IP مبدا میفرسته . خب همونطوری که قبلا اشاره کردیم بعضی تکنولوژی ها از چندین نمونه از نرم افزار در حال اجرا به طور همزمان پشتیبانی نمی کنند. حالا برخلاف PID isolation ، زمانی که یه نرم افزار مثل ایمیل سرور Connection دریافت میکنه انتظار میره که روی پورت خاصی باشه بنابراین اگه حتی ما بیایم PID و ایزوله هم کنیم سرور ایمیل فقط یه نمونه در حال اجرا خواهد داشت چون که پورت ۲۵ در حال استفاده هست . حالا Network namespaces اجازه میده که فرآیند های داخل هر namespace instance به یه IP آدرس جدید و همچنین رنج کامل پورت ها دسترسی داشته باشه . و به این صورت شما میتوانید چندتا ورژن مختلف از ایمیل سرور و روی پورت ۲۵ اجرا کنید بدون conflict خاصی .

خب حالا باز بریم سراغ مثال ساختمون خودمون ، ما گفتیم که این ساختمون ها به یه مجتمع فیزیکی متصل هستند . و یه تعداد یکسانی فضای مسکونی در هر کدوم از ساختمون ها وجود داره و علاوه بر اون شماره گذاری واحد های دوتا ساختمون هم یکسان انجام شده . مثلا هر دوتا ساختمون واحد ۷۰۷ دارند . تو این مثال IP Address همون آدرس خیابون ساختمون ها هست و پورت هم شماره هر واحد یا آپارتمان اون ساختمون حالا همونجوری که ما گفتیم هر ساختمون آپارتمانی بخشی از همون مجتمع فیزیکی هست و اون مجتمع فیزیکی هم ادرسش مثلا 123 Fake Street هست حالا یه شرکت میخواد به واحد ۷۰۷ به اقای استیو قبض بفرسته و این آدرس ثبت می کند روی قبض

Steve Ovens, 123 Fake Street Unit 707

حالا امکان داره که این قبض هیچوقت به دست آقای استیو نرسه چون تو اون مجتمع ممکنه ]چندتا ساختمون باشه که واحد ۷۰۷ داشته باشه حالا این net namespace اجازه میده ما به هر کدوم از این ساختمون های یه Ip Address منحصر به فرد بدیم روی یه مجتمع فیزیکی یکسان . حالا دیگه راحت میشه گفت مثلا ساختمون اول ادرسش 123 Fake Street هست ساختمون دوم 125 Fake Street روی یه مجتمع فیزیکی یکسان .

- Unix Timesharing System (uts namespace)

این مورد و خیلی خلاصه بخوام بگم ، همونجوری که قبلا اشاره کردیم ارتباطات ما با یه هاست از طریق IP و PORT انجام میشه اما خب این خیلی راحت میشه که به یه پراسس ایزوله یه نام هم اضافه کنیم تا دیگه نیاز نباشه برای ارتباط باهاش از Ip , Port استفاده کینم

مثالش هم تو کانتینر ها می بینیم که وقتی میخوایم یه کانتینر ایجاد کنیم معمولا یه اسم واسش اننتخاب می کنیم که ارتباط باهاش راحت باشه علاوه بر اون اگه ip هر دفه عوض بشه نیاز نباشه ما اونو به خاطر بسپاریم

تو مثال ساختمون هم اینجوری میشه گفت که یه نفر وقتی از ما میپرسه که کجا زندگی میکنی شاید واسه ما راحت تر باشه خیلی خلاصه بگیم City Place تا بخوایم ادرس خیابون و کوچه و شماره واحد اون ساختمون و بدیم . پس uts namespace به ما اجازه میده ما چندتا hostname روی یه سینگل host داشته باشیم .

User namespace

هر سیستم کامپیوتری یه راهی برای تشخیص این که صاحب یه فایل کی هست و داره . و خب این کار باعث میشه که بتونیم به فایل های حساس دسترسی های خاص و محدود بدیم و خب یوزر های مختلف یه سیستم هم نمیتونن به فایل های یکدیگر دسترسی داشته باشن مگر در موارد خاص که اجازه داده بشه . یوزر ه وقتی لاگین میکنه یه اسمی داره حالا هر چیزی میتونه باشه ترکیبی از یه سری کاراکتر هست اما هر یوزر یه UID خاص داره مثلا یوزر ali یه UID داره به این عدد 1001 حالا واسه ردیابی درست پرمیشن های یه فایل این ali مپ میشه به 1001 و حالا شما اگه این یوزنیم و تغییر هم بدید هیچ اتفاق برای دسترسی به فایل ها نمیوفته مثلا ali بشه ahmad بازم UID همون هست .

مثالش تو ساختمون مثل صندوق پست هست . مثلا شما شماره صندوق پستی ک دارید ۷۰۷ هست حالا از این به بعد میخواید اونو تغییر بدید و بزارید ۷۰۲ درسته اون شماره یا همون یوزرنیم تغییر میکنه اما دسترسی افرادی که به اون صندوق دسترسی داشتن عوض نمیشه و تغییری نمیکنه .

Mount (mnt namespace)

خب mount namespace برای ایزوله کردن mount point استفاده میشه به این صورت که پراسس ها در namespace های مختلف فایل های همدیگرو نتونن بیینن . یه چی مثل مفهموم chroot .


خب بریم از مثال ساختمون یه خورده فاصله بگریم و یه مثال دیگه واسه این مفهموم بزنیم :


فرض کنید دو نفر در یک خانه زندگی می کنند. این دو نفر ممکن است یک اتاق مشترک داشته باشند، اما آنها همچنین ممکن است اتاق های خواب جداگانه ای داشته باشند. اتاق خواب های جداگانه داشته باشند . یا دو نفر باهم ازدواج کردند امکان داره خیلی چیزای مشترک داشته باشن و در عین حال بعضی چیز های شخصی هم داشته باشند .


پس namespace اجازه میده حتی اگه دوتا فرآیند داخل یه سیستم باشن طوری ایزوله بشن که هر کدوم فایل سیستم خودشونو داشته باشن در حالی که از منابع اون سیستم هم مینونن استفاده کنن .

Interprocess communication (IPC)

این namespace یه مقداری کارش پیچیده هست که بعدا تو یه پست دیگه مفصل راجبش توضیح میدم . اما به صورت کلی IPC مدیریت میکنه ارتباط بین پراسس ها رو با استفاده از shared memory , message queues و سمافور ها . حالا اگه نمیدونید اینا چیه نگران نباشید بعدا توضیح میدیم همرو .

حالا برای این که یه مقدار بفهمیم داره چیگار میکنه یکی از ابعادش که همون shared memory هست با یه مثال بررسی میکنیم : فرض کنید دو برنامه وجود دارد، برنامه A و برنامه B. برنامه A نیاز به ارسال داده به برنامه B دارد. برنامه A می تواند از حافظه اشتراکی برای این کار استفاده کند.

ابتدا، برنامه A یک ناحیه حافظه اشتراکی ایجاد می کند. سپس، برنامه A داده ها را به ناحیه حافظه اشتراکی می نویسد. در نهایت، برنامه A برنامه B را مطلع می کند که داده ها در ناحیه حافظه اشتراکی موجود است. برنامه B می تواند داده ها را از ناحیه حافظه اشتراکی بخواند. هنگامی که برنامه B داده ها را خواند، می تواند ناحیه حافظه اشتراکی را آزاد کند.

نکته پایانی

خب تو این مقاله یه بررسی اجمالی در مورد namespace ها کردیم و متوجه شدیم که تا حدودی namespace چی جوری یه فرآیند و ایزوله میکنه ، و یه تعریف هم از کانتینر ها گفتم . تو پست های بعدی سعی میکنم که به صورت دستی یه کانتینر ایجاد کنیم با استفاده از همین namespace ها خوندیم البته یه سری نکات دیگه هم هست که باید بدونیم در مورد کانتینر ها . امیدوارم که این مطالب مفید باشه .?

namespace ‌هاکانتینرداکرdokcercontainer
علاقه مند به تکنولوژی
شاید از این پست‌ها خوشتان بیاید