Virtuální linuxový server - User Mode Linux

Obsah


Úvod

Virtuální servery umožňují současný běh několika instancí operačního systému na jednom hardware. V operačním systému GNU/Linux jsou nejznámější systémy pro virtualizaci komerční VMWare, Virtuozzo a OS řešení User Mode Linux (dále jen UML). Protože nemám peněz nazbyt, zvolil jsem si pro svojí další práci UML.

UML je jedna varianta překladu jádra Linuxu, která ho umožňuje spouštět jako normální program z již bežícího systému a to i vícekrát. UML se spouští pod neprivilegovaným uživatelem a ze strany hostitelského systému se tváří jako "normální" procesy. Uvnitř UML vidíte pouze své procesy, jste v něm uzavřeni a prakticky neexistuje cesta ven do hostitelského systému. Samozřejmě poznáte, že se jedná o UML, protože jsou některé výpisy z adresáře /proc trochu jiné. Velkou výhodou je, že můžete dát například zákazníkovi práva uživatele root, ale ty jsou platná pouze uvnitř UML.

Potřebný software

Pro provoz UML potřebujete na hostitelský systém nainstalovat uml-utilities, dostatek RAM a místa na disku. Uml-utilities použijeme pro vytvoření virtuálních síťových rozhraní v hostitelském systému (lze to udělat i ručně, ale jsem líný a tak raději používám utilitu uml_net :-) a pro základní ovládání UML (získání informací o stroji aniž bychom se do něj přihlašovali, zálohování a třeba i vypnutí). Dále je potřeba zakompilovat podporu pro tun do jádra kvůli virtuálním síťovým rozhraním. Další program, který potřebujeme je screen v něm budeme UML spouštět (spustíme UML jako nromální proces, odhlásíme se od konzole a UML běží ve screenu na pozadí).

Instalace

Hostitelský počítač

Na hostitelský počítač nejsou kladeny příliš veliké nároky, co se týká programového vybavení. UML mi nyní funguje na Debianu (kříženec mezi testing, unstable a experimental :-) a na druhém počítači, kde si s UML hraji běží Slackware-current.

Je důležité mít podporu pro síťová rozhraní tun, kdo používáte standardní distribuční jádro máte po starostech, kdo si ho překládá sám, určitě si poradí. Přítomnost vyzkoušejte příkazem modprobe tun. Dále si nainstalujte program screen, v něm budeme spouštět UML - uvidíme chybová hlášení jádra a můžeme ho spustit na pozadí, uml-utilities si nainstalujte také (použil jsem verzi z Debiana, na Slackware jsem si kompiloval ze zdrojových souborů)

Virtuální server

Pro provoz virtuálního serveru (UML) potřebujeme speciálním způsobem přeložené jádro a také nějaký souborový systém, z kterého budeme bootovat případně kde budou domácí adresáře uživatelů a podobně.

Jádro

Pro UML jsem použil vanilla jádro verze 2.6.9, na hostitelském systému běží jádro 2.4.27 se standardní sadou patchů distribuce Debian. Vlastní kompilace UML jádra se provádí tímto způsobem:

cd /usr/src/linux
make menuconfig ARCH=um
make vmlinux ARCH=um

Jádro jsem si přeložil bez modulů, protože je to jednodušší a stejně si myslím, že bych modulárním jádrem moc paměti neušetřil. Po kompilaci nám vznikne v adresáři se zdrojovým kódem jádra soubor vmlinux, který si nakopírujeme do adresáře /home/uml (do tohoto adresáře budu dávat vše co se týká UML) a nastavíme mu práva 755. Tento soubor je naše jádro pro UML systém a pokud si ho spustíte, měl by se ukázat klasická výpis bootu jádra s tím, že skončí na neexistenci root filesystému.

Souborový systém

Vytvoření souborového systému pro UML je celkem jednoduché a vystačíme si se std. nástroji z distribuce. Pro standardní instalaci Linuxu by nám mohlo stačit 4 GiB místa pro root filesystem, vytvoříme si proto prázdný soubor veliký 4 GiB:

dd if=/dev/zero of=/home/uml/debian.img bs=1M count=1 seek=4096

Tímto příkazem jsme vytvořili soubor veliký 4 GiB na kterém si vytvoříme souborový systém, soubor jsem nazval debian.img, protože do něj nainstaluji distribuci Debian.

mkfs.xfs -f /home/uml/debian.img

Jak jste si jistě všimli, soubor nezabírá celé 4 GiB, ale podstatně méně, je to tím, že to je takzvaný řídký soubor (to udělal ten seek u příkazu dd). Pokud tyto soubory podporuje souborový systém na kterém jsou umístěny, tak zebrou jen tolik místa, kolik obsahují dat (no dobře, zaberou ho o trochu víc - přesně o své i-nody, které spotřebují) a tam kde by bylo prázdno si souborový systém poznamená, že tam je tolik a tolik alokovaných bajtů, ale nezabírá to místo na disku. Proto můžete vyrobit třeba terabytový soubor na 40 GB disku. Využijeme toho ještě několikrát.

Vzniklý soubor připojíme do adresáře /mnt, do kterého v zápětí nainstalujeme Debiana.

mount /home/uml/debian.img /mnt -o loop

Instalaci Debiana provedeme pomocí skriptu Debootstrap, který si nainstalujeme příkazem apt-get install debootstrap. Rozhodl jsem se, že si nainstaluji sarge - základní instalaci provedu pomocí příkazu

debootstrap sarge /mnt

Tím se mi nainstaluje minimální základ systému do adresáře /mnt. Nainstalovaný systém je téměř nenastavený, proto se do přepneme pomocí chrootu a doinstalujeme vše co je potřeba.

chroot /mnt
mount -n /proc

Okolo sítě jsem si nastavil pouze DNS servery a rozhraní lo, eth0 jsem nenastavoval, protože to se bude muset konfigurovat pro každou běžící instanci UML zvlášť (využijeme jeden společný root_fs pro všechny uživatele jako základ systému). Je třeba nastavit apt-get aby bylo možné instalovat další programy a také si musíme napsat nové soubory /etc/fstab a /etc/hosts. Po tom co nastavíte apt-get nainstalujte minimálně ssh, osobně jsem ještě nainstaloval progrmy mc, vim a pár dalších, které většina lidí používá.

Soubor /etc/fstab je trochu jiný, proto se mu budu věnovat trochu víc. V UML nejsou dostupná klasická zařízení pro disky typu /dev/hdX, ale používají se /dev/ubdX. Můj /etc/fstab vypadá následovně:

/dev/ubd/0  /  xfs defaults 0 0
/dev/ubd/1 none swap defaults 0 0
/proc none proc defaults 0 0
/dev/pts none devpts 0 0
/dev/shm none shmfs 0 0
/sys none sysfs 0 0

Uvnitř UML nepoužívám devfs, protože mi to připadá zbytečné. Zařízení /dev/ubd/X vyrobíme následujícím způsobem:

mkdir /dev/ubd
cd /dev/ubd
for i in 0 1 2 3 4 5 6 7; do mknod $i b 98 $[ $i * 16 ]; done

Další úprava nastavení, kterou jsem provedl je vypnutí všech konzolí v souboru /etc/inittab kromě dvou prvních. První konzoli přiřadím na zařízení /dev/ptypX na které se pak můžu připojit z hostitelského počítače například pomocí programu minicom (minicom -o -p /dev/ptypX) a druhou konzoli pověsím na telnet na nějaký port (například 9001 a podobně), to ovšem znamená, že si musíte do hostitelského systému nainstalovat telnet server. Z hlediska bezpečnosti to je celkem v pohodě pokud se nebudete připojovat z jiného systému než hostitelského.

Z pohledu UML systému pak přihlášení ze zařízení /dev/ptypX nebo telnetu vypadá jako byste se hlásily z normální textové konzole, v logu se ukáže že jste přišli z konzole tty0 nebo tty1. Samozřejmě, že se z běžně na systém nebudeme přihlašovat přes minicom nebo telnet, ale ta možnost se hodí pokud si uživatel shodí ssh a podobně, přeci byste mu kvůli tomu nerestartovali celý stroj? :-)

V případě, že jste s instalací systému pro UML spokojeni a nenapadá vás co ještě nastavit, utečte z chrootu a odpojte adresář /mnt. Pokud se rozhodnete ještě změnit nějaké nastavení tak je to samozřejmě možné.

Spuštění

Nyní máme připravené jádro i souborový systém pro virtuální server a můžeme ho zkusit nastartovat. Start provedeme zatím bez sítě, jen zkusíme jestli vůbec nabootujeme. UML systému přidělíme 64MiB RAM, první konzole virtuálního systému bude poslouchat na /dev/ptyp0 (v mém případě je to /dev/pty/s0 a /dev/ptyp0 je symlink na něj - používám na počítači devfs. ) a druhá na tcp portu 9001 bude čekat na přihlášení pomocí telnetu. nastavení con0 způsobí, že se bude na obrazovku vypisovat spouštění initu a podobně. Pro otestování základní funkčnosti nám následující příkaz stačí, pro ostrý provoz to však ještě nestačí.

/home/uml/vmlinux mem=64M ubd0=/home/uml/debian.img con0=fd:0,fd:1 con1=pty con2=port:9001

V případě, že jste nabootovali, byste měli mít na obrazovce výstup jádra a initu. Také by se někde mělo vypsat jaké pty zařízení je použito pro první konzoli.

Virtual console 1 assigned device '/dev/ptyp0'

Ještě ověříme jestli poslouchá telnet na portu 9001:

tsunami:~# netstat -tanp | grep 9001
tcp   0   0 0.0.0.0:9001    0.0.0.0:*    LISTEN    23879/linux         

Vyzkoušíme přihlášení na pty zařízení:

minicom -o -p /dev/ptyp0

Mělo by se ukázat něco jako:

Welcome to minicom 2.1

OPTIONS: History Buffer, F-key Macros, Search History Buffer, I18n 
Compiled on Nov 12 2003, 19:21:57.

Press CTRL-A Z for help on special keys


Debian GNU/Linux 3.1 umlstroj tty1

umlstroj login: 

Z minicomu se odhlásíte pomocí stisku Ctrl+A Q.
Přihlášení na telnet je jednoduché:

tsunami:~# telnet localhost 9001
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Debian GNU/Linux 3.1 tsunami

Debian GNU/Linux 3.1 umlstroj tty2

umlstroj login: 

Pokud chcete z telnetu utéct, stiskněte Ctrl+],Ctrl+d

Ať už se přihlásíte přes minicom nebo telnet, můžete se normálně přihlásit do systému. Vše co v systému uděláte se souborovým systémem se uloží normálně do souboru debian.img, který se pro virtuální server tváří jako disk.

Další spouštění provedeme již jako neprivilegovaný uživatel se sítí a trochu jiným nastavením disků. Spouštění pod neprivilegovaným uživatelem znamená, že binárce uml_net, kterou použijeme pro nastavení sítě musíme dát SUID bit. IP adresa, kterou zadáme jako parametr při spouštění musí být jiná než adresa uvnitř UML, je to totiž adresa lokálního síťového rozhraní. Zvolil jsem si adresu 10.0.1.1, uvnitř UML bude adresa 10.0.0.1. Aby měl UML systém přístup na síť je třeba správně nastavit NAT na hostitelském systému. Zvolil jsem si kombinaci SNAT a DNAT.

Soubor debian.img se systémem pro virtuální server je dobré používat pouze pro čtení a změny zapisovat někam jinam. Umožní nám to použít jeden výchozí debian.img pro více instancí UML. Mechanismus, který se pro to využívá se nazývá Copy On Write (COW). Znamená to, že linuxu předhodíme jako parametr další soubor, do kterého se budou zapisovat všechny změny na disku. Soubor si jádro při startu založí samo. Soubor uml_swap.img použijeme pro swapování UML systému, vyrobíme ho pomocí programu dd

Swap:

dd if=/dev/zero of=/home/uml/uml_swap.img
mkswap /home/uml/uml_swap.img

Spuštění UML systému tedy provedeme příkazem:

/home/uml/vmlinux mem=64M udb0=/home/uml/debian_cow.img,/home/uml/debian.img\
ubd1=/home/uml/uml_swap.img con0=fd:0,fd:1 con1=pty con2=port:9001 eth0=tuntap,,,10.0.1.1

Síťování

Privátní IP adresa

Jakmile se přihlásíte do UML pomocí telnetu nebo minicomu, nastavte si správně soubor /etc/network/interfaces tak aby tam byla jako lokální IP adresa na rozhraní eth0 10.0.0.1 a jako gateway 10.0.1.1. Potom proveďte restart sítě pomocí /etc/init.d/network restart. Ve výpisu dmesg v UML systému by se mělo ukázat něco jako:

* modprobe tun
* ifconfig tap0 10.0.1.1 netmask 255.255.255.255 up
* bash -c echo 1 > /proc/sys/net/ipv4/ip_forward
* route add -host 10.0.0.1 dev tap0
* bash -c echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp
done.

Je to sada příkazů, které spustila utilita uml_net v hostitelském systému a tím nastavila síť. Niní byste si měli pingnout UML systém z hostitelského počítače

tsunami:~# ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.096 ms

a také naopak z UML byste si měli pingnout hostitelský počítač

umlstroj:~# ping 10.0.0.2
PING 10.0.1.1 (10.0.1.1) 56(84) bytes of data.
64 bytes from 10.0.1.1: icmp_seq=1 ttl=64 time=0.416 ms

Nyní si pomocí iptables můžete nastavit SNAT a DNAT na hostitelském počítači tak jak potřebujete.

Veřejná IP adresa

V případě, že se rozhodnete v UML systému použít veřejnou IP adresu, samozřejmě můžete. Postup nastavení adresy je stejný jako v minulém příkladu, jen nepotřebujete SNAT a DNAT.

Soubory ke stažení

Závěr

Tento text neberte jako kompletní manuál, je to jen přiblížení méně známého způsobu provozu Linuxu. Originální dokumentaci najdete na stránkách projektu.

$Id: uml.html,v 1.16 2005/05/09 19:32:35 tsunami Exp $