Virtuelles Netzwerk in einer Qemu-KVM Umgebung einrichten

Aus Siduction Wiki DE
Wechseln zu: Navigation, Suche


Begriffserklärung


Warum ein virtuelles Netzwerk einrichten

Dieser Artikel behandelt ein fortgeschrittenes Thema der Virtualisierung und baut auf ein gewisses Basiswissen und Erfahrung rund um Qemu-KVM auf. Standardmäßig ist eine virtuelle Maschine vom Wirtsystem (Host) aus Sicherheitsgründen abgeschirmt und somit über die normalen Netzwerkverbindungen, wie ftp, ssh, scp usw. nicht zu erreichen. Unter Umständen ist es für bestimmte Einsatzzwecke nötig das ein gemeinsames Netzwerk von allen virtuellen Gästen, sowie des Wirtsystem nutzen zu können. Qemu-KVM kann mit Hilfe einer Software-Brigde das lokale Netzwerk mit dem virtuellen Netz verbinden.


Installation

Zuerst müssen auf dem Wirtsystem zwei Pakete installert damit man mit den Konfigurationsarbeiten beginnnen kann. Dazu ein die Konsole öffnen und als root einloggen. Danach die Pakete uml-utilities und bridge-utils installieren.

# apt-get install uml-utilities bridge-utils


Damit das ganze überhaupt zum Laufen kommt sind folgende Qemu-KVM Pakete nötig.

  • etherboot-qemu
  • qemu-keymaps
  • qemu-kvm
  • qemu-utils

Wenn noch nicht installiert dann ggf. nachholen.

# apt-get install qemu-kvm qemu-utils


Konfiguration

Die Konfiguration gliedert sich in zwei Teile, erstens am Wirtsystem und zum zweiten am Gastsystem(en).

Konfiguration vom Wirtsystem anpassen

Bitte vor dem verändern von wichtigen Konfigurationsdateien die jeweilige Datei an einen sicheren Ort kopieren um für alle Fälle ein Backup zu besitzen.

Gruppenzugehörikeit

Der User der später die virtuellen System starten und nutzen soll muss in der Gruppe kvm sein. Dazu den User modifizieren. Hier im Beispiel den Usernamen michael an eigene Bedürfnisse anpassen.

# usermod -a -G kvm michael


Netzwerk anpassen

Zur Netzwerk Konfiguration in /etc/network/interfaces muss diese neu erstellt werden. Das Devive bri0 ist die "Software-Brücke" (Bridge) die das Verbindungsstück zwischen lokalen und virtuellen Netz ist. eth0 ist das reale Neztwerkinterface das im Rechner steckt. Die Bridge wird mit einer festen IP-Adresse konfiguriert. Im Beispiel gehe ich von dem Netz 192.168.178.0 aus, an dem drei Machinen angeschlossen sind, ein Wirtsystem und zwei virtuelle Gäste sowie ein Router (z.B. FritzBox) an dem das Wirtsystem per LAN-Kabel angeschlossen ist.

IP-Adressen:

  • 192.168.178.001 Router zum Anschluss ans Internet
  • 192.168.178.100 Wirtsystem
  • 192.168.178.101 Erstes Gastsystem
  • 192.168.178.102 Zweites Gastsystem


auto lo
iface lo inet loopback
auto eth0
iface eth0 inet manual
auto bri0
iface bri0 inet static
     address 192.168.178.100
     broadcast 192.168.178.255
     gateway 192.168.178.1
     netmask 255.255.255.0
     network 192.168.178.0
     dns-nameservers 192.168.178.1
     dns-search 192.168.178.1
     bridge_ports eth0
     bridge_fd 9
     bridge_hello 2
     bridge_maxage 12
     bridge_stp off


KVM Startscript anpassen

Das KVM-Startscript muss unbedingt angepasst werden. Nachfolgend werden die Originalversion und die angepasste Version gezeigt. Wichtig ist hier vorallen die erste Zeile im Script, der sogenannte Shebang . Diese ist leider bei der Linux-Distribution siduction ein Link auf die dash und bei der Ausführung Problem bereitet. Bitte abändern und wie weiter unten aufgelistet, auf die bash linken.

#! /bin/sh
# Script to bring a network (tap) device for qemu-kvm up
# The idea is to add the tap device to the same bridge
# as we have default routing to.

switch=$(ip route ls | \
   awk '/^default / {
         for(i=0;i<NF;i++) { if ($i == "dev") { print $(i+1); exit; } }
        }'
       )
/sbin/ifconfig $1 0.0.0.0 up

# only add the interface to default-route bridge if we
# have such interface (with default route) and if that
# interface is actually a bridge.
if [ -n "$switch" -a -d /sys/class/net/$switch/bridge/. ]; then
  /usr/sbin/brctl addif $switch $1 || :
fi


Hier die angepasste und vereinfachte Version mit korrekter Shebang.

#!/bin/bash
switch=$(/sbin/ip route list | awk '/^default / { print $NF }')
/usr/bin/sudo /sbin/ifconfig $1 0.0.0.0 up
/usr/bin/sudo /usr/sbin/brctl addif ${switch} $1

sudo anpassen

Um als User die jeweiligen Aktionen wie z.B.Netzwerk starten und stoppen, TUN- und TAP-Devices erzeugen usw durchführen zu können,. sind einige Command -Aliase in der sudo-Konfiguration zu definieren. Der User, der in der Gruppe kvm ist, soll ohne Passwortabfrage die Kommandos tunctl, ifconfig brctl und ip ausführen dürfen.

Dazu als root auf der Konsole das Kommando visudo ausführen und die nachfolgenden Zeilen via Copy&Paste einfügen und abspeichern:

Cmnd_Alias KVM = /usr/sbin/tunctl, /sbin/ifconfig, /usr/sbin/brctl, /sbin/ip
%kvm ALL=(ALL) NOPASSWD: KVM

Als User kann man dies überprüfen, indem man in der Konsole sudo -l ausführt:.

$ sudo -l
Matching Defaults entries for michael on this host:
   env_reset

User michael may run the following commands on this host:
   (ALL) NOPASSWD: /usr/sbin/tunctl, /sbin/ifconfig, /usr/sbin/brctl, /sbin/ip

Konfiguration vom Gastsystem anpassen

Auf den ersten Gast ist die Netzwerk Konfiguration wie folgt zu erstellen.

auto lo
iface lo inet loopback
allow-hotplug eth0
iface eth0 inet static
  address 192.168.178.101
  broadcast 192.168.178.255
  gateway 192.168.178.1
  netmask 255.255.255.0
  network 192.168.178.0
  dns-nameservers 192.168.178.1
  dns-search 192.168.178.1


Ebenso auf dem zweiten Gast die Netzwerk Konfiguration abändern, natürlicher mit einer unterschiedlichen IP-Adresse.

auto lo
iface lo inet loopback
allow-hotplug eth0
iface eth0 inet static
  address 192.168.178.102
  broadcast 192.168.178.255
  gateway 192.168.178.1
  netmask 255.255.255.0
  network 192.168.178.0
  dns-nameservers 192.168.178.1
  dns-search 192.168.178.1


Manuelles Starten der virtuellen Maschinen

Um die nachfolgende Automatisierung zu verstehen, muss man als Grundlage die Netzwerkverbindungen via Bridge erst einmal manuell aufbauen. Die vorangegangen Schritte der Netzwerkkonfiguration sind auf Wirt- und Gastsystem(en) abgeschlossen und nun muss zuerst mal das Netzwerk restartet werden.

# /etc/init.d/network stop
# /etc/init.d/network start

Ein ifconfig zeigt die neuen Geräte

$ sudo /sbin/ifconfig
bri0      Link encap:Ethernet  Hardware Adresse 00:01:80:78:82:35  
          inet Adresse:192.168.178.100  Bcast:192.168.178.255  Maske:255.255.255.0
          inet6-Adresse: fe80::201:80ff:fe78:8235/64 Gültigkeitsbereich:Verbindung
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metrik:1
          RX packets:106261 errors:0 dropped:0 overruns:0 frame:0
          TX packets:78679 errors:0 dropped:0 overruns:0 carrier:0
          Kollisionen:0 Sendewarteschlangenlänge:0 
          RX bytes:58928291 (56.1 MiB)  TX bytes:10451558 (9.9 MiB)

eth0      Link encap:Ethernet  Hardware Adresse 00:01:80:78:82:35  
          inet6-Adresse: fe80::201:80ff:fe78:8235/64 Gültigkeitsbereich:Verbindung
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metrik:1
          RX packets:125003 errors:0 dropped:0 overruns:0 frame:0
          TX packets:79224 errors:0 dropped:0 overruns:0 carrier:0
          Kollisionen:0 Sendewarteschlangenlänge:1000 
          RX bytes:67358102 (64.2 MiB)  TX bytes:10473746 (9.9 MiB)
          Interrupt:20 Speicher:fe9c0000-fe9e0000 

lo        Link encap:Lokale Schleife  
          inet Adresse:127.0.0.1  Maske:255.0.0.0
          inet6-Adresse: ::1/128 Gültigkeitsbereich:Maschine
          UP LOOPBACK RUNNING  MTU:16436  Metrik:1
          RX packets:1347 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1347 errors:0 dropped:0 overruns:0 carrier:0
          Kollisionen:0 Sendewarteschlangenlänge:0 
          RX bytes:89892 (87.7 KiB)  TX bytes:89892 (87.7 KiB)


Mit dem Kommando brctl kann man sich den Zustand der Software-Brigde anzeigen lassen. Das Netzwerkdevice eth0 ist virtuell schon an die Bridge angeschlossen:

$ sudo /usr/sbin/brctl show
bridge name     bridge id               STP enabled     interfaces
bri0            8000.000180788235       no              eth0


Nun muss man die TAP-Devices noch an die Bridge binden, damit die Gäste auf das gemeinsame Netzwerk zugreifen können. Mit dem Kommando tunctl erzeugen wir TAP-Device das vom User "michael" (Mitglied der Gruppe kvm) genutzt werden kann.

$ sudo /usr/sbin/tunctl -b -u michael -g kvm
tap0


Die Vorbereitungen sind soweit abgeschlossen und nun kann man mit dem Kommando kvm den virtuellen PC starten. Im nachfolgenden Beispiel wir von einer bestehenden siduction Installtion mit dem Imagenamen siduction-virtpc01.img ausgegangen. Des weiteren wird die MAC-Adresse der 12:A1:00:12:34:02 (Parameter macaddr) für die eindeutige Identifikation im Netzwerk benutzt. Das soeben erzeugte TAP-Interface tap0 wird per Parameter ifname übergeben. Der virtuelle Netzwerkkartentyp wird mit der Option model definiert (hier: virtio).

Den nachfolgenden kvm-Befehl als User auf der Kommandozeile absetzen und warten bis die VM hochgefahren ist. Am virtuellen System anmelden und eine Konsole starten. Als root einloggen und das Kommando ifconfig absetzen.

$ kvm -net nic,vlan=0,macaddr=12:A1:00:12:34:02,model=virtio -net tap,vlan=0,ifname=tap0 -usb -usbdevice tablet -hda ./siduction-virtpc01.img -m 1024

Am virtuellen System anmelden und eine Konsole starten. Als root einloggen und das Kommando ifconfig absetzen. eth0 hat die IP-Adresse 192.168.178.101, kann also im Netzwerk 192.168.178.0 eine Verbindungen zu anderen Gästen oder dem Wirt aufbauen.

eth0      Link encap:Ethernet  Hardware Adresse 12:a1:00:12:34:02  
          inet Adresse:192.168.178.101  Bcast:192.168.178.255  Maske:255.255.255.0
          inet6-Adresse: fe80::10a1:ff:fe12:3402/64 Gültigkeitsbereich:Verbindung
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metrik:1
          RX packets:222 errors:0 dropped:0 overruns:0 frame:0
          TX packets:77 errors:0 dropped:0 overruns:0 carrier:0
          Kollisionen:0 Sendewarteschlangenlänge:1000 
          RX bytes:31106 (30.3 KiB)  TX bytes:6162 (6.0 KiB)

lo        Link encap:Lokale Schleife  
          inet Adresse:127.0.0.1  Maske:255.0.0.0
          inet6-Adresse: ::1/128 Gültigkeitsbereich:Maschine
          UP LOOPBACK RUNNING  MTU:16436  Metrik:1
          RX packets:64 errors:0 dropped:0 overruns:0 frame:0
          TX packets:64 errors:0 dropped:0 overruns:0 carrier:0
          Kollisionen:0 Sendewarteschlangenlänge:0 
          RX bytes:3240 (3.1 KiB)  TX bytes:3240 (3.1 KiB)


Ebenso wird mit dem zweiten virtuellen Gast verfahren. Hier benutzt man das nächste frei TAP-Device tap1.

$ sudo /usr/sbin/tunctl -b -u michael -g kvm
tap1

Der zweite virtuelle Gast wird gestartet mit MAC-Adresse 12:A1:00:12:34:03, TAP-Device tap1 und dem vorhandenen Imagenamen siduction-virtpc02.img. Alle anderen Parameter sind identisch zur ersten VM.

$ kvm -net nic,vlan=0,macaddr=12:A1:00:12:34:03,model=virtio -net tap,vlan=0,ifname=tap1 -usb -usbdevice tablet -hda ./siduction-virtpc02.img -m 1024

Die zweite virtuelle Maschine hat die IP-Adresse 192.168.178.102 und ist von allen beteilgten Stationen im Netzwerk erreichbar. In einer Konsole am Wirtsystem sieht man mit dem Kommando brctl, dass beide TAP-Devices und das Netzwerkdevice eth0 des Wirtes an der Brücke angeschlossen sind.

# brctl show
bridge name     bridge id               STP enabled     interfaces
bri0            8000.000180788235       no              eth0
                                                        tap0
                                                        tap1


Nun können wir beide VM's wieder herunterfahren. Zum Löschen der nicht mehr benötigten TAP-Devies setzen wir folgende Befehle in der Konsole ab.

$ sudo /sbin/ifconfig tap0 down
$ /usr/sbin/tunctl -d tap0
$ sudo /sbin/ifconfig tap1 down
$ /usr/sbin/tunctl -d tap1

Automatisiertes Starten der virtuellen Maschinen

Mit einem Shellscript vm.sh kann man sich das Starten der virtuellen Maschinen erheblich vereinfachen. Bitte das unten aufgelistete Script bei der vorbelegten Variable $IMGPATH ggf. an eigene Bedürfnisse anpassen. Der Aufruf erfolgt mit zwei Parametern.

Syntax:

$ ./vm.sh <Image Filename> <Name des Gastes>

Besipiel:

$ ./vm.sh siduction.img virtpc01


Das Script erzeugt als User das TAP-Device und bindet es an die Brigde an. Es wird eine zufällige MAC-Adresse erstellt, die zum Starten der VM benutzt wird. Der angebende erste Parameter (bootbares Image) und der Instanzname (zweiter Parameter) werden beim Auruf des kvm Kommandos übergeben. Wenn die VM heruntergefahren wurde, wird das TAP-Device deaktiviert und gelöscht..


#!/bin/bash
#
IMGPATH="/mnt/vm"
IMGFILE=$1
VMNAME=$2
USERID=`whoami`
BRIGDE=`sudo /usr/sbin/brctl show | egrep ^bri[0-9]|awk '{print $1}'`
AUFRUFPARAM=$#
VLAN="0"
MACADRESSE="12:A1:00:12:"
MODEL="virtio"
INTERFACE=`sudo /usr/sbin/tunctl -b -u $USERID -g kvm`
BOOT="on"
MEDIA="disk"
USBDEVICE="tablet"
SOUNDHW="es1370"
RAMSIZE="1024"

# Funktionen
do_check_option()
{
   if [ $AUFRUFPARAM -ne 2 ]
      then
      echo ""
      echo "Achtung, falscher Aufruf des Sriptes $0"
      echo "Syntax:    $0 <Pfad zum Imagefile> <Name der VM>"
      echo "Beispiel:  $0 /mnt/vm/siduction.img virtpc01"
      echo ""
      exit 1
   fi
}

do_create_macadr()
{
for Z in `seq 1 2`
   do
   RND=`echo $((RANDOM % 15))`
   MAC=`echo $RND | awk -v RND="$RND" '{printf("%02d\n",$1)}'`
   if [ $Z -le 1 ]
      then
      TMP=`echo -n $MAC`
      MACADRESSE=`echo $MACADRESSE$TMP":"`
   elif [ $Z -eq 2 ]
      then
      TMP=`echo -n $MAC`
      MACADRESSE=`echo $MACADRESSE$TMP`
      echo ""
   fi
done
}

do_param_output()
{
   echo "Starte virtuelle KVM/Qemu Maschine mit folgenden Parametern:"
   echo " VM Name     --> "$VMNAME
   echo " Imagedatei  --> "$IMGPATH/$IMGFILE
   echo " NIC Modell  --> "$MODEL
   echo " MAC-Adresse --> "$MACADRESSE
   echo " Brigde Name --> "$BRIGDE
   echo " TAP-Device  --> "$INTERFACE
   echo " VLAN-Nr.    --> "$VLAN
   echo " USB-Device  --> "$USBDEVICE
   echo " Sound-HW    --> "$SOUNDHW
   echo " RAM Groesse --> "$RAMSIZE
}

do_start_vm()
{
   # Nachfolgende zwei Codezeilen wurden zur besseren Übersicht in zwei Hälften geteilt.
   # Bitte Backslash "\" entfernen und beiden Zeile in einer zusammenfassen.
   kvm -name $VMNAME -net nic,vlan=$VLAN,macaddr=$MACADRESSE,model=$MODEL -net tap,vlan=$VLAN,ifname=$INTERFACE -drive \ 
   if=$MODEL,boot=$BOOT,file=$IMGPATH/$IMGFILE,media=$MEDIA -usb -usbdevice $USBDEVICE -soundhw $SOUNDHW -m $RAMSIZE
}

do_stop_vm()
{
   sudo /sbin/ifconfig $INTERFACE down
   sudo /usr/sbin/tunctl -d $INTERFACE
}


# Hauptprogramm
do_check_option $AUFRUFPARAM
do_create_macadr
do_param_output
do_start_vm
do_stop_vm
#EOF

Fehlerbehebung

Unter Umständen könnten Nebeneffekte auftreten, z.B. bei dem Systemmonitor conky, wenn dort das Netzwerkinterface eth0 überwacht wird. Es muß dann auf das Device bri0 umkonfiguriert werden. Bei der Netzwerkkonfiguration mit den virtuellen Gästen ist die virtuelle Brücke bri0 das "übergeordnete" Netzwerkinterface.


Testen der Netzwerkverbindungen

  • Erste VM hochfahren
  • Zweite VM hochfahren
  • SSH-Verbindung von erster VM auf Hostsystem testen
virtpc01-$ ssh 192.168.178.100
  • SSH-Verbindung von zweiter VM auf Hostsystem testen
virtpc02-$ ssh 192.168.178.100
  • SSH-Verbindung von erster auf zweiter VM testen
virtpc01-$ ssh 192.168.178.102
  • SSH-Verbindung von zweiter auf erste VM testen
virtpc02-$ ssh 192.168.178.101
  • SSH-Verbindung vom Wirt auf die beiden VM's testen
hostpc-$ ssh 192.168.178.101
hostpc-$ ssh 192.168.178.102

Wenn diese Test alle erfolgreich abgeschlossen werden konnten, hat man sein virtuelles Netzwerk komplett eingerichtet.

Weiterführende Informationen

Das Online Buch zu qemu-kvm & libvirt

Qemu-Buch: Virtuelle Netzwerke konfigurieren

Qemu-Buch: Startoptionen von QEMU und KVM


Mein Dank an towo für die Bereitstellung seiner KVM-Startscripte und die Hilfe im IRC #frickelplatz.