Portál AbcLinuxu, 3. května 2025 15:24
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 svoji 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ž běží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 ta jsou platná pouze uvnitř
UML.
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 normální proces, odhlásíme se z konzole a UML
běží ve screenu na pozadí).
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ů).
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, ze kterého budeme bootovat, případně kde budou domácí adresáře uživatelů a podobně.
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.
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 parametr
seek
u příkazu dd
). Pokud tyto soubory podporuje
souborový systém, na kterém jsou umístěny, tak zaberou 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
vzápětí nainstalujeme Debian.
mount /home/uml/debian.img /mnt -o loop
Instalaci Debianu 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
něj 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
programy 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ě prvních dvou. 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ásili z normální textové konzole. V
logu se ukáže, že jste přišli z konzole tty0
nebo
tty1
.
Samozřejmě, že se 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é.
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 64 MiB 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
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íť. Nyní 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.
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.
root
(bz2 archiv o velikosti 133 MiB,
po rozbalení zabere na disku necelých 300 MiB)./uml_new_user username distribuce
username
je jméno uživatele, pod kterým má UML běžet.distribuce
je název .img
souboru, který se
použije jako root_fs (například debian
pro soubor
debian.img
)./home/uml
, UML stroje
se vytvářejí v /home/virtual
.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 UML.
dd if=/dev/zero of=/home/uml/debian.img bs=1M count=0 seek=4096Váš dd udělá 4097MB, poslední MB je fyzicky alokovaný. Napadá mne, zdali by se nedal sloučit UML s vícevrstevnými root FS, používanými u live CD. Ušetřil by se tím prostor na disku a vyřešil by se upgrade mnoha UML - zákazníci by dostali pronajatý server na vícevrstevném souborovým systému. Ten by byl pouze ke čtení (např. přes NFS), a na něm by byla vrstva pro zápis, takže zákazník by měl právo zápisu, ale provedené změny by se ukládaly pouze lokálně. Samozřejmě /home a /tmp, a možná části /var nebo /srv, by byly čistě lokální.
INIT: Entering runlevel: 2
Starting system log daemon: syslogd.
Starting kernel log daemon: klogd.
Starting MTA: exim4.
Starting internet superserver: inetd.
Starting deferred execution scheduler: atd.
Starting periodic command scheduler: cron.
INIT: Id "2" respawning too fast: disabled for 5 minutes
INIT: Id "3" respawning too fast: disabled for 5 minutes
INIT: Id "4" respawning too fast: disabled for 5 minutes
INIT: Id "5" respawning too fast: disabled for 5 minutes
INIT: Id "1" respawning too fast: disabled for 5 minutes
INIT: Id "6" respawning too fast: disabled for 5 minutes
INIT: no more processes left in this runlevel
INIT: Id "2" respawning too fast: disabled for 5 minutes
INIT: Id "4" respawning too fast: disabled for 5 minutes
INIT: Id "3" respawning too fast: disabled for 5 minutes
INIT: Id "5" respawning too fast: disabled for 5 minutes
INIT: Id "1" respawning too fast: disabled for 5 minutes
INIT: Id "6" respawning too fast: disabled for 5 minutes
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.