VDE

Z DCEwiki
Skočit na navigaci Skočit na vyhledávání
VDE (Virtual Distributed Etherenet) byl až do implementace openvswitche do hlavní vývojové větve linuxového kernelu[1] jediná možnost, jak vytvořit komplexní síťovou infrastrukturu pro virtualizované prostředí.

Jeho propustnost je limitována tím, že používá sokety a virtuální switche běží jako normální procesy v userspace. Nicméně dodnes může mít své opodstatnění při testech síťové konfigurace, neboť podle vytížení procesů bylo možné ihned odhalit případný nežádoucí síťový provoz, který by za normálních okolností vedl k přetížení fyzického switche.

VDE switch se může uplatnit také pokud chcete tunelovat prostřednictvím běžného TCP připojení nižší síťové vrstvy.

vde

Poznámka Pozor na verzování VDE. Ačkoliv je v repozitory stále uvedeno číslo verze 2.3.1, prodělal tento balík utilit od doby jejího vydání docela dost změn. Především byly vyřešeny nějaké bugy, ale přibyl také kupříkladu plugin pro virtuální switche, který umožňuje monitorovat IP adresy na jednotlivých portech.

V oficiální distribuci Debianu jsou momentálně k dispozici balíčky založené na verzi z počátku srpna 2010. Ovšem jejich struktura je z mého hlediska poměrně chaotickým reliktem. Vytvořil jsem nově debianizovanou verzi, která formálně na tento distribuční balík navazuje a kterou máte možnost nainstalovat z naší Repository pro Debian amd64.

Pokud používáte 32 bitový systém, pak vám nezbyde, než si tento balíček překompilovat. Zdroják v repository by měl být použitelný bez ohledu na platformu.

Možná si kladete otázku, v čem je rozdíl, takže - balíček vde2 je nyní pouze dummy balíkem, který doinstaluje jednotlivé součásti VDE, ovšem zabalené podle logiky použití.

  • vde2-switch obsahuje virtuální switch a aplikaci unixterm, přes kterou se lze připojovat na řídící sokety VDE switchů a řídících utilit (např. wirefilter, aj.)
  • libvde2-switch obsahuje pluginy pro virtuální switch
  • vde2-plugs obsahuje součásti spojené s propojováním virtuálních switchů
  • vde2-utils obsahuje aplikace, skrz které lze kontrolovat virtuální switche a konektivitu skrz ně proudící
  • vde2-wrapper obsahuje původní wrapper pro QEMU vdeq, který se používá u verzí QEMU, které nemají integrovanou podporu VDE. Novější verze QEMU jej nepotřebuje.
  • libvde2-python obsahuje knihovnu přes kterou lze používat VDE z pythonu (věc, která byla přidána až po vydání stable verze)

Naopak jsem z balíků zcela vyřadil utility vdecmd a vdeterm, neboť je nelze nikde jinde použít než pouze s VDE a navíc lze jejich funkcionalitu (např. uchovávání historie příkazů) vyřešit mnohem elegantněji přes rlwrap.

Upozornění VDE je virtuální switch, který využívá sokety, což sebou přináší omezení při použití tzv. Jumbo Frames. To jsou pakety s větší velikostí než je 1472 bajtů (MTU 1500). U soketů je totiž maximální velikost ethernetového paketu omezena na 1514 bajtů přes IPN_SO_MTU: maximum transfer unit


Možnosti napojení backendu QEMU na sokety se využívá i při připojení přes VDE (Virtual Distributed Etherenet) virtuální switche, u kterých jsou fyzické ethernetové zásuvky nahrazeny sokety. U VDE je oproti připojení přes backend socket je výhodné, že virtuální switche běží v userspace a k vytvoření a propojování virtuální síťové infrastruktury nejsou nutně zapotřebí práva superuživatele, což je výhodné, neboť ani při vytvoření komplikované ethernetové infrastruktury nejsou nutné žádné zásahy do stávající síťové infrastruktury hostitele.

Virtuální switch

Základním prvkem VDE je virtuální switch. Ten vytvoří spuštěná instance aplikace vde_switch, a vypadá jako běžný adresář, ve kterém je soket s názvem ctl[2]. Umístění tohoto adresáře ( aka virtuálního switche) lze změnit při spouštění virtálního switche parametrem -s (resp. --sock). 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 a v případě, že je spuštěna paralelně další instance bez PID souboru to nemusí dopadnout dobře, neboť více procesů nemůže obsluhovat současně jeden soket.

Spuštěná instance aplikace vde_switch pak řídí komunikaci mezi sokety virtuálních zásuvek, které se umísťují do adresáře virtuálního switche, stejným způsobem, jako firmware fyzického switche řídí komunikaci mezi porty.

Poznámka
stroj:~# vde_switch -d -s /tmp/virtualni_switch
Řízení virtuálního switche

Aby bylo možné virtuální switch řídit, je třeba pamatovat při spouštění virtuálního switche na vytvoření soketu, přes který bude probíhat řízení switche. Normálně totiž, není-li virtuální switch spuštěn s parametrem -d jako démon na pozadí, je dostupná řídící konzole switche přímo na terminálu, ze kterého je virtuální switch spuštěn.

V případě, že chceme virtuální switch spouštět na pozadí, je nutné řídící konzoli virtuálního switche připojit na unixový soket, ke kterému se pak lze připojit aplikací unixterm. Cestu na soket nastavíme parametrem -M.

Další věc, která není k zahození je vytvoření PID souboru. Jednak se lze na tento soubor navázat při skriptování, ale především tím lze jednoduše zabránit spuštění paralelní instance virtuálního switche. Sice by se tím nic moc nestalo, ale nedošlo by k napojení jeho řídící konzole na soket a tak by byl tím pádem defakto nedostupný a nezbylo by, než jej "ustřelit" přes příkaz kill.

Upozornění Silně doporučuji při nahazování konektivity do vnější sítě používat pro tuto zásuvku nastavení PID souboru. Jednak lze pak jednoduše ve skriptu kontrolovat, je-li skript stále připojen[3], ale především tím lze zabránit paralelnímu připojení stejného rozhraní do jednoho místa.

To je zásadní rozdíl virtuálního switche od skutečného. V reálu totiž nikdy do jedné zástrčky současně dva konektory nedáte, kdežto u virtuálního switche v tom není žádný problém. Vytvoří se tím smyčka, která může "odbouchnout" port na switchi na mnohem vyšší úrovni, než je zrovna switch přes který je připojen váš hostitel[4].

U virtuálních zásuvek uvnitř VDE infrastruktury to až tak nevadí, protože vde switch pro každou zásuvku automaticky vytváří samostatný port a je-li aktivováno SPT (Spanning Tree Protokol), tak situaci vyřeší tím, že port který je v konfliktu ihned "ustřelí".

Asi největší výhodou přístupu k řídící konzoli switche je možnost rychle si ověřit co je do switche vlastně připojeno a jak

Poznámka
stroj :~# unixterm /tmp/vlan1.manage
VDE switch V.2.3.1
(C) Virtual Square Team (coord. R. Davoli) 2005,2006,2007 - GPLv2

vde$ port/print
0000 DATA END WITH '.'
Port 0001 untagged_vlan=0000 ACTIVE - Unnamed Allocatable
 Current User: root Access Control: (User: NONE - Group: NONE)
 IN:  pkts     142028          bytes            173036991
 OUT: pkts     105328          bytes             11385472
  -- endpoint ID 0003 module unix prog   : vde_plug: user=root PID=3025 172.0.0.2 33419 22 SOCK=/tmp/vlan1.switch/.03025-00000
Port 0002 untagged_vlan=0000 ACTIVE - Unnamed Allocatable
 Current User: root Access Control: (User: NONE - Group: NONE)
 IN:  pkts     101512          bytes             11183224
 OUT: pkts     141985          bytes            173034712
  -- endpoint ID 0008 module unix prog   : vde_plug: user=root PID=3053 172.0.0.2 33419 22 SOCK=/tmp/vlan1.switch/.03053-00000
.
1000 Success

vde$

Z předchozí ukázky výpisu lze vyčíst že je jsou do switche připojeny dvě zásuvky[5]. Jedna z nich je připojena na tap zařízení a druhá rozvádí připojení dál do VDE infrastruktury. VDE switche podporují pluginy a tak lze použít i plugin, který umožňuje zjistit jaká MAC adresa na kterém portu visí.

Přes tuto řídící konzoli lze také switch korektně vypnout příkazem shutdown.

Virtuální zásuvky

Virtuální zásuvka je ekvivalentem síťové zásuvky (portu) na fyzickém switchi. Součástí VDE je několik aplikací, co umí vytvořit virtuální zásuvku. Mohou si ji také vytvořit i aplikace, které podporují VDE. Do QEMU byla nativní podpora VDE přidána 19. července 2008. U starších verzí QEMU, bylo možné VDE používat přes wrapper vdeq.

vde_plug
je základní utilita, která se používá pro vytvoření virtuální zásuvky. Utilita dpipe vytváří virtuální dráty tím, že spojuje rourami stdin a stdout vstupy a výstupy virtuálních zásuvek.
vde_pcapplug
utilita, která se používá pro připojení virtuálního 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)
Spojování VDE switchů

Pro vytvoření virtuálního drátu mezi virtuálními switchi se v rámci nejrůznějších manuálů k VDE píše především o dpipe

dpipe
je utilita ke spojování vstupů a výstupů virtuálních zásuvek (ve skutečnosti soketů), vytvořených utilitou vde_plug. Emuluje obousměrnou rouru tím, že propojí deskriptory vstupu a výstupu. Používá se především k propojení virtuálních switchů v rámci jednoho stroje, ale dá se použít i k propojení virtuálních switchů napříč internetem. Vlastní přenos datového proudu přes síť však musí zajistit jiná aplikace. V příkladech použití VDE2 se nejčastěji objevuje ssh i když lze použít také socat nebo 'nc, jak uvidíte v níže uvedených příkladech.

Mnohem výhodnější než kombinaci dpipe, vde_plug a ssh je ale použít k propojení virtuálních switchů vde_cryptcab.

vde_cryptcab
Na rozdíl od dpipe, která pouze propojuje vstupy a výstupy mezi virtuální zásuvkou A a virtuální zásuvkou B, funguje na principu server - klient. Takže přes jeden naslouchající port virtuální zásuvky zapojené do virtuálního switche na stroji A lze připojit přes UDP protokol virtuální zásuvku z virtuálního switche na stroji B i virtuální zásuvku z virtuálního switche na stroji C a dalších. Pro šifrování propojení se používá algoritmus blowfish, který je rychlejší než algoritmy, které defaultně používá ssh. Data se honí přes UDP protokol, který má jednodušší hlavičky než TCP protokol přes který jede ssh, tudíž za stejný časový úsek lze sítí protlačit více dat než přes ssh tunel. Navíc lze monitorovat, jaká spojení jsou realizována.

Další utilitou, která umožňuje propojovat VDE switche přes internet je vde_over_ns.

vde_over_ns
Umožňuje tunelovat virtuální drát přes DNS protokol. Ten totiž obvykle nebývá při připojení do vnější sítě omezován. Takto realizované datové přenosy jsou však z principu pomalé a navíc při nich dochází k 10% ztrátě paketů. Jde tudíž o vyloženě nouzovou záležitost.

Schéma použití dpipe:

Poznámka 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

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

Poznámka
stroj:~# dpipe vde_plug /tmp/virtual_switch_A = vde_plug /tmp/virtual_switch_B
Poznámka Z hlediska výkonu při přenosu dat přes dpipe nehraje kupodivu velkou roli, jaká utilita se použije k síťovému propojení. 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, byla změna šifrovacího algoritmu na blowfish (stejný jako používá nativně vde_cryptcab.

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 pomocí dpipe prostřednictvím ssh.

Výhodné je, že tomto případě může být spojení sestaveno 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 jako server v režimu LISTEN čekat 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 připojit k naslouchajícímu portu přes socat zásuvku na stroji B

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 a QEMU podporuje backend pro připojení přes sokety, nemůže být nic jednoduššího, než napojit virtuál přímo k VDE soketu, 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 svedena do VDE switche a teprve na ten lze připíchnout virtuální stroj!

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.

Připojení VDE switche na vnější síť

Konektivitu z vnější sítě lze do VDE infrastruktury přivést buď připojením tap zařízení, na úrovni druhé vrstvy (ethernet), nebo přes pcap - na úrovni třetí vrstvy (TCP).

Rozdíl je v tom, že při připojení virtuální zásuvky přes vde_pcapplug vlastně nastavíme síťové zařízení které má poskytnout konektivitu do promiskuitního režimu, a z něj si pak "odsáváme" potřebnou konektivitu. Kdežto při připojení virtuální zásuvky přes vde_plug2tap "napíchneme" virtuální drát přímo na samostatné virtuální zařízení, které si vytvoříme v kernelu a toto zařízení pak umístíme do společného bridge se zařízením, kterým se do stroje dostává vnější konektivita. Čímž v podstatě dosáhneme stejného efektu, jako bychom použili u virtuálního stroje backend tap[6].

Příklad připojení zařízení eth0 na virtuální switch /tmp/virtual_switch_A přes vde_pcapplug

Poznámka
user@stroj~$ sudo vde_pcapplug -m 660 -g kvm -s /tmp/virtual_switch_A eth0

Použití vde_plug2tap je stejné. Rozdíl je pouze v tom, že vde_plug2tap nelze na jiné zařízení než typu tap použít. Více o zařízení typu tuntap viz backend tap.

Utility

vde_l3
je v podstatě virtuální IPv4 router, který umožňuje routovat datové přenosy mezi dvěma i více virtuálními switchi. Jeho hlavní význam je však v tom, že umožňuje realizovat shapping ( traffic control ) na úrovni třetí vrstvy (TCP/IP). Na úrovni druhé vrstvy, se kterou pracují vde_switche totiž jinak QoS implementovat nelze.
wirefilter
je utilita, která umožňuje za běhu měnit vlastnosti virtuálního drátu. Tzn. že umí nasimulovat pomalejší připojení. Daní za tuto funkcionalitu je však 10% ztráta paketů.
vde_autolink
je nadstavba pro virtuální switche, která umožňuje automatické sestavování a údržbu virtuálních drátů.
slirpvde
je věc převzatá do VDE z QEMU. SLiRP je aplikace, která emuluje připojení přes sériovou linku. V podstatě se jedná o virtuální rozhraní, které zajišťuje NAT mezi vnější a vnitřní sítí. Pro použití VDE v kombinaci s QEMU nemá tato aplikace žádný význam.

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 ve virtuálu. To však má smysl pouze pro testovací a experimentální účely, neboť daní za tento komfort je 10% ztráta paketů a tím i pokles propustnosti sítě.

Použití aplikace wirefilter je jednoduché - přidá se do kolony příkazu dpipe do místa, na kterém chceme připojení "škrtit". Viz příklad spojení virtuálního switche virtual_switch_A na stroji A s virtuálním switchem virtual_switch_B přes wirefilter, na kterém pak lze řídit po připojení přes soket /tmp/wire_A_B.console průtok dat:

Poznámka
A:~# dpipe vde_plug /tmp/virtual_switch_A = wirefilter -M /tmp/wire_A_B.console = vde_plug /tmp/virtual_switch_B

Skript pro nahození a připojení virtuálního switche přes pcap

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

Poznámka
#!/bin/bash
# $1 - start|stop
# $2 - cesta ke switchi
# $3 - síťové rozhraní s vnější konektivitou

if [ "$1" == "" ]; then
    exit 0;
fi

switch() {
    if [ "$1" == "start" ]; then
        if [ -f "$2.pid" ]; then
            if [ -d "/proc$(<$2.pid)" ]; then
                echo "Virtuální switch je zapnutý" && exit 0
            else
                # Switch už neběží, zruš PID soubor a zavolej funkci switch znovu
                rm -f $2.pid
                switch $@
            fi
        else
            # Switch neběží, může být nahozen
            vde_switch -d -s $2.switch -M $2.manage -p $2.pid &
            # Propojení switche s rozhraním předaným jako třetí parametr
            vde_pcapplug -m 660 -g kvm -s $2.switch $3 &
        fi
    elif [ "$1" == "stop" ]; then
        kill -s SIGQUIT $(</tmp/$2.pid)
        rm /tmp/$2.pid
    else
        echo "Použití: $0 [ start | stop ] path dev"
    fi
}

switch $@

Skript po spuštění vytvoří adresář pro sokety, jehož název který bude končit příponou .switch, pid soubor s příponou .pid a řídící soket s příponou .manage

  1. Openvswitch byl zařazen do hlavní vývojové větve linuxového jádra od verze 3.3, vydané 18. března 2012
  2. Pozor na záměnu, nejde o soket přes který lze VDE switch řídit!
  3. Je-li proces realizující zásuvku ukončen, přestane v adresáři /proc existovat podadresář s tímto číslem procesu
  4. Tato situace může nastat především tehdy, když správce fyzické infrastruktury takovou situaci nemá ošetřenou na switchích nižší úrovně. Ty by totiž měly zachytit tento problém hned v první linii.
  5. Je-li vnější konektivita do switche přivedena přes vde_pcapplug , je místo vde_plug ve výpisu vde_pcapplug)
  6. Rozdíl je ale v tom, že je-li použit přímo backend tap, tak ovladač virtio-net z virtuálního stroje může využívat "zkratku" do prostoru jádra hostitele přes modul vhost-net, je-li k dispozici. Což bohužel u připojení přes VDE nelze.