Product SiteDocumentation Site

12.2. مجازی‌سازی

مجازی‌سازی یکی از بزرگترین پیشرفت‌های علوم رایانه در سال‌های اخیر است. این عبارت شامل چندین مفهوم انتزاعی و تکنیکی است که در شبیه‌سازی رایانه‌های مجازی به طوری که مستقل از سخت‌افزار واقعی عمل می‌کنند. یک سرور فیزیکی می‌تواند شامل چندین سرور مجازی باشد که جدا از یکدیگر فعالیت می‌کنند. برنامه‌های کاربردی آن بسیار هستند که از این انزوا مشتق می‌شوند: برای نمونه، محیط‌های آزمایشی همراه با پیکربندی‌های متفاوت یا جداسازی سرویس‌های میزبانی بین چندین ماشین مجازی برای امنیت.
راهکارهای گوناگون مجازی‌سازی هر کدام با نقاط قوت و ضعف خود وجود دارند. تمرکز این کتاب روی Xen، LXC و KVM است اما سایر پیاده‌سازی‌های قابل ذکر عبارتند از:

12.2.1. Xen

Xen یک راهکار “paravirtualization” است که شامل یک لایه انتزاعی سبک به نام “hypervisor” می‌باشد که بین سخت‌افزار و سیستم‌های بالایی قرار می‌گیرد؛ این لایه مانند یک داور دسترسی از ماشین‌های مجازی به سخت‌افزار را کنترل می‌کند. اگرچه، تنها شامل چند دستورالعمل کوتاه است، باقی عملیات به طور مستقیم از طرف سخت‌افزار و به نیابت از سیستم‌های دیگر انجام می‌شوند. مزیت اصلی آن این است که عملکرد کاهش نمی‌یابد و سیستم‌های تقریبا با سرعت اصلی سخت‌افزار اجرا می‌شوند؛ اشکال اصلی آن این است که کرنل‌های سیستم عامل‌ها به منظور استفاده از hypervisor باید سازگار با Xen باشند.
بیایید چند عبارت را بررسی کنیم. hypervisor پایین‌ترین لایه است که به صورت مستقیم روی سخت‌افزار اجرا می‌شود، حتی پایین‌تر از کرنل. این hypervisor می‌تواند سایر نرم‌افزارها را درون چندین دامنه قرار دهد، که می‌توانند به عنوان ماشین‌های مجازی دیده شوند. یکی از این دامنه‌ها (اولین آن‌ها که آغاز می‌شود) به عنوان dom0 شناخته می‌شود و نقش ویژه‌ای دارد، چرا که تنها این دامنه می‌تواند hypervisor و اجرای سایر دامنه‌ها را کنترل کند. سایر دامنه‌ها به عنوان domU شناخته می‌شوند. به عبارت دیگر، و از دید کاربر، dom0 به عنوان “میزبان” برای سایر سیستم‌های مجازی عمل می‌کند در صورتی که domU به عنوان یک “میهمان” دیده می‌شود.
استفاده از Xen تحت دبیان نیازمند سه مولفه است:
  • خود hypervisor. با توجه به سخت‌افزار موجود، بسته مناسب آن یکی از گزینه‌های xen-hypervisor-4.4-amd64، xen-hypervisor-4.4-armhf یا xen-hypervisor-4.4-arm64 خواهد بود.
  • کرنلی که روی آن hypervisor اجرا می‌شود. هر کرنل جدیدتر از ۳.۰ اینکار را انجام می‌دهد، از جمله ۳.۱۶ موجود در Jessie.
  • معماری i386 همچنین نیازمند یک کتابخانه استاندارد است که بتواند از اصلاحیه‌های موجود در Xen بهره‌مند شود؛ این کتابخانه در بسته libc6-xen موجود است.
به منظور اینکه انتخاب این مولفه‌ها بدون دردسر انجام شود، چندین بسته کاربردی (از جمله xen-linux-system-amd64) ایجاد شده‌اند؛ این بسته‌ها با ترکیب خوبی از hypervisor مناسب و بسته‌های کرنل آن قرار گرفته‌اند. hypervisor همچنین شامل بسته xen-utils-4.4 است که ابزار لازم برای کنترل آن از طریق dom0 را فراهم می‌آورد. این عمل در حقیقت کتابخانه استاندارد را نصب می‌کند. طی نصب این بسته‌ها، اسکریپت‌های پیکربندی همچنین یک مدخل درون منوی راه‌اندازی Grub ایجاد می‌کنند تا کرنل انتخابی برای آغاز dom0 مشخص گردد. به یاد داشته باشید که این مدخل معمولا به عنوان گزینه اول در فهرست قرار نمی‌گیرد، به همین منظور به صورت پیشفرض انتخاب نمی‌گردد. اگر این عملکرد مطلوب شما نباشد، دستورات زیر می‌توانند آن را تغییر دهند:
# mv /etc/grub.d/20_linux_xen /etc/grub.d/09_linux_xen
# update-grub
زمانی که این پیشنیازها نصب شوند، گام بعدی آزمایش عملکرد خود dom0 است؛ این عمل شامل راه‌اندازی مجدد hypervisor و کرنل Xen می‌باشد. سیستم باید به شیوه استاندارد خود راه‌اندازی شده، همراه با چندین پیام که طی گام‌های اولیه راه‌اندزای در کنسول نمایش می‌یابند.
اکنون زمان آن فرا رسیده است که با استفاده از ابزار موجود در xen-tools به نصب سیستم‌های کاربردی روی domU بپردازیم. این بسته شامل دستور xen-create-image می‌باشد که تقریبا این فرآیند را خودکارسازی می‌کند. تنها پارامتر ضروری آن --hostname است که نام domU را مشخص می‌کند؛ سایر گزینه‌ها نیز مهم هستند ولی می‌توانند درون فایل پیکربندی /etc/xen-tools/xen-tools.conf قرار بگیرند که نبود آن‌ها خطایی را در هنگام اجرای دستور صادر نمی‌کند. بنابراین مهم است که محتوای این فایل را قبل از ایجاد هر image بررسی کرده یا از پارامترهای اضافی هنگام فراخوانی xen-create-image استفاده کنیم. پارامترهای مهم قابل ذکر عبارتند از:
  • --memory، برای مشخص کردن میزان RAM اختصاص یافته به سیستم جدید؛
  • --size و --swap، برای تعریف اندازه "دیسک‌های مجازی" موجود برای domU؛
  • --debootstrap، برای نصب شدن سیستم جدید با استفاده از debootstrap؛ در این مورد، از گزینه --dist اغلب استفاده می‌شود (همراه با نام یک توزیع مانند jessie).
  • --dhcp بیان می‌کند که پیکربندی شبکه domU باید از طریق DHCP انجام شود در صورتی که --ip امکان استفاده از نشانی ایستای IP را فراهم می‌کند.
  • در انتها، از یک روش ذخیره‌سازی به منظور ایجاد image استفاده کرد (آن‌هایی که به عنوان درایوهای هارد دیسک از domU در نظر گرفته می‌شوند). ساده‌ترین روش، با توجه به گزینه --dir، ایجاد یک فایل در dom0 به ازای هر دستگاه domU فراهم‌کننده آن است. برای سیستم‌هایی که از LVM استفاده می‌کنند، گزینه جایگزین استفاده از --lvm است، که همراه با نام یک گروه آرایه آورده می‌شود؛ سپس xen-create-image اقدام به ایجاد یک گروه منطقی درون آرایه‌ها می‌کند که این گروه منطقی به عنوان یک درایو هارد دیسک به domU معرفی می‌گردد.
زمانی که این انتخاب‌ّها صورت گیرد، می‌توانیم image خود را برای domU بعدی در Xen ایجاد کنیم:
# xen-create-image --hostname testxen --dhcp --dir /srv/testxen --size=2G --dist=jessie --role=udev

[...]
General Information
--------------------
Hostname       :  testxen
Distribution   :  jessie
Mirror         :  http://ftp.debian.org/debian/
Partitions     :  swap            128Mb (swap)
                  /               2G    (ext3)
Image type     :  sparse
Memory size    :  128Mb
Kernel path    :  /boot/vmlinuz-3.16.0-4-amd64
Initrd path    :  /boot/initrd.img-3.16.0-4-amd64
[...]
Logfile produced at:
         /var/log/xen-tools/testxen.log

Installation Summary
---------------------
Hostname        :  testxen
Distribution    :  jessie
MAC Address     :  00:16:3E:8E:67:5C
IP-Address(es)  :  dynamic
RSA Fingerprint :  0a:6e:71:98:95:46:64:ec:80:37:63:18:73:04:dd:2b
Root Password   :  adaX2jyRHNuWm8BDJS7PcEJ
اکنون دارای یک ماشین مجازی هستیم که اجرا نمی‌شود (و تنها از فضای موجود در هارد دیسک dom0 استفاده می‌کند). البته که می‌توانیم با استفاده از پارامترهای گوناگون دیگر image بیشتری بسازیم.
قبل از اینکه این ماشین‌های مجازی را روشن کنیم باید راجع به چگونگی دسترسی به آن‌ها تصمیم بگیریم. آن‌ها می‌توانند به عنوان ماشین‌های ایزوله شده تنها از طریق کنسول سیستم خود تعریف شوند، اما این روش به ندرت از الگوی کارکرد تبعیت می‌کند. اکثر مواقع، یک domU به عنوان یک سرور راه دور در نظر گرفته می‌شود که تنها از طریق یک شبکه قابل دسترسی است. با این حال، اختصاص یک کارت شبکه به هر domU ممکن است مناسب نباشد؛ به همین دلیل است که Xen امکان ایجاد رابط‌های مجازی که هر دامنه قادر به مشاهده و استفاده استاندارد از آن‌ها باشد را می‌دهد. به یاد داشته باشید که این کارت‌ها، با وجود مجازی بودن، تنها زمانی مفید هستند که به یک شبکه متصل گردند. Xen دارای چندین مدل شبکه برای این منظور است:
  • ساده‌ترین مدل bridge است؛ تمام کارت‌های شبکه eth0 (در سیستم‌های dom0 و domU) طوری عمل می‌کنند گویی به سوئیچ اصلی Ethernet متصل شده‌اند.
  • سپس مدل routing قرار دارد، به صورتی که dom0 به عنوان یک مسیریاب میان سیستم‌های domU و شبکه خارجی (فیزیکی) قرار می‌گیرد.
  • در نهایت، در مدل NAT، dom0 بین سیستم‌های domU و باقی شبکه قرار می‌گیرد، اما سیستم‌های domU به صورت مستقیم از خارج قابل دسترس نیستند و ترافیک از طریق ترجمه نشانی شبکه یا NAT با استفاده از dom0 انتقال می‌یابد.
این سه مدل شبکه دارای تعدادی رابط با نام‌های نامتعارف هستند از جمله vif*، veth*، peth* و xenbr0. hypervisor موجود در Xen با توجه به لایه تعریف شده آن‌ها را مرتب‌سازی می‌کند که این کار با استفاده از ابزارهای سمت-کاربر صورت می‌گیرد. از آنجا که مدل‌های NAT و routing تنها برای موارد خاص کاربرد دارند، تنها به بررسی مدل bridge می‌پردازیم.
پیکربندی استاندارد بسته‌های Xen تغییری در پیکربندی شبکه در کل سیستم ایجاد نمی‌کند. با این حال، فرآیند پس‌زمینه xend طوری پیکربندی شده است تا رابط‌های مجازی شبکه را با هر شبکه bridge از پیش موجود یکپارچه سازد (در صورت وجود چندین bridge گزینه xenbr0 اولویت می‌یابد). برای اینکار نیازمند برپایی یک bridge در /etc/network/interfaces هستیم تا مدخل موجود eth0 جایگزین گردد (که نیازمند نصب بسته bridge-utils می‌باشد، به همین دلیل است که بسته xen-utils-4.4 توصیه می‌شود):
auto xenbr0
iface xenbr0 inet dhcp
    bridge_ports eth0
    bridge_maxwait 0
پس از راه‌اندازی مجدد و اطمینان از اینکه bridge به طور خودکار ایجاد شده است، اکنون می‌توانیم domU را با استفاده از ابزار کنترلی Xen، به خصوص دستور xl، آغاز کنیم. این دستور امکان چندین تغییر روی دامنه‌ها را همراه با فهرست‌سازی آن‌ها و آغاز/پایان هر کدام فراهم می‌آورد.
# xl list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0   463     1     r-----      9.8
# xl create /etc/xen/testxen.cfg
Parsing config from /etc/xen/testxen.cfg
# xl list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0   366     1     r-----     11.4
testxen                                      1   128     1     -b----      1.1
به یاد داشته باشید که domU ایجاد شده بنام ... از حافظه واقعی گرفته شده از RAM که معمولا برای dom0 در نظر گرفته می‌شود، استفاده می‌کند و نه یک حافظه شبیه‌سازی شده. بنابراین هنگام راه‌اندازی یک سرور مبتی بر Xen باید دقت عمل در تخصیص حافظه به خرج داد.
بسیار خوب! ماشین مجازی ما راه‌اندازی شد. دو روش دسترسی به آن وجود دارد. روش معمول اتصال ... به آن است، مانند یک ماشین حقیقی که از طریق شبکه متصل می‌شویم؛ اینکار نیازمند برپایی یک سرور DHCP یا پیکربندی DNS جداگانه است. روش دیگر، که در صورت اشتباه بودن پیکربندی شبکه می‌تواند تنها روش ممکن باشد، استفاده از کنسول hvc0 همراه با دستور xl console است:
# xl console testxen
[...]

Debian GNU/Linux 8 testxen hvc0

testxen login: 
در این حالت می‌توان یک نشست جداگانه برای دسترسی به ماشین مجازی ایجاد کرد. قطع اتصال این کنسول با استفاده از کلید ترکیبی Control+] انجام می‌شود.
زمانی که domU آغاز گردد، می‌تواند مانند هر سرور دیگری مورد استفاده قرار گیرد (چرا که یک سیستم گنو/لینوکس است). اگرچه، وضعیت ماشین مجازی آن برخی قابلیت‌های دیگر را فراهم می‌کند. برای نمونه، یک domU با استفاده از دستورات xl pause و xl unpause می‌تواند به صورت موقت متوقف شده یا ادامه یابد. به یاد داشته باشید که یک domU متوقف شده با اینکه از قدرت پردازنده استفاده نمی‌کند، اما هم اکنون حافظه اختصاص یافته به خود را دارد. استفاده از دستورات xl save و xl restore نیز قابل توجه است: ذخیره‌سازی یک domU تمام منابع اختصاص یافته به آن، از جمله RAM، را آزادسازی می‌کند. در زمان بازگرداندن (یا ادامه، به این منظور) یک domU چیزی به جز گذشت زمان را احساس نمی‌کند. اگر هنگام خاموش کردن dom0 یک domU در حال اجرا باشد، اسکریپت‌های پیکربندی به صورت خودکار domU را ذخیره‌سازی کرده تا در راه‌اندازی بعدی از سر گرفته شود. این عمل البته ناملایمت‌های عملیات hibernate کردن یک رایانه لپ‌تاپ را به همراه دارد، برای نمونه؛ به طور مشخص اگر domU به مدت زمان طولانی در حالت تعلیق باشد، ارتباطات شبکه ممکن است منقضی گردند. به یاد داشته باشید که Xen به شدت ناسازگار با بخش مدیریت قدرت ACPI است، که عملیات متوقف‌سازی سیستم میزبان (dom0) را انجام می‌دهد.
متوقف‌سازی یا راه‌اندازی مجدد یک domU می‌تواند از طریق خود آن (با دستور shutdown) یا از طریق dom0 با استفاده از xl shutdown یا xl reboot انجام شود.

12.2.2. LXC

با اینکه از آن برای ساخت “ماشین‌های مجازی” استفاده می‌شود، LXC به طور دقیق یک سیستم مجازی‌سازی نیست، بلکه سیستمی برای جدا کردن گروهی از فرآیندها نسبت به یکدیگر می‌باشد که درون یک میزبان اجرا می‌شوند. این سیستم از پیشرفت‌های اخیر در کرنل لینوکس بهره می‌برد، که بنام گروه‌های کنترل شناخته می‌شوند، به این معنی که مجموعه‌های مختلف از فرآیندها که “گروه” نامیده می‌شوند دید متفاوتی نسبت به جنبه‌های کلی سیستم دارند. از جمله این جنبه‌ها می‌توان به شناسه‌های فرآیند، پیکربندی شبکه و نقاط اتصال اشاره کرد. چنین گروهی از فرآیندهای ایزوله‌شده هیچ گونه دسترسی دیگر به سایر فرآیندهای سیستم ندارند و دسترسی آن‌ها به فایل سیستم تنها محدود به مجموعه‌ای کوچک می‌گردد. از این رو می‌تواند رابط شبکه و جدول مسیریابی مربوط به خود را داشته باشد و می‌تواند طوری پیکربندی شود که تنها مجموعه کوچکی از دستگاه‌های موجود در سیستم را مشاهده کند.
این ویژگی‌ها می‌توانند به منظور جدا کردن خانواده فرآیند آغازی توسط init با یکدیگر ترکیب شده که نتیجه نهایی آن مشابه با ماشین مجازی است. نام رسمی چنین تنظیمی “مخزن” است (با توجه به نام LXC که برابر است با: LinuX Containers) اما تفاوت عمده آن با ماشین‌های مجازی “واقعی” مانند Xen یا KVM در نبود یک کرنل دوم است؛ مخزن از همان کرنل سیستم میزبان استفاده می‌کند. اینکار مزایا و معایب خود را دارد: مزایای آن شامل عملکرد فوق‌العاده به دلیل نبود overhead و این حقیقت که کرنل یک دید سراسری نسبت به تمام فرآیندهای اجرایی روی سیستم دارد، به این منظور که عملیات زمان‌بندی می‌تواند به شیوه‌ای موثرتر انجام شود نسبت به حالتی که دو کرنل جداگانه باید مجموعه‌‌های مختلف از وظایف را مدیریت می‌کردند. از میان معایت نیز می‌توان به غیرممکن بودن اجرای یک کرنل مختلف درون یک مخزن اشاره کرد (خواه یک نسخه متفاوت لینوکس خواه یک سیستم عامل دیگر).
از آنجا که با مفهوم ایزوله کردن و نه یک راهکار مجازی‌سازی ساده سروکار داریم، برپایی مخازن LXC بسیار پیچیده‌تر از اجرای debian-installer در یک ماشین مجازی است. ابتدا چندین پیشنیاز را بررسی کرده سپس به قسمت پیکربندی شبکه می‌رویم؛ در این قسمت است که می‌توانیم سیستم را درون یک مخزن اجرا کنیم.

12.2.2.1. گام‌های مقدماتی

بسته lxc شامل ابزار مورد نیاز برای نصب و اجرای LXC است.
LXC همچنین به سیستم پیکربندی control groups نیاز دارد که به صورت یک فایل سیستم مجازی به /sys/fs/cgroup متصل می‌شود. از آنجا که دبیان ۸ به systemd روی آورده، که خود مبتنی بر گروه‌های کنترل است، اینکار در زمان راه‌اندازی سیستم بدون هیچ پیکربندی خاص صورت می‌گیرد.

12.2.2.2. پیکربندی شبکه

هدف از نصب LXC برپایی ماشین‌های مجازی است؛ با اینکه می‌توانیم آن‌ها را به صورت ایزوله در شبکه قرار دهیم و تنها از طریق فایل سیستم با آن‌ها تعامل کنیم، اکثر موارد کاربردی شامل دسترسی حداقلی شبکه به مخازن است. در حالت معمولی، به هر مخزن یک رابط مجازی شبکه اختصاص می‌یابد که از طریق bridge به یک رابط حقیقی شبکه متصل است. این رابط مجازی هم می‌تواند به رابط فیزیکی میزبان (که در این صورت مخزن به صورت مستقیم در شبکه قرار می‌گیرد) هم می‌تواند به رابط مجازی دیگری در میزبان متصل شود (که میزبان کار فیلتر و مسیریابی ترافیک را انجام می‌دهد). در هر صورت، بسته bridge-utils مورد نیاز خواهد بود.
مورد اول به سادگی ویرایش فایل /etc/network/interfaces، انتقال پیکربندی برای رابط فیزیکی (برای نمونه eth0) به رابط bridge (معمولا br0) و پیکربندی پیوند بین آن‌ها است. برای نمونه، اگر فایل پیکربندی رابط شبکه شامل مدخل‌های زیر باشد:
auto eth0
iface eth0 inet dhcp
آن‌ها باید غیرفعال شده و با مدخل‌های زیر جایگزین گردند:
#auto eth0
#iface eth0 inet dhcp

auto br0
iface br0 inet dhcp
  bridge-ports eth0
تاثیر این پیکربندی مشابه با حالتی خواهد بود که مخازن به صورت ماشین‌هایی به شبکه فیزیکی یکسانی از طریق میزبان متصل می‌شدند. پیکربندی “bridge” انتقال فریم‌های Ethernet را بین تمام رابط‌های bridged مدیریت می‌کند که شامل eth0 همراه با رابط‌های تعریف شده برای مخازن می‌باشد.
در مواری که این پیکربندی نمی‌تواند استفاده شود (برای نمونه اگر هیچ نشانی عمومی IP نتواند به مخازن اختصاص یابد)، یک رابط مجازی tap ایجاد و به bridge متصل می‌شود. معادل توپولوژی شبکه سپس به میزبانی با یک کارت شبکه ثانویه تبدیل شده که به یک سوئیچ جداگانه متصل است، همراه با مخازن متصل به آن سوئیچ. میزبان باید به صورت یک gateway برای مخازنی عمل کند که قصد ارتباط با دنیای خارج را دارند.
علاوه بر bridge-utils، این پیکربندی “غنی” نیازمند بسته vde2 است؛ فایل /etc/network/interfaces سپس به صورت زیر در می‌آید:
# Interface eth0 is unchanged
auto eth0
iface eth0 inet dhcp

# Virtual interface 
auto tap0
iface tap0 inet manual
  vde2-switch -t tap0

# Bridge for containers
auto br0
iface br0 inet static
  bridge-ports tap0
  address 10.0.0.1
  netmask 255.255.255.0
شبکه می‌تواند یا به صورت ایستا درون مخازن یا به صورت پویا از طریق سرور DHCP درون میزبان برپا شود. چنین سرور DHCP باید طوری پیکربندی شود که به پرس و جوهای موجود در رابط br0 پاسخ دهد.

12.2.2.3. برپایی سیستم

اکنون بیاید فایل سیستم مورد نیاز مخزن را برپا کنیم. از آنجا که این “ماشین مجازی” به صورت مستقیم روی سخت‌افزار اجرا نخواهد شد، در مقایسه با یک فایل سیستم استاندارد رعایت برخی نکات ضروری است، به خصوص تا آنجا که به کرنل، دستگاه‌ها و کنسول‌ها مربوط باشد. خوشبختانه lxc شامل اسکریپت‌هایی است که اکثر این پیکربندی را به صورت خودکار انجام می‌دهند. برای نمونه، دستورات پیش رو (که نیازمند بسته‌های debootstrap و rsync هستند) اقدام به نصب یک مخزن دبیان می‌کنند:
root@mirwiz:~# lxc-create -n testlxc -t debian
debootstrap is /usr/sbin/debootstrap
Checking cache download in /var/cache/lxc/debian/rootfs-jessie-amd64 ... 
Downloading debian minimal ...
I: Retrieving Release 
I: Retrieving Release.gpg 
[...]
Download complete.
Copying rootfs to /var/lib/lxc/testlxc/rootfs...
[...]
Root password is 'sSiKhMzI', please change !
root@mirwiz:~# 
به یاد داشته باشید که فایل سیستم به صورت اولیه در /var/cache/lxc ایجاد شد، سپس به مقصد خود انتقال یافت. اینکار امکان ایجاد مخازن مشابه را با سرعت بیشتری فراهم می‌کند، چرا که تنها عملیات رونوشت‌گیری مورد نیاز است.
به یاد داشته باشید که اسکریپت ایجاد قالب دبیان یک گزینه --arch به منظور تعیین معماری سیستم و یک گزینه --release به منظور نصب نسخه‌ای بجز نسخه انتشار اصلی از دبیان را قبول می‌کند. همچنین می‌توانید با استفاده از متغیر محیطی MIRROR از یک mirror مخصوص به دبیان استفاده کنید.
فایل سیستم تازه ایجاد شده اکنون شامل یک سیستم پایه دبیان است و مخزن پیشفرض آن هیچ رابط شبکه‌ای ندارد (بجز گزینه loopback). از آنجا که این مورد نظر ما نیست، به ویرایش فایل پیکربندی مخزن (/var/lib/lxc/testlxc/config) پرداخته و چندین مدخل lxc.network.* را در آن ایجاد می‌کنیم:
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.hwaddr = 4a:49:43:49:79:20
وجود این مدخل‌ها به این معنی است که یک رابط مجازی برای مخزن ایجاد خواهد شد؛ که به صورت خودکار هنگام آغاز مخزن شروع می‌شوند؛ که به صورت خودکار به bridge موجود در میزبان بنام br0 متصل می‌شوند؛ که نشانی MAC آن مطابق بالا خواهد بود. در صورت فقدان یا غیرفعال بودن این گزینه آخر، از یک نشانی MAC تصادفی استفاده خواهد شد.
یک مدخل مفید دیگر در آن فایل تنظیم نام میزبان است:
lxc.utsname = testlxc

12.2.2.4. آغاز مخزن

اکنون که image ماشین مجازی آماده است، بیایید مخزن را آغاز کنیم:
root@mirwiz:~# lxc-start --daemon --name=testlxc
root@mirwiz:~# lxc-console -n testlxc
Debian GNU/Linux 8 testlxc tty1

testlxc login: root
Password: 
Linux testlxc 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1 (2015-05-24) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@testlxc:~# ps auxwf
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.2  28164  4432 ?        Ss   17:33   0:00 /sbin/init
root        20  0.0  0.1  32960  3160 ?        Ss   17:33   0:00 /lib/systemd/systemd-journald
root        82  0.0  0.3  55164  5456 ?        Ss   17:34   0:00 /usr/sbin/sshd -D
root        87  0.0  0.1  12656  1924 tty2     Ss+  17:34   0:00 /sbin/agetty --noclear tty2 linux
root        88  0.0  0.1  12656  1764 tty3     Ss+  17:34   0:00 /sbin/agetty --noclear tty3 linux
root        89  0.0  0.1  12656  1908 tty4     Ss+  17:34   0:00 /sbin/agetty --noclear tty4 linux
root        90  0.0  0.1  63300  2944 tty1     Ss   17:34   0:00 /bin/login --     
root       117  0.0  0.2  21828  3668 tty1     S    17:35   0:00  \_ -bash
root       268  0.0  0.1  19088  2572 tty1     R+   17:39   0:00      \_ ps auxfw
root        91  0.0  0.1  14228  2356 console  Ss+  17:34   0:00 /sbin/agetty --noclear --keep-baud console 115200 38400 9600 vt102
root       197  0.0  0.4  25384  7640 ?        Ss   17:38   0:00 dhclient -v -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.e
root       266  0.0  0.1  12656  1840 ?        Ss   17:39   0:00 /sbin/agetty --noclear tty5 linux
root       267  0.0  0.1  12656  1928 ?        Ss   17:39   0:00 /sbin/agetty --noclear tty6 linux
root@testlxc:~# 
اکنون درون مخزن هستیم؛ دسترسی به فرآیندها تنها محدود به آن‌هایی است که توسط مخزن آغاز شده باشند و دسترسی به فایل سیستم تنها بخش کوچکی از فایل سیستم کامل /var/lib/lxc/testlxc/rootfs را شامل می‌شود. با استفاده از کلید ترکیبی Control+a q می‌توانیم از کنسول خارج شویم.
به یاد داشته باشید که مخزن را به عنوان یک فرآیند پس‌زمینه اجرا کردیم، به لطف گزینه --daemon از lxc-start. با استفاده از دستور lxc-stop --name=testlxc می‌توانیم مخزن را متوقف کنیم.
بسته lxc شامل یک اسکریپت راه‌اندازی است که به صورت خودکار یک یا چند مخزن را در زمان راه‌اندازی میزبان آغاز می‌کند (مبتنی بر lxc-autostart است که به صورت خودکار مخازن شامل گزینه lxc.start.auto برابر ۱ را راه‌اندازی می‌کند). با استفاده از lxc.start.order و lxc.group می‌توان کنترل بیشتری روی ترتیب اجرای مخازن اعمال کرد: به صورت پیشفرض، اسکریپت راه‌اندازی ابتدا مخازنی را آغاز می‌کند که جزو گروه onboot باشند سپس به سراغ مخازن دیگر می‌رود). در هر دو مورد، ترتیب درون هر گروه توسط گزینه lxc.start.order مشخص می‌شود.

12.2.3. مجازی‌سازی با KVM

KVM، که مخفف عبارت Kernel-based Virtual Machine است، در درجه اول یک افزونه کرنل به حساب می‌آید که اکثر زیرساخت مورد نیاز یک مجازی‌ساز را فراهم می‌کند اما خود یک مجازی‌ساز نیست. کنترل واقعی مجازی‌سازی توسط برنامه‌ای مبتنی بر QEMU انجام می‌شود. نگران نباشید اگر در این قسمت دستورات مربوط به qemu-* را مشاهده کنید: تمام آن‌ها مرتبط با KVM هستند.
برخلاف سایر سیستم‌های مجازی‌سازی، KVM از ابتدا درون کرنل لینوکس قرار گرفت. توسعه‌دهندگان آن تصمیم گرفتند از مجموعه دستورالعمل‌های پردازنده برای مجازی‌سازی (Intel-VT و AMD-V) استفاده کنند که اینکار باعث می‌شود KVM سبک، ظریف و سازگار با منابع پایین باشد. نقطه ضعف آن این است که KVM روی هر رایانه‌ای نمی‌تواند اجرا شود بلکه فقط برخی پردازنده‌های خاص از آن پشتیبانی می‌کنند. برای رایانه‌های مبتنی بر x86، می‌توانید به دنبال پرچم‌های مخصوص پردازنده به نام “vmx” یا “svm” در فایل /proc/cpuinfo بگردید.
با پشتیبانی مداوم Red Hat از توسعه آن، KVM کم و بیش به مرجع مجازی‌سازی در لینوکس تبدیل شده است.

12.2.3.1. گام‌های مقدماتی

KVM برخلاف ابزاری مانند VirtualBox، شامل رابط کاربری برای مدیریت ماشین‌های مجازی نیست. بسته qemu-kvm تنها شامل یک فایل اجرایی برای آغاز یک ماشین مجازی است، همراه با اسکریپت‌های راه‌اندازی که اقدام به بارگیری افزونه‌های مناسب کرنل می‌کنند.
خوشبختانه، Red Hat برای غلبه بر این مشکل مجموعه ابزاری فراهم کرده است که شامل کتابخانه libvirt و ابزارهای virtual machine manager می‌شوند. libvirt امکان مدیریت ماشین‌های مجازی را به یک شیوه یکسان فراهم می‌کند، جدا از سیستم مجازی‌سازی که در پشت صحنه قرار دارد (هم اکنون از QEMU، KVM، Xen، LXC، OpenVZ، VirtualBox، VMWare و UML پشتیبانی می‌کند). virtual-manager یک رابط گرافیکی است که با استفاده از libvirt ماشین‌های مجازی را مدیریت می‌کند.
ابتدا با استفاده از apt-get install qemu-kvm libvirt-bin virtinst virt-manager virt-viewer بسته‌های مورد نیاز را نصب می‌کنیم. libvirt-bin فرآیند پس‌زمینه libvirtd را فراهم می‌کند، که امکان مدیریت (معمولا راه دور) ماشین‌های مجازی اجرای در سیستم میزبان را فراهم کرده و ماشین‌های مجازی مورد نیاز را در زمان راه‌اندازی میزبان آغاز می‌کند. علاوه بر این، این بسته ابزار خط-فرمان virsh را فراهم می‌کند که امکان کنترل ماشین‌های libvirtd را بوجود می‌آورد.
بسته virtinst شامل virt-install می‌شود که امکان ایجاد ماشین‌های مجازی از خط فرمان را فراهم می‌کند. در نهایت، virt-viewer اجازه دسترسی به کنسول گرافیکی یک ماشین مجازی را بوجود می‌آورد.

12.2.3.2. پیکربندی شبکه

درست مانند Xen و LXC، متداول‌ترین پیکربندی شبکه شامل یک bridge که رابط‌های شبکه ماشین‌های مجازی را گروه‌بندی می‌کند، می‌باشد ( قسمت 12.2.2.2, “پیکربندی شبکه” را مشاهده کنید).
به طور متقابل، در پیکربندی پیشفرض فراهم شده توسط KVM، یک نشانی خصوصی به ماشین مجازی اختصاص می‌یابد (در محدوده 192.168.122.0/24) و NAT طوری تنظیم می‌شود که ماشین مجازی بتواند به شبکه خارجی دسترسی داشته باشد.
باقیمانده این قسمت با توجه به اینکه میزبان دارای یک رابط فیزیکی eth0 و bridge br0 است ادامه می‌یابد، به طوری که اولی به دومی متصل شده است.

12.2.3.3. نصب با virt-install

ایجاد یک ماشین مجازی بسیار شبیه یک سیستم عادی است، با این تفاوت که ویژگی‌های ماشین مجازی به صورت گزینه‌های بی‌پایان در خط فرمان قرار می‌گیرند.
در عمل، یعنی از یک نصب کننده دبیان استفاده خواهیم کرد، با راه‌اندازی ماشین مجازی روی یک درایو DVD-ROM که به یک تصویر از DVD دبیان ذخیره شده در سیستم میزبان نگاشت شده است. ماشین مجازی از طریق پروتکل VNC کنسول گرافیکی خود را آماده می‌کند ( قسمت 9.2.2, “استفاده از میزکارهای گرافیکی راه‌دور” را مشاهده کنید) که اینکار به ما اجازه می‌دهد فرآیند نصب را کنترل کنیم.
ابتدا باید به libvirtd بگوییم تصاویر دیسک را در کجا ذخیره کند، مگر مکان پیشفرض /var/lib/libvirt/images/ مناسب باشد.
root@mirwiz:~# mkdir /srv/kvm
root@mirwiz:~# virsh pool-create-as srv-kvm dir --target /srv/kvm
Pool srv-kvm created

root@mirwiz:~# 
اکنون بیایید فرآیند نصب ماشین مجازی را آغاز کرده و نگاهی بر مهم‌ترین گزینه‌های virt-install بیندازیم. این دستور، ماشین مجازی و پارامترهای آن را در libvirtd ثبت می‌کند سپس به اجرای آن پرداخته تا فرآیند نصب ادامه یابد.
# virt-install --connect qemu:///system  1
               --virt-type kvm           2
               --name testkvm            3
               --ram 1024                4
               --disk /srv/kvm/testkvm.qcow,format=qcow2,size=10 5
               --cdrom /srv/isos/debian-8.1.0-amd64-netinst.iso  6
               --network bridge=br0      7
               --vnc                     8
               --os-type linux           9
               --os-variant debianwheezy

Starting install...
Allocating 'testkvm.qcow'             |  10 GB     00:00
Creating domain...                    |    0 B     00:00
Guest installation complete... restarting guest.

1

گزینه --connect مشخص می‌کند از کدام “hypervisor” استفاده شود. فرم استفاده از آن شامل یک URL همراه با سیستم مجازی‌سازی مرتبط (xen://، qemu://، lxc://، openvz://، vbox://) و ماشینی که باید از آن میزبانی کند می‌باشد (در صورت استفاده از localhost می‌تواند خالی باشد). علاوه بر این و در مورد QEMU/KVM، هر کاربر می‌تواند با استفاده از مجوزهای محدودشده ماشین‌های مجازی را مدیریت کند و مسیر URL امکان تفاوت قائل شدن بین ماشین‌های “سیستم” (/system) را از دیگر (/session) فراهم می‌کند.

2

از آنجا که KVM به شیوه مشابه QEMU مدیریت می‌شود، --virt-type kvm امکان مشخص کردن استفاده از KVM با وجود تشابه با URL QEMU را فراهم می‌کند.

3

گزینه --name یک نام (منحصربفرد) برای ماشین مجازی تعریف می‌کند.

4

گزینه --ram میزان RAM (به مگابایت) اختصاص یافته به ماشین مجازی را تعریف می‌کند.

5

گزینه --disk مکان فایل تصویری که قرار است هارد دیسک ماشین مجازی در آن قرار گیرد را تعریف می‌کند؛ این فایل با استفاده از پارامتر size (به گیگابایت) در صورت موجود نبودن، ایجاد می‌گردد. پارامتر format امکان ذخیره‌سازی فایل تصویر را در قالب‌های گوناگون بوجود می‌آورد. قالب پیشفرض (raw) یک فایل تکی است که با محتوا و اندازه دیسک سازگاری داشته باشد. در اینجا از یک قالب پیشرفته‌تر استفاده کرده‌ایم، که مختص به QEMU می‌باشد و امکان شروع با یک فایل کوچک را می‌دهد که به مرور زمان و نیاز ماشین مجازی به فضای بیشتر، بزرگ‌تر می‌شود.

6

گزینه --cdrom به منظور یافتن دیسک نوری برای فرآیند نصب استفاده می‌شود. مسیر می‌تواند شامل یک مسیر محلی برای فایل ISO، یک URL که فایل می‌تواند از آنجا دریافت شود یا فایل دستگاه مربوط به یک درایو فیزیکی CD-ROM باشد (/dev/cdrom).

7

گزینه --network مشخص می‌کند کارت مجازی شبکه چطور با پیکربندی سیستم میزبان ادغام شود. عملکرد پیشفرض آن (که در این نمونه به صورت صریح بیان کرده‌ایم) ادغام آن با شبکه bridge از قبل موجود در سیستم است. اگر چنین bridge موجود نباشد، ماشین مجازی تنها با استفاده از NAT می‌تواند به شبکه فیزیکی دسترسی یابد، بنابراین یک نشانی در محدوده زیرشبکه 192.168.122.0/24 دریافت می‌کند.

8

گزینه --vnc بیان می‌کند که کنسول گرافیکی باید توسط VNC قابل ارائه باشد. عملکرد پیشفرض سرور VNC این است که تنها به رابط local گوش دهد؛ اگر برنامه VNC در یک میزبان دیگر قرار داشته باشد، برقراری ارتباط نیازمند برپایی تونل SSH می‌باشد ( قسمت 9.2.1.3, “ایجاد تونل‌های رمزگذاری شده با پورت فورواردینگ” را مشاهده کنید). به همین ترتیب، از --vnclisten=0.0.0.0 می‌توان برای دسترسی به سرور VNC از طریق تمام رابط‌های شبکه استفاده کرد؛ به یاد داشته باشید که در این صورت باید از یک طراحی firewall بهره‌مند شوید.

9

گزینه‌های --os-type و --os-variant، با توجه به برخی از ویژگ‌های سیستم عامل اشاره شده، امکان بهینه‌سازی چندین پارامتر ماشین مجازی را فراهم می‌کنند.
در این نقطه، ماشین مجازی در حال اجرا است و به منظور ادامه فرآیند نصب باید به کنسول گرافیکی متصل شویم. اگر عملیات قبل از طریق یک میزکار گرافیکی صورت گرفته باشد، این ارتباط به صورت مستقیم برقرار می‌شود. در غیر اینصورت، یا در حالتی که از راه دور اینکار را انجام می‌دهیم، virt-viewer با استفاده از هر محیط گرافیکی برای باز کردن کنسول گرافیکی می‌تواند اجرا شود (به یاد داشته باشید که دو مرتبه گذرواژه root درخواست می‌شود چرا که ۲ ارتباط SSH مورد نیاز است):
$ virt-viewer --connect qemu+ssh://root@server/system testkvm
root@server's password: 
root@server's password: 
زمانی که فرآیند نصب به پایان برسد، ماشین مجازی راه‌اندازی مجدد می‌گردد تا قابل استفاده شود.

12.2.3.4. مدیریت ماشین‌های مجازی با virsh

اکنون که نصب به پایان رسیده است، بیایید چگونگی مدیریت ماشین‌های مجازی را بررسی کنیم. اولین کاری که باید بکنیم پرسش از libvirtd برای فهرستی از ماشین‌های مجازی موجود است:
# virsh -c qemu:///system list --all
 Id Name                 State
----------------------------------
  - testkvm              shut off
بیایید ماشین مجازی آزمایشی خود را آغاز کنیم:
# virsh -c qemu:///system start testkvm
Domain testkvm started
اکنون می‌توانیم دستورالعمل‌های ارتباط به کنسول گرافیکی را دریافت کنیم (نمایش VNC بازگشتی می‌تواند به عنوان پارامتر vncviewer استفاده شود):
# virsh -c qemu:///system vncdisplay testkvm
:0
سایر دستورات virsh عبارتند از:
  • reboot برای راه‌اندازی مجدد یک ماشین مجازی؛
  • shutdown برای درخواست یک shutdown تمیز؛
  • destroy برای توقف خشن آن؛
  • suspend برای توقف عادی آن؛
  • resume برای ادامه فعالیت آن؛
  • autostart برای فعال کردن (یا غیر فعال کردن با گزینه --disable) راه‌اندازی ماشین مجازی به صورت خودکار در زمان راه‌اندازی میزبان؛
  • undefine برای حذف تمام نشانه‌های ماشین مجازی از libvirtd.
تمام این دستورات شناسه ماشین مجازی را به عنوان یک پارامتر دریافت می‌کنند.

12.2.3.5. نصب یک سیستم مبتنی بر RPM در دبیان با استفاده از yum

اگر قرار باشد ماشین مجازی به منظور اجرای دبیان (یا یکی از توزیع‌های آن) راه‌اندازی گردد، سیستم می‌تواند با استفاده از debootstrap همانطور که توضیح داده شد راه‌اندازی شود. اما اگر قرار باشد ماشین مجازی به منظور اجرای یک سیستم مبتنی بر RPM (مانند Fedora، CentOS یا Scientific Linux) راه‌اندازی گردد، اینکار باید با استفاده از ابزار yum صورت گیرد (که در بسته‌ای با همین نام قرار دارد).
این فرآیند شامل استفاده از rpm به منظور استخراج مجموعه‌ای از فایل‌ها، شامل فایل‌های پیکربندی yum، سپس فراخوانی yum برای استخراج سایر بسته‌های باقیمانده می‌باشد. اما از آنجا که فراخوانی yum خارج از chroot صورت می‌گیرد، باید برخی تغییرات موقتی را ایجاد کنیم. در نمونه زیر، chroot هدف عبارت است از /srv/centos.
# rootdir="/srv/centos"
# mkdir -p "$rootdir" /etc/rpm
# echo "%_dbpath /var/lib/rpm" > /etc/rpm/macros.dbpath
# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/centos-release-7-1.1503.el7.centos.2.8.x86_64.rpm
# rpm --nodeps --root "$rootdir" -i centos-release-7-1.1503.el7.centos.2.8.x86_64.rpm
rpm: RPM should not be used directly install RPM packages, use Alien instead!
rpm: However assuming you know what you are doing...
warning: centos-release-7-1.1503.el7.centos.2.8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
# sed -i -e "s,gpgkey=file:///etc/,gpgkey=file://${rootdir}/etc/,g" $rootdir/etc/yum.repos.d/*.repo
# yum --assumeyes --installroot $rootdir groupinstall core
[...]
# sed -i -e "s,gpgkey=file://${rootdir}/etc/,gpgkey=file:///etc/,g" $rootdir/etc/yum.repos.d/*.repo