1566/7960

Qemu

Pokud si chcete hrát, nastavovat, zkoušet… není vždy jednoduché a často ani možné mít na tyto hrátky tolik fyzických strojů. Ale nezoufejte je tu Qemu. Na jeho domovské stránce se dočteme:

QEMU is a generic and open source machine emulator and virtualizer.

Qemu je program, který emuluje počítač. Do tohoto počítače je možné nainstalovat jakýkoliv operační systém bez zásahu do toho stávajícího. Takto je možné si vyzkoušet instalaci, konfiguraci a mnoho dalších věcí a přitom nepotřebuje žádný další počítač. V jednom počítači si můžete naemulovat celou počítačovou sít.

Qemu není jedinou možností. Ještě můžete použít například VMware nebo VirtualBox. Přiznám se, že jsem zkoušel jen Qemu. Pokud někdo prošlápnete jinou cestičku rád se poučím.

Velkou předností Qemu je právě to, jak umí pracovat se sítí. Umí velice jednoduše spojit různé virtuální stroje na různých hostitelích do jedné virtuální sítě. Více se dočtete v dokumentaci u parametru -net.

Qemu je dostupný jak pro Linux tak pod Windows. Stačí si ho stáhnout nebo použít balíčkovací systém vaší distribuce.

 # aptitude install qemu kqemu-source 

kQemu

V Linuxu je možné zavést do jádra akcelerační modul kqemu, který běh emulátoru výrazně zrychluje. Pokud se rozhodnete provozovat Qemu pod Linuxem je zavedení modulu kqemu do jádra téměř nutností.

kqemu se nejspíš bude nacházet v balíčku kqemu-verzejadra. Nebo nějak podobně. Stačí nainstalovat a potom zavést příkazem modprobe.

 # modprobe kqemu 

V příkladech dál to neuvádím, ale pro plné využití modulu kqemu je nutné zapnout při volání Qemu parametr -kernel-kqemu. Je tu trošku problém v tom, že je možné ho volat pouze tehdy, pokud probíhá virtualizace 32-bitu na 32-bitu (nebo 64-bitu na 64-bytu) a pokud virtuální stroj má jádro i386 nebo i486 ale ne i686.

Module Assistant

Pokud vaše distribuce neobsahuje balíček s již zkompilovaným modulem kqemu, budete si ho muset dokompilovat ručně. To je možné buď opravdu ručně – což není těžké, protože jsem to zvládl i já, nebo použijete module-assistant, který udělá vše za vás.


# aptitude install module-assistant
# module-assistant

Nejprve vybereme PREPARE, který nastaví systém tak, aby bylo možné kompilovat moduly.

Potom pomocí SELECT mezerníkem vybereme kqemu a tabulátorem se přepneme na OK.

Nakonec stačí vybrat BUILD a INSTALL.

... nebo prostě a jesnoduše:

 # module-assistant prepare kqemu-source
 # module-assistant auto-install kqemu-source

A je hotovo. Možná bude potřeba do souboru /etc/modules přidat řádek kqemu, aby se modul načítal automaticky při startu systému a aby nebylo potřeba pokaždé modul ručně zavádět.

 # modprobe kqemu 

KVM

Pokud váš procesor obsahuje hardwarovou podporu virtualizace, můžete místo Qemu použít KVM. KVM je upravená verze Qemu, která má podporu přímo v jádře (Kernel-based Virtual Machine). Běh virtuálního stroje je pak téměř tak rychlý, jako by běžel přímo na hostitelském hardware.

Nejprve je potřeba ověřit jestli procesor podporuje virtualizaci.

$ egrep '^flags.*(vmx|svm)' /proc/cpuinfo

Pokud tento příkaz vypíše flagy procesoru má procesor podporu virtualizace.

Stačí tedy jen nainstalovat KVM

 # aptitude install kvm

Pokud nemáte zavedené jaderné moduly musíte je zavést. Kompilovat je pravděpodobně nebude muset protože by měly již být obsaženy v jádře (od verze 2.6.20).

# modprobe kvm-intel

nebo

# modprobe kvm-amd

Praktická ukázka

Nutno říci, že tady mě hodně navedl Honza Outrata Patří mu za to velký dík. Myslím, že je také dobré říct, že možností je více, než tu uvádím. Více v Dokumentaci.

Obraz disku

Nejprve je třeba vytvořit si obraz disku, na který budeme instalovat. K tomu použijeme qemu-img.

$ qemu-img create -f qcow2 qemumachine.img 3G

Pomocí parametru -f si můžeme vybrat formát. Formát qcow2 má dynamickou velikost, takže na disku nezabere celé 3 GB, ale jen tolik, kolik na něj skutečně umístíme. Pokud tam budete chtít dát WinXP jsou ale 3 GB dost málo :-).

Instalujeme

$ qemu     -cdrom /cesta/k/debian-40r4a-i386-netinst.iso -hda qemumachine.img -m 64 -boot d
$ sudo kvm -cdrom /cesta/k/debian-40r4a-i386-netinst.iso -hda qemumachine.img -m 64 -boot d

Já místo qemu používám kvm. Proto uvádím obě dvě varianty. kvm je třeba spuštět jako uživatel root. Proto to sudo. Jinak je syntax stejná a myslím čítelná. -m udává kolik bude mít virtuální počítač paměti RAM.

Pokud se vám instalovat nechce můžete si stáhnout již nainstalovaný obraz s Linuxem. Heslem je zde heslo.

Spojení počítačů do virtuální sítě

Vše probíhá pomocí parametru -net.

-net nic,vlan=0,macaddr=52:54:00:12:34:54

vytvoří nové virtuální síťové rozhraní a

-net socket,vlan=0,mcast=230.0.0.1:54321

toto rozhraní připojí do virtuální sítě tvořené multicastem skutečné sítě na vyhrazeném portu 54321. Obrovská výhoda je, že takto můžeme spojit více virtuálních strojů na více hostitelích. Je nutné aby každé síťové rozhraní mělo jinou MAC adresu.

Celé to tedy je:

qemu qemumachine.img -net nic,vlan=0,macaddr=52:54:00:12:34:54 -net socket,vlan=0,mcast=230.0.0.1:54321

Výchozí emulovaná síťová karta ve virtuálním stroji je (s ovladačem) ne2k_pci, což je 10 Mb/s. Pro 100 Mb/s je rtl8139.

 -net nic,vlan=0,macaddr=52:54:00:12:34:54,model=rtl8139

Připojení virtuální sítě do skutečné sítě.

Na hostujícím počítači se vytvoří virtuální rozhraní tap0. K tomu je potřeba mít nainstalovaný balík uml-utilities. Pomocí tohoto rozhraní se vytvoří síť mezi hostujícím a hostitelským strojem.

# tunctl -t tap0
# ip addr add 192.168.68.1/29 dev tap0
# ip link set dev tap0 up

Hostitelský počítač musí fungovat jako router tzn. musí provádět IP forwarding a dále by měl dělat NAT.

# echo 1 >/proc/sys/net/ipv4/ip_forward
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Virtuální počítač bude mít dvě síťová rozhraní. Jedno bude v síti 192.168.68.0/29 s tap0. Druhé rozhraní bude ve virtuální multicastované síti 192.168.69.0/24. (Ty lomítka na konci řádků znamenají, že je to celé jeden příkaz. Přesněji řečeno lomítko ruší speciální význam znaku konec řádku.)

qemu /cesta/k/qemumachine.img -m 82 \
   -net nic,vlan=0,macaddr=52:54:00:12:34:51 \
   -net socket,vlan=0,mcast=230.0.0.1:54321 \
   -net nic,vlan=1,macaddr=52:54:00:12:34:50 \
   -net tap,vlan=1,ifname=tap0,script=no

Je nutné aby tento virtuální počítač také routoval:

qemu# echo 1 >/proc/sys/net/ipv4/ip_forward

Pokud se chcete z hostujícího počítače dostat do virtuální sítě, je nutné říci hostujícímu počítači kudy se tam chodí. To se provede přidáním routovacího pravidla.

# ip route add 192.168.69.0/24 via 192.168.68.2

Schematické znázornění celé situace.

Vše v jednom

Protože dělat tole všechno pokaždé znova není efektivní napsal jsem si skriptík. Aby vše chodilo jak má, spouštím ho přes sudo.

 #!/bin/bash

 kvm /storage/kvm/etch-pooh.img -m 82 \
   -net nic,macaddr=52:54:00:12:34:52 \
   -net socket,mcast=230.0.0.1:54321 &
 sleep 2
 kvm /storage/kvm/etch-prasatko.img -m 82 \
   -net nic,macaddr=52:54:00:12:34:53 \
   -net socket,mcast=230.0.0.1:54321 &
 sleep 2
 kvm /storage/kvm/lenny-kralicek.img -m 82 \
   -net nic,macaddr=52:54:00:12:34:54 \
   -net socket,mcast=230.0.0.1:54321 &
 sleep 2

 # nastavi tap0
 tunctl -t tap0
 ip addr add 192.168.68.1/29 dev tap0
 ip link set dev tap0 up
 ip route add 192.168.69.0/24 via 192.168.68.2
 # udela router
 echo 1 >/proc/sys/net/ipv4/ip_forward
 iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

 kvm /storage/kvm/etch-krystufek.img -m 82 \
   -net nic,vlan=0,macaddr=52:54:00:12:34:51 \
   -net socket,vlan=0,mcast=230.0.0.1:54321 \
   -net nic,vlan=1,macaddr=52:54:00:12:34:50 \
   -net tap,vlan=1,ifname=tap0,script=no \
   -net nic,vlan=2,macaddr=52:54:00:12:34:49 \
   -net user,vlan=2

 # uz nebude routovat
 iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
 echo 0 >/proc/sys/net/ipv4/ip_forward
 # zrusi tap0
 ip link set dev tap0 down
 ip addr del 192.168.68.1/29 dev tap0
 tunctl -d tap0


náhled obrazovky

Takto je možné vytvořit si jakoukoli síť. Pokud chceme virtuálních sítí více, stačí použít více portů pro multicast. Fantazii se meze nekladou.

Ve výuce potřebuji, aby se na rozdílných hostitelích spojili studenti do jedné nebo více sítí. Také je potřeba aby každá síťová karta měla jinou MAC adresu. Proto jsem napsal skript, který je umístěn na síťovém disku a každý student ho může zavolat.

$ start-qemu.sh 1 3

Spustí virtuální počítač, který bude mít dvě síťové karty. Jednu v síti 1 a druhou v síti 3. Image disku může být také na síti a jen pro čtení, protože parametr -snapshot zajistí, že změny se neukládají do image ale jen do poměti.

#!/bin/bash

zIP=$(ip a s | egrep global | perl -e '$vstup=<>; $vstup=~/(\d+\.\d+.\d+.\d+)/; ($vstup=$1)=~s/\.//g; $vstup=~/(..)(..)$/;  print "$1:$2\n";')

PRIKAZ="qemu /home/students/qemumachine.img -m 82"
for i in $@; do
    if [ $i == tap ]; then
        MAC="52:54:00:10:$zIP"
        PRIKAZ="$PRIKAZ -net nic,vlan=0,macaddr=$MAC,model=rtl8139 -net tap,vlan=0,ifname=tap0,script=no"
    else
        MAC="52:54:00:1$i:$zIP"
        PRIKAZ="$PRIKAZ -net nic,vlan=$i,macaddr=$MAC,model=rtl8139 -net socket,vlan=$i,mcast=230.0.0.1:5432$i"
    fi
done

echo $PRIKAZ -snapshot -kernel-kqemu;
$PRIKAZ -snapshot -kernel-kqemu;

Jen jeden router, VLAN na jednom hostiteli

Předchozí příklad má jednu nevýhodu: potřebujeme dva routery. Jeden router tvoří bránu mezi hostitelem a hostem, druhý routuje celou virtuální síť. Celá situace je tedy poměrně nepřehledná a adresní prostor musíme všelijak kouskovat na podsítě.

Pokud potřebujete virtuální síť na jednom hostiteli nabízí se možnost vytvořit pro každého hosta virtuální rozhraní tapX a všechny tyto rozhraní spojit do jednoho mostu (bridge). (Budete potřebovat balík bridge-utils.)

# tunctl
Set 'tap0' persistent and owned by uid 0
# tunctl
Set 'tap1' persistent and owned by uid 0
# ip link set dev tap0 up
# ip link set dev tap1 up
# brctl addbr br0 
# brctl addif br0 tap0 tap1
# ip link set dev br0 up
#
# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.06b60bd9dd1d       no              tap0
                                                        tap1

Rozhraní tap0 a tap1 nyní sdílí jedno médiu a není potřebné je nijak routovat. Rozhraní br0 nastavíme IP adresu ve virtuální síti -- bude pro ni tvořit bránu.

# ip addr add 192.168.68.1/29 dev br0

Dále je zapotřebí virtuální síť skrýt za NAT.

# sysctl net/ipv4/ip_forward=1
net.ipv4.ip_forward = 1
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

A můžeme virtuální stroje nastartovat. Přidělíme jim adresy v síti 192.168.68.0/29 a jako bránu nastavíme 192.168.68.1 (tedy br0).

$ sudo kvm lenny-pooh.img -m 82 \
-net nic,vlan=0,macaddr=52:54:00:12:34:50 -net tap,vlan=0,ifname=tap0,script=no &
$ sudo kvm lenny-prasatko.img -m 82 \
-net nic,vlan=0,macaddr=52:54:00:12:34:51 -net tap,vlan=0,ifname=tap1,script=no &

...a pak už jen uklidit:

# iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# sysctl net/ipv4/ip_forward=0
net.ipv4.ip_forward = 0
# brctl delbr br0
bridge br0 is still up; can't delete it
# ip link set dev br0 down
# brctl delbr br0
# tunctl -d tap0
Set 'tap0' nonpersistent
# tunctl -d tap1
Set 'tap1' nonpersistent

Jen jeden router, VLAN na více hostitelích

Pokud potřebujeme spojit do virtuální sítě více virtuálních počítačů na více hostitelích musí být routrem jeden z virtuálních počítačů. Ten bude mít dvě síťová rozhraní. Jedno bude připojeno k tap0, druhé bude připojeno do virtuální multicast sítě. Abychom si vystačili s jedním routrem, je nutné opět spojit rozhraní tap0 a fyzické rozhraní eth0 do mostu (bridge).

# ip addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:17:a4:e5:cc:df brd ff:ff:ff:ff:ff:ff
    inet 172.16.196.184/16 brd 172.16.0.255 scope global eth0
    inet6 fe80::217:a4ff:fee5:ccdf/64 scope link
       valid_lft forever preferred_lft forever
# ip route show
172.16.0.0/16 dev eth0  proto kernel  scope link  src 172.16.196.184
default via 172.16.0.99 dev eth0
# ip addr delete 172.16.196.184/16 dev eth0
# tunctl
Set 'tap0' persistent and owned by uid 0
# ip link set dev tap0 up
# brctl addbr br0
# brctl addif br0 eth0 tap0
# ip link set dev br0 up
# ip addr add 172.16.196.184/16 dev br0
# ip route add default via 172.16.0.99

Nastartujeme virtuální router:

$ sudo kvm lenny-pooh.img -m 82 \
-net nic,vlan=1,macaddr=52:54:00:12:34:51 -net socket,vlan=1,mcast=230.0.0.1:54321 \
-net nic,vlan=0,macaddr=52:54:00:12:34:50 -net tap,vlan=0,ifname=tap0,script=no &

Rozhraní s MAC 52:54:00:12:34:50 je na společném médiu (díky mostu) s fyzickým rozhraním eth0, proto mu přiřadím adresu a bránu ze sítě 172.16.0.0/16. Rozhraní s MAC 52:54:00:12:34:51 je ve virtuální multicastované síti. Na tomto virtuálním PC je nutné zapnout forwarding a NAT.

Na dalších hostitelích potom pustíme něco jako:

$ sudo kvm lenny-prasatko.img -m 82 \
 -net nic,vlan=0,macaddr=52:54:00:12:34:51 -net socket,vlan=0,mcast=230.0.0.1:54321 &

Musí to být opravdu na jiném hostiteli. Pokud takto nastavíte bridge a pustíte multicastovanou síť na jednou hostiteli, budou vznikat duplicitní pakety.

Bridge při startu

Pokud toužíte zapnou bridge hned při startu systému musíte změnit konfiguraci síťových rozhraní. Debian má k těmto účelům soubor /etc/network/interfaces.

auto br0 
    iface br0 inet static 
    address 192.168.0.2 
    netmask 255.255.255.0
    network 192.168.0.0 
    gateway 192.168.0.1 
    bridge_ports eth0 
    bridge_stp off 
    bridge_maxwait 5

Tím mám vše nachystáno a pokud se rozhodnu přidat k bridge další rozhraní, udělám jen něco jako:

# tunctl
# ip link set dev tap0 up
# brctl addif br0 tap0

Kouzlo jménem Proxy ARP

Všechno co bylo popsáné výše má jeden zásadní problém -- NAT. A NAT je zlo. Mně by se líbilo, kdyby celá virtuální síť byla jako na LAN. To není problém, ale na nadřazeném routru si musím hlídat směrovací pravidla -- to taky není ono. Řešení se jmenuje Proxy_ARP (krásné HOWTO)..

Na virtuálním routeru rozhraní, které je ve skutečné (velké) síti zapnu proxy_ARP a ip_forwarding

# echo 1 >/proc/sys/net/ipv4/conf/eth1/proxy_arp
# echo 1 >/proc/sys/net/ipv4/ip_forward

nebo

# sysctl net.ipv4.conf.eth1.proxy_arp=1
# sysctl net.ipv4.ip_forward=1

... a na ostatním virtuálním počítačům ve virtuální síti nastavím tento router jako bránu. Virtuální síť má přidělenou určitou část adresního rozsahu (velké) skutečné LAN. Když jdou pakety z virtuální podsítě ven, jdou klasicky přes bránu. Když jdou pakety z (velké) skutečné LAN do virtuální podsítě jsou všechny díky proxy_arp nasměrovány na virtuální router a ten už si s nimi poradí. Cekově se tak vytváří iluze, že celá virtuální síť je na LAN.

-nographic

Ve chvíli, kdy už máte dost hraní, chceto to spustit na ostro a hodláte Qemu/KVM použít k běhu více nezávislích strojů na jednou HW, bude se vám s největší pravděpodobností hodit parametr -nographic, který zakáže gravidký výstup. Samozdřejmě to předpokládá, že máte již vše, nebo skoro vše nachýstáno (hlavně síťoání) a další komunikace s virtuálním stojem bude probíhat pomocí pomocí ssh, vnc, nebo nějaké jiné podobné šílenosti. Pokud potřebujete vnc, podívejte se do manuálu na parametr -vnc. Osobně to dělám tak, že se k hostitelskému systému připojím pomocí ssh -X (grafický výstup vzdálených aplikací se mi zobrazuje na lokálním X-serveru), vše si nachystám a pak spustím Qemu s parametrem -nographic.

Jen ještě dodám, že pokud chcete virtualizovat Linux na Linuxu je v mnoha případech vhodnější použít VServer nebo OpenVZ.

Možné problémy

Pokud něco nejede, je častou příčinou problému firewall, který běží na hostiteli. Je proto nutné ho odpovídajícím způsobem nastavit (zastavit). man qemu

| navigace |

Licence Creative Commons Valid XHTML 1.0 Strict Valid CSS! Antispam.er.cz Blog: Tlapicka.net