KVM (konfigurace sítě)

Z DCEwiki
Skočit na navigaci Skočit na vyhledávání
Model qemu networking.svg

QEMU pro každé síťové zařízení ( NIC - Network Interface Card ) virtuálního stroje má samostatné dvě části. Část, která zprostředkovává komunikaci QEMU s prostředím virtuálu (označovanou jako fore) a část, která komunikuje se systémem hostitele (označovanou backend). Obě tyto části se konfigurují na příkazovém řádku samostatně, ale přes stejnou přes volbu -net

Jak funguje připojení QEMU

Na schematickém modelu vpravo je zobrazeno jakým způsobem funguje síťová infrastruktura QEMU.

QEMU (zelený blok) jako takové je userspace aplikace, která emuluje hardware pro spuštěný virtuál.

Poznámka Pokud není v jádře přítomný hypervizor, který by umožňuje virtuálu využít virtualizaci CPU na úrovni hardware hostitele, tak je virtualizován i procesor virtuálního stroje.

Virtuální stroj pak komunikuje s emulovaným hardware, tak jako kdyby šlo o fyzické zařízení. Tzn. že rychlost, s jakou pak během virtualizace probíhají síťové přenosy mezi aplikacemi spuštěnými uvnitř virtuálu a backendem QEMU, je daná parametry emulovaného hardware a ovladačem použitým ve virtuálním stroji.

Použití vlan v konfiguraci NIC u QEMU

Nastavení vlan v nastavení NIC u QEMU nemá nic společného s nastavením skutečných vlan (IEEE 802.1Q), ale je určeno k propojení backendu a příslušného NIC rozhraní v rámci spuštěné instance virtuálního stroje.

Pokud totiž žádná vlan v konfiguraci NIC nastavena není, jsou při spuštění QEMU automaticky všechny nadefinované NIC i jejich backendy ve vlan 0, což v případě, že je do virtuálního stroje přivedeno na úrovni backendu více síťových segmentů, může vést k tomu, že mezi nimi začnou protékat data, aniž by na to měl virtualizovaný stroj vůbec nějaký vliv.

           GUEST
    eth0    eth1      eth2
     |       |         |
----------------------------
|   NIC     NIC       NIC  |
|          vlan=0          |
|   TAP  X  USER      NONE |
----------------------------
     |        |
    VLAN1   VLAN2
        HOST
Upozornění Skutečnost že takto mohou být propojeny jinak vzájemně oddělené segmenty může vést k síťovým kolapsům! Viz výše uvedený příklad.

Nastavení vlan v QEMU je tedy určeno k separaci jednotlivých NIC rozhraní a připojených backendů. Každé NIC zařízení zvoleným číslem vlan svázáno s příslušným backendem. Tím lze vnější konektivitu bezpečně přivést do prostředí virtuálu, aniž by tím hrozilo nekontrolovatelné propouštění ethernetových rámců mezi jinak oddělenými síťovými segmenty.

           GUEST
    eth0    eth1      eth2
     |       |         |
----------------------------
|   NIC  |  NIC   |   NIC  |
| vlan=1 | vlan=2 | vlan=0 |
|   TAP  |  USER  |  NONE  |
----------------------------
     |        |
    VLAN1   VLAN2
        HOST
Poznámka Předchozí text o použití vlan u QEMU je velmi důležitý z hlediska pochopení dalšího textu.

Většinou totiž mívají virtuální stroje maximálně jedno až dvě rozhraní a jen málokdo řeší, jak dostat do jednoho virtuálního stroje více subnetů. Proto se u většiny postupů na internetu s nastavením a významem vlan při konfiguraci síťových rozhraní u QEMU často nesetkáte.

Osobně jsem zjistil k čemu jsou až v situaci, kdy jsme narazili na skutečnost, že nám u virtuálního stroje, který byl předtím virtualizován v prostředí XENu najednou někudy protékají pakety mezi interní VLAN a veřejnou sítí.

Při laborování s tímto virtuálním strojem jsme s překvapením zjistili, že pakety začínají protékat dřív, než vůbec stroj začne bootovat! Zkusili jsme tedy oddělit jednotlivé NIC (a k nim i příslušné backendy) právě pomocí vlan a tak intuitivně přišli na to, k čemu vlastně jsou. Až dodatečně jsem narazil i na webovou stránku, která použití vlan zmiňuje a vysvětluje[1].

Možnosti "backendové" části NIC

Backendová část síťové karty zajišťuje komunikaci QEMU s odpovídající síťovou infrastrukturou hostitelského systému. Pokud má virtuální stroj pouze jedno NIC zařízení, a má být navíc za NAT, tak většinou není z hlediska backendu nutné nic složitého řešit. Maximálně vytažení nějakého portu z virtuálu.

Situace se však od základu mění, pokud má mít virtuální stroj síťových zařízení více a navíc - má-li každé z nich používat jiný backend.

Na příkazovém řádku většinou následuje konfigurace backendu bezprostředně za konfigurací fore části NIC, ale to nestačí! K jednoznačnému svázání příslušného backendu s fore částí NIC musí být nastavená stejná hodnota vlan.

Je-li ve virtuálním stroji vytvořeno více NIC zařízení a všechny mají nastavenou stejnou hodnotu vlan jako příslušný backend, tak to bude mít stejný efekt, jako bychom mezi backend a NIC zařízení připojili HUB.

           GUEST
    eth0    eth1      eth2
     |       |         |
----------------------------
|   NIC     NIC   |   NIC  |
|  vlan=1  vlan=1 | vlan=2 |
|       USER      |   TAP  |
----------------------------
         |             |
       VLAN1         VLAN2
              HOST


user

Většinou je to jedno, že má QEMU na jeden background připojeno více NIC zařízení, protože výchozí backend, který QEMU používá k připojení k vnější síti je user - což je ve skutečnosti připojení k tap zařízení přes interní NAT.

Při konfiguraci síťového rozhraní ve virtuálním stroji přes DHCP klienta (u linuxu dhclient) interní DHCP server QEMU přidělí každému z nich samostatnou IP adresu. Ve výchozím stavu přiděluje tento interní DHCP server adresy v rozsahu 10.0.2.x , ale dalšími parametry lze tento interní DHCP server podle potřeby překonfigurovat.


Poznámka
… -net nic,maccaddr=00:00:0a:00:00:0a,if=virtio -net user …

none

Jak plyne z předchozího odstavce, každé další NIC zařízení v QEMU má k dispozici konektivitu přes NAT. Pokud však chceme mít uvnitř virtuálního stroje NIC zařízení, které žádnou konektivitu nemá, tak ji musíme explicitně zakázat tím, že nastavíme backend none a zařízení, které konektivitu mít mají, svážeme pře vlan s příslušnými backendy.

Poznámka
… -net nic,maccaddr=00:00:0a:00:00:aa,if=virtio -net none \
-net nic,maccaddr=00:00:0a:00:00:bb,if=virtio,vlan=1 -net user,vlan=1 \
-net nic,maccaddr=00:00:0a:00:00:cc,if=virtio,vlan=1 \
-net nic,maccaddr=00:00:0a:00:00:dd,if=virtio,vlan=2 -net tap,ifname=tap0,vlan=2

socket

Pokud nepotřebujeme mít ve virtuálních strojích vnější konektivitu ale chceme je pouze propojit mezi sebou, můžeme využít ke komunikaci background socket, který komunikuje na úrovni 5. vrstvy.

  • Komunikace mezi stroji může probíhat jak prostřednictvím TCP, tak UDP paketů.
  • Při použití TCP protokolu bude fungovat stroj virtualA jako server a stroj virtualB jako klient.
  • Přes soket lze navzájem propojit do jedné sítě i více než dva stroje. U připojení přes TCP by konfigurace dalších strojů vypadala stejně jako u stroje virtualB.
  • Při použití UDP protokolu vypadá konfigurace u všech strojů stejně.
  • Je třeba mít na paměti, že každý stroj musí mít svou vlastní nekonfliktní MAC adresu, což QEMU interně neřeší. Je tedy třeba pro každý stroj unikátní MAC nastavit ručně.


  • Pokud má TCP komunikace probíhat po síti, tak se v konfiguraci stroje virtualB, virtualizovaného na jiném stroji, uvede místo localhost IP adresa stroje, kde je virtualizován virtualA (který má otevřen soket v režimu LISTEN)
Upozornění Komunikace přes sokety má několik omezení:
  • Aby mohl být při spuštění virtuálního stroje vytvořen příslušný soket, musí být QEMU spuštěno pod uživatelem root, protože obyčejný uživatel zpravidla k soketům nemá přístup
  • Při připojení přes soket na úrovni TCP stroje mezi sebou komunikují prostřednictvím stroje, který má soket nastaven v režimu listen (což je u výše uvedeného příkladu stroj virtualA. Ten funguje jako server. V případě, že bude vypnut, síťová komunikace mezi ostatními stroji přestane fungovat!

Konfigurace soketu s připojením přes TCP protokol

virtualA ---------------
             |         |
          virtualB  virtualC

Konfigurace stroje virtualA..

Poznámka
… -net nic,maccaddr=00:00:0a:00:aa:aa,if=virtio -net socket,listen=localhost:1234 …

-net nic,maccadr=aa. -net socket,listen=localhost:1234

Konfigurace stroje virtualB..

Poznámka
… -net nic,maccaddr=00:00:0a:00:bb:bb,if=virtio -net socket,connect=virtualA:1234 …

Konfigurace stroje virtualC..

Poznámka
… -net nic,maccaddr=00:00:0a:00:cc:cc,if=virtio -net socket,connect=virtualA:1234 …

Konfigurace soketu s připojením přes UDP protokol

Při propojení strojů přes UDP protokol nefiguruje v konfiguraci IP adresa žádného hostitele, ale multicastová adresa rozhraní[2], přes které spolu hostitelé mohou komunikovat.

    --------------------
    |        |         |
virtualA  virtualB  virtualC

Konfigurace stroje virtualA..

Poznámka
… -net nic,maccaddr=00:00:0a:00:aa:aa,if=virtio -net socket,mcast=224.0.0.1:1234 …

Konfigurace stroje virtualB..

Poznámka
… -net nic,maccaddr=00:00:0a:00:bb:bb,if=virtio -net socket,mcast=224.0.0.1:1234 …

Konfigurace stroje virtualC..

Poznámka
… -net nic,maccaddr=00:00:0a:00:cc:cc,if=virtio -net socket,mcast=224.0.0.1:1234 …

QEMU connection model socket.svg

vde

Možnosti napojení backendu QEMU na sokety se využívá i při připojení přes vde2 virtuální switche, u kterých jsou fyzické ethernetové zásuvky nahrazeny sokety. Proti připojení přes socket je výhodné, že virtuální switche běží v userspace a k propojování virtuální síťové infrastruktury nemusí být zapotřebí práv superuživatele, což je z hlediska variability použití VDE (Virtual Distributed Etherenet) velmi flexibilní, neboť ani při emulaci komplikované ethernetové infrastruktury v rámci jednoho fyzického stroje, nejsou nutné žádné zásahy do stávající síťové infrastruktury hostitele.

Virtuální switch

Virtuální switch tvoří spuštěná instance aplikace vde_switch, která vytvoří adresář se soketem pojmenovaným ctl, přes který pak lze switch řídit. Umístění tohoto adresáře ( aka virtuálního switche) do kterého se pak umisťují sokety virtuálních zásuvek lze změnit při spouštění virtálního switche parametrem -s (resp. -sock). Defaultně, není-li při spouštění příkazu vde_switch uvedeno jinak, je totiž výchozím adresářem virtuálního switche - /tmp/vde.ctl. Tato instance aplikace vde_switch pak zajišťuje komunikaci mezi sokety virtuálních zásuvek jako skutečný switch.

Poznámka
stroj:~# vde_switch -d -s /tmp/virtualni_switch

Virtuální zásuvky

Virtuální zásuvka : je ekvivalentem fyzického portu na fyzickém switchi. Vytvoří se spuštěním instance aplikace vde_plug, která se v adresáři virtuálního switche vytvoří soket se vstupem a výstupem přesměrovaným na stdin a stdout - tento soket (virtuální zásuvka), pak v rámci virtuálního switche funguje jako normální port na switchi. V instalaci balíku vde2 jsou k dispozici tři utility pro vytváření virtuálních zásuvek.

vde_plug
se používá při spojování přes virtuální dráty - stdin a stdout
vde_pcapplug
se používá pro připojení virtuálního portu switche k síťovému interface na úrovni IP (TUN)
vde_plug2tap
se používá pro připojení virtuálního portu switche k síťovému interface na úrovni ethernetu (TAP)
Poznámka Virtuální zásuvky si mohou tvořit také samy aplikace, pokud podporují vde, jako např. QEMU.

Ke spojování vstupů a výstupů virtuálních zásuvek (ve skutečnosti soketů), vytvořených utilitou vde_plug, používá VDE obousměrnou rouru, kterou sestavuje utilita - dpipe.

Použití této roury je jednoduché: dpipe <plugA> = <plugB>

plugA
je vstup a výstup z virtuální zásuvky ve switchi A
plugB
je vstup a výstup z virtuální zásuvky ve switchi B

Viz příklad reálného použití:

Poznámka
stroj:~# dpipe vde_plug /tmp/virtual_switch_A = vde_plug /tmp/virtual_switch_B

Tato obousměrná roura se používá i při propojení virtuálních switchů napříč internetem. Vlastní přenos datového proudu po síti však musí zajišťovat jiná aplikace. V příkladech použití VDE2 se lze nejčastěji setkat s využitím ssh, i když lze použít i jinou utilitu - v následujících příkladech bude uvedeno použití utility socat nebo 'nc.

Poznámka Z hlediska výkonu při přenosu dat nehraje kupodivu velkou roli, jaká utilita se k propojení použije. Při praktických testech, které jsem prováděl, se ukázalo, že rozdíl v přenosové rychlosti při použití "ssh versus socat" byl vcelku zanedbatelný. Naopak připojení přes ssh se ukázalo jako stabilnější. Co však mělo mírně zlepšující vliv na rychlost přenosu, bylo nastavení šifrovacího algoritmu.
Spojení dvou vzdálených VDE switchů

Následující příklad demonstruje propojení virtuálního switche virtual_switch_A na stroji A s virtuálním switchem virtual_switch_B na stroji B prostřednictvím ssh. V tomto případě je spojení sestavované pouze ze stroje A.

Poznámka
A:~# dpipe vde_plug /tmp/virtual_switch_A = ssh user@B vde_plug /tmp/virtual_switch_B

QEMU connection model vde.svg

Pokud chceme stejné spojení realizovat přes socat, musíme spojení sestavovat postupně na stroji A i B. Pro přenos můžeme použít jak UDP, tak TCP. Vždy však musí být jedna strana v režimu LISTEN, kdy čeká na připojení klienta. Nejprve je tedy třeba spustit "naslouchající" zásuvku na UDP portu stroje A

Poznámka
A:~# dpipe vde_plug /tmp/virtual_switch_A = socat - UDP4-LISTEN:6666,reuseaddr &

A teprve pak zásuvku na stroji B, která se připojí k naslouchajícímu UDP portu stroje A

Poznámka
B:~# dpipe vde_plug /tmp/virtual_switch_B = socat - UDP4:A:6666 &

QEMU connection model vde socat.svg

Více podrobností ke konfiguraci portů při přesměrování přes socat viz manuál.

Upozornění Zdálo by se, že když existuje možnost přesměrování datového proudu ze zásuvky VDE switche na TCP soket, nemůže být nic jednoduššího, než napojit virtuální stroj přímo na soket, bez toho že by se musel zapojit do virtuálního switche. Ovšem chyba lávky - tohle nefunguje. Z TCP soketu musí být konektivita opět svedena do VDE switche a teprve na ten pak lze připíchnout virtuální stroj


Při porovnání výsledků propojení ssh versus socat mé testy ukázaly, že rozdíl v přenosové rychlosti byl minimální. Z hlediska uživatele je připojení přes ssh bezpečné a i bezproblémové. Zpočátku jsem se domníval, že bude z hlediska propustnosti dat ssh horší varianta, neboť na rozdíl pouhého přesměrování - které dělá socat, data průběžně šifruje. Ale praxe ukázala, že naopak použití ssh vykazuje mírně lepší výsledky - obzvláště při nastavení šifrovacího algoritmu blowfish.

Co se však ukázalo jako nežádoucí, to bylo použití komprese. U ssh se ve výchozí konfiguraci totiž data nekomprimují. Při použití komprese se spojení mezi virtuálními switchi hroutilo.

Podstatně větší roli na výkon při síťové komunikaci, než použití přenosové utility, má fakt, zda-li je či není u virtuálního stroje zapnuta KVM virtualizace a také jaké NIC zařízení QEMU do virtuálu propaguje.

Řízení virtuálního switche

Při spuštění virtuálního switche se v něm vytvoří soket - ctl. Skrz něj probíhá řízení switche. Totiž, pokud není uveden parametr -d, kterým se spustí virtuální switch na pozadí, spustí se na aktuální konzoli ovládací shell, skrz který lze switch řídit.

Management konzole lze provádět prostřednictvím unixového soketu parametrem -M na která se lze připojit aplikací unixterm

Skriptování

Jednoduchý spouštěcí skript pro vytvoření páteřního soketu, na který mohou být připojovány virtuální switche spouštěných strojů:

Poznámka
#!/bin/bash
if [ "$1" == "" ]; then
    exit 0;
    fi
if [ "$1" == "start" ]; then
    if [ -f "/tmp/paterni_soket.pid" ]; then
	echo "Virtuální switch je zapnutý" && exit 0
	fi
    # Vytvoření páteřního soketu přes který mohou lézt virtuály ven
    vde_switch -d -s /tmp/paterni_soket &
    echo $(($!+1)) > /tmp/paterni_soket.pid
    # Propojení páteřního soketu s rozhraním eth0
    vde_pcapplug -m 660 -g kvm -s /tmp/paterni_soket eth0 &
    echo $(($!+1)) >> /tmp/paterni_soket.pid
elif [ "$1" == "stop" ]; then
    kill $(</tmp/paterni_soket.pid)
    rm /tmp/paterni_soket.pid
else
    echo "Použití: $0 [ start | stop ] "
fi

Poznámky ke skriptu:

  • U vde_pcapplug jsou nastavena práva tak, aby se mohl každý uživatel s právy ke spouštění virtuálních strojů připojit na vnější síť.
  • Při zápisu PID se musí přičíst jedna, protože PID spuštěného procesu bude o tuto hodnotu vyšší, je PID zachycený skriptem
  • Pro vytváření soketů může být použit libovolný adresář, do kterého lze zapisovat.
  • Soubor, ve kterém jsou uloženy PID má smysl především proto, abychom při zastavení "vypnuli" pouze procesy spojené s tímto switchem

wirefilter

Součástí vde2 je také nástroj wirefilter, který umožňuje dynamicky měnit parametry virtuálního drátu, a tím i ovlivňovat dostupnou konektivitu. To však má smysl pouze pro testovací a experimentální účely, neboť daní za to je 10% ztráta paketů. Je-li wirefilter zkombinován ještě s ssh připojením, tak propustnost sítě razantně poklesne.

tap

QEMU connection model tap.svg

QEMU connection model l2tp.svg

Konfigurační možnosti "fore" části NIC

Vytvoření síťového rozhraní v prostředí virtuálního stroje zajišťuje část fore, která se od backend části síťového rozhraní liší od pohledu tím, že začíná parametrem nic.

Poznámka
… -net nic,maccaddr=00:00:0a:00:00:0a,if=virtio -net none
…

Výše uvedený příklad demonstruje vytvoření síťového rozhraní s MAC adresou 00:00:0a:00:00:0a, které se ve virtuálu "ohlásí" jako virtio zařízení.

Poznámka NIC zařízení, které by se vytvořilo na základě výše uvedené konfigurace by mělo nastaven backend na none, což znamená, že by vůbec nebylo připojeno k síti. Pokud by tato volba nebyla uvedena, bylo by automaticky na straně backendu připojené přes NAT (backend user)

Nastavení dalších síťových zařízení se provádí zcela jednoduše - přidáním dalších "párů" volby -net.

Upozornění V případě, že je konfigurováno více NIC pro jeden stroj je nutné zajistit, aby nemohlo dojít na síti k nějakému konfliktu - duplicitní MAC adresa, překřížené vlany, aj.

vlan

Parametr vlan je třeba použít pokud má mít virtuální stroj více síťových rozhraní, které mezi sebou nesmí být vzájemně propojeny. Není-li parametr vlan uveden, nastavuje QEMU automaticky pro všechny NIC vlan 0. Takže v případě, že je každý NIC na úrovni backendu připojen do jiného subnetu, začne mezi nimi propouštět pakety, aniž by s tím spuštěný virtuál měl cokoliv do činění.

macaddr

QEMU pro každé další síťové rozhraní negeneruje automaticky samostatnou MAC adresu, nýbrž používá pořád tu stejnou. Má-li tedy virtuální stroj mít více síťových karet, nebo je-li připojených více virtuálních strojů virtualizovaných přes QEMU do jednoho síťového segmentu, je vhodné pro každé NIC nastavit vlastní MAC adresu.

model

Prostřednictvím konfiguračního parametru model lze vhodnou volbou typu virtuální síťové karty ovlivnit, jaký ovladač virtualizovaný stroj použije pro komunikaci se síťovým rozhraním a tím ovlivnit i rychlost zpracování jeho síťové komunikace.

Jaké modely umí QEMU emulovat, lze zjistit spuštěním QEMU s volbou..

Poznámka
… -net nic,model=?

Použitelné modely síťových karet z hlediska propustnosti...

virtio
Virtio network device je z hlediska konektivity tou nejoptimálnější volbou, pokud má virtuální stroj k dispozici virtio ovladače. QEMU totiž při komunikaci přes virtio nic neemuluje, ale předává pakety ke zpracování přímo do kernelu. Ovladače k virtio pro systémy MS Windows lze stáhnout z webu fy. Red Hat inc.. Ovladač v linuxovém jádře virtuálního stroje se jmenuje virtio-net.
e1000
Emulace skutečné síťové karty Intel 82549EM Gigabit je v QEMU výchozí, pokud však nemá virtualizovaný systém pro tuto síťovou kartu nainstalovaný ovladač, je nutno vyzkoušet některé jiné z následujících zařízení.
pcnet
Gigabajtová síťová karta, která se hlásí jako AMD 79c970 [PCnet 32 LANCE]]. Ovladač k ní je součástí vmware tools
rtl8139
Emuluje kartu s čipem Realtec. Tento typ 100 megabitové síťové karty patřil mezi nejběžnější síťové karty, které nebyly z produkce Intelu. Výhodné je, že ovladač k této síťové kartě je přímo ve Windows XP
ne2k_pci
Realtek RTL-8029(AS) byla pouze 10 megabitová síťová karta, jedna z posledních, které ještě podporovaly koaxiální kabeláž. Tuto síťovou kartu však bylo možné rozchodit i pod DOSem
Poznámka Speciálně u virtio NIC lze nastavit i další parametry, které umožňují emulovat síťovou kartu na PCI-E, z hlediska běžného nasazení však nejsou tyto parametry podstatné.

name

Parametr name umožňuje nastavit pro NIC jméno, pod kterým pak bude příslušné rozhraní známé v prostředí monitorovací konzole QEMU.