KVM

Die in Linux integrierte Virtualisierungslösung heisst KVM (Kernel-based Virtual Machine) und ist seit Version 2.6.20 Bestandteil des Linux-Kernels. KVM ist formal ein Hypervisor vom Typ 2, was bedeutet, dass das Hostsystem (die Maschine, die die virtuellen Maschinen ausführt) im multi-user.target läuft - also selbst ein vollwertiges Linux-Betriebssystem benötigt, um „seine“ Gast-Systeme virtuell ausführen zu können. Es gibt allerdings auch Stimmen, die KVM als Typ 1 klassifizieren.

QEMU (= Quick Emulator) ist ein Hardware-Emulator: es simuliert die komplette Hardware eines Computers in Software und kommt ohne Hardware-Unterstützung aus. Diese Vollvirtualisierung ist entwicklungsintensiv und nicht sonderlich performant.

Das SPICE-Projekt ist eine Open-Source-Lösung für den nahtlosen Fernzugriff auf virtuelle Maschinen.

KVM nutzt vorhandene Hardware, bei welcher es Virtualisierungsunterstützung voraussetzt. Bei dieser „Paravirtualisierung“ (also Virtualisierung, die durch Hardware unterstützt wird) weiss das Gastsystem, dass es in einer virtuellen Umgebung läuft. Es kommuniziert mit speziellen Treibern direkt mit der Hardware des Hostsystems. Die Paravirtualisierung unter KVM nennt sich „VirtIO“. Alternativ nutzt KVM die von QEMU emulierte Hardware.

Ob KVM durch die Hardware unterstützt wird, ermittelt man über die CPU-Eigenschaften. Hardwareseitig wird ein Intel-Prozessor mit Intel VT-x und Intel 64 extensions (im Falle von 64 bit Gastsystemen) oder eine AMD-CPU mit den AMD-V und AMD64 extensions (auch hier, falls man 64 bittige Gast-Betriebssysteme ausführen möchte) benötigt. Das lässt sich auf dem Bare Metal Hypervisor wie folgt kontrollieren:

cat /proc/cpuinfo | grep -E "vmx|svm"

Für erweiterte KVM-Installationen sollte das „No eXecute“-Feature eingeschaltet sein:

cat /proc/cpuinfo | grep -E "nx"

Ein anderer Weg, um die Hardware auf ihre Tauglichkeit hin zu prüfen:

lsmod | grep kvm

Wird hier nichts oder nur „kvm“ statt „kvm“ plus „kvm_intel“ bzw. „kvm_amd“ angezeigt, kann man zwar virtuelle Maschinen installieren und ausführen - allerdings nur QEMU basierend, was einiges an Geduld im Umgang mit den VMs erfordert.

Tipp

Ein produktiver KVM-Host, der eine Reihe an Maschinen hostet, sollte mindestens 16 GB Swap-Space besitzen. Swap-Space wird intensiv verwendet, selbst wenn genügend RAM vorhanden ist.

Grafikkarten:

Karte

VGA compatible

vgabios Support

UEFI Support

Linux Driver

Windows Driver

Recommended On

ATI VGA

Bochs

Desktop + Server with UEFI

Cirrus VGA

QXL

Providing multihead support for windows guests.

Ramfb

Arm

Standard VGA

Desktop, Server

VirtIO GPU

Desktop, ARM

VirtIO VGA

Desktop

Storage:

  • Wer Gluster verwendet, gibt als Storage-Pfad gluster://gluster-host/path/to/vm.qcow2 an.

Tipp

In Zusammenhang mit einer VM ist der Begriff „CPU Steal“ interessant: Wird eine CPU Steal-Auslastung angezeigt, wartet die CPU der VM auf die CPU des Hypervisors. Der Hypervisor kann also die VM nicht bedienen - oft besitzt die VM in einem solchen Fall (fast) genau so viele virtuelle CPUs bzw. Cores wie der physische Hypervisor, lastet diese voll aus und häte gerne noch mehr Ressourcen, oder der Hypervisor ist mit sich selbst oder anderen VMs beschäftigt. Ab 10% CPU Steal (über alle Cores) sollte man anfangen, das Phänomen zu beobachten; eine Warnung ist ab 15% angebracht, kritisch wird es ab 20%.

Links:

KVM installieren - Basics

Ein reiner KVM-Host kommt mit einer Minimal-Installation ohne grafischen Desktop aus, es wird nur das „Virtualization Host“-Package benötigt, welches den Hypervisor sowie die Management-Tools enthält. Wenn es fehlt, installiert man es mit

# RHEL
dnf -y groupinstall "Virtualization Host"

# Fedora
dnf -y install @virtualization
systemctl enable --now libvirtd

Damit wird ein System mindestens zum QEMU- oder - besser - zum KVM/QEMU-Hypervisor, je nach eingesetzter Hardware. Grafisch lässt sich der KVM-Host z.B. entfernt von einer Fedora-Workstation mit VMM managen.

Auch für Windows existiert ein Client, siehe https://virt-manager.org/download/.

Wer seine VMs im UEFI-Mode booten möchte, benötigt noch das OVMF-Paket, welches eine 64-bit UEFI-Firmware für KVM und QEMU enthält:

dnf -y install OVMF

Ist der Host ausschliesslich für die Ausführung von virtuellen Hosts da, kann man folgende Tuning-Anpassung vornehmen:

tuned-adm active
tuned-adm profile virtual-host

KVM installieren - Advanced

Der KVM-Host soll als Router für seine Guests agieren? Wer Gastsysteme betreiben möchte, die logisch gesehen am Netzwerk-Anschluss des KVM-Hosts hängen sollen, muss auf dem KVM-Host eine Bridge auf Basis einer oder mehrerer physischer Netzwerkkarten einrichten, damit der Gast vom Host aus kommunizieren kann. Anschliessend lässt sich im VMM unter „Virtual Networks“ ein Netzwerk auf Basis dieser Bridge im Routed Mode hinzufügen und durch die Gastsysteme nutzen.

Der Trick dann: im VMM kein „Virtual Network“ anlegen - das braucht es nicht, schliesslich sollen die VMs direkt über die Host-Bridge kommunizieren.

Also:

  • auf dem Host eine Bridge anlegen

  • kein „Virtual Network“ im VMM

  • VM erzeugen, IP-Adresse aus dem gebridgden Netz geben

Die Guests müssen NAT auf dem Host verwenden, um sich mit dem echten Netzwerk zu verbinden. Auf dem Host daher:

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.d/99-ipforward.conf
sysctl -p

In der physischen Netzwerkkarte des Hosts alle IP-Eigenschaften deaktivieren, und die Bridge-Angabe hinzufügen. Beispiel:

/etc/sysconfig/network-scripts/ifcfg-eno16777736
#DNS1="192.168.202.2"
#GATEWAY="192.168.202.2"
#IPADDR="192.168.202.111"
#NETMASK="255.255.255.0"
BRIDGE=virbr0
DEVICE="eno16777736"
HWADDR="00:0c:29:32:d0:4c"
ONBOOT=yes

Bridge erstellen:

/etc/sysconfig/network-scripts/ifcfg-virbr0
BOOTPROTO=static
DEVICE=virbr0
DNS1=192.168.202.2
GATEWAY=192.168.202.2
IPADDR=192.168.202.111
NETMASK=255.255.255.0
ONBOOT=yes
TYPE=BRIDGE

Reboot.

VMM

Virtuelle Maschinen administriert man am bequemsten grafisch - mit dem „Virtual Machine Manager“ (VMM). Dieser muss nicht zwangsläufig auf dem Hypervisor installiert werden; man kann ihn auch lokal installieren und sich zur Administration mit dem KVM-Hypervisor verbinden:

dnf -y install virt-manager

virsh Cheat Sheet

Das Kommandozeilen-Tool virsh verwaltet VMs und den KVM-Hypervisor. Wird es ohne Parameter aufgerufen, öffnet sich die interaktive virsh-Shell. Mit „Domain“ ist der Name einer virtuellen Maschine gemeint. So wird es installiert:

dnf -y install libvirt-client

virsh COMMAND DOMAIN-ID [OPTIONS]

virsh help
virsh help restore

virsh capabilities
virsh list --all

virsh autostart my_vm
virsh start my_vm
virsh suspend my_vm
virsh resume my_vm
virsh reboot my_vm
virsh shutdown my_vm

virsh edit my_vm
virsh destroy my_vm

virsh blkiotune my_vm
virsh memtune my_vm --hard-limit 1g
virsh setmem my_vm 2048m
virsh schedinfo my_vm cpu_shares=100
virsh vcpupin my_vm 0 1,3

virsh net-list --all
virsh net-define ./bridge.xml
virsh net-start br0
virsh net-autostart br0

# get all IP addresses
# assuming, "default" is the name of the network
virsh -r net-dhcp-leases default

virsh pool-define /tmp/gluster-storage.xml
virsh pool-start glusterfs-pool
virsh pool-list --all

# get the storage path of the pool named "default"
virsh pool-dumpxml default | grep -i path

virsh vol-list glusterfs-pool

virsh create my_vm.xml
virsh define my_vm.xml
virsh dumpxml my_vm > my_vm.xml
virsh save my_vm my_vm.xml
virsh restore my_vm.xml

virsh domdisplay --domain my_vm
# with Remote-viewer installed
remote-viewer $OUTPUTOFPREVIOUSCOMMAND

Die Auslastung des Hypervisors ermittelt man mit dnf -y install virt-top && virt-top.

VM auf der Commandline installieren

dnf -y install virt-install

# adapt these to your needs:
export ISO_FILE='http://download.rockylinux.org/pub/rocky/8/isos/x86_64/Rocky-x86_64-dvd.iso'
export KICKSTART_FILE='https://raw.githubusercontent.com/Linuxfabrik/kickstart/main/lf-rhel.cfg'
export OS_VARIANT='rhel8.0'                 # rhel9.3, centos8, centos7.0 etc.
export BOOT=''                              # bios boot; 'uefi' for UEFI; other see `man virt-install`

# mostly no need to adapt:
export VCPUS=2
export MEM_SIZE=4096
export DISK_MODEL=virtio                    # or sata, scsi, ide, ...
export DISK_SIZE=50
export NETWORK_BRIDGE=virbr0
export NETWORK_MODEL=virtio

#wget $ISO_FILE
export VIRT_INSTALL="sudo virt-install \
    --console pty,target_type=virtio \
    --cpu host-passthrough \
    --disk 'size=${DISK_SIZE},bus=${DISK_MODEL}' \
    --graphics none \
    --location $(basename ${ISO_FILE}) \
    --memory ${MEM_SIZE} \
    --name ${OS_VARIANT}-${LF_TYPE} \
    --network 'bridge=${NETWORK_BRIDGE},model=${NETWORK_MODEL}' \
    --os-variant ${OS_VARIANT} \
    --sound none \
    --vcpus ${VCPUS} \
    --extra-args 'inst.ks=${KICKSTART_FILE}'"
if [ -n $BOOT ]; then
    export VIRT_INSTALL="$VIRT_INSTALL --boot ${BOOT}"
fi
echo $VIRT_INSTALL
$VIRT_INSTALL

Bemerkung

Wird UEFI verwendet, können von einer VM - ob sie läuft oder nicht - keine Snapshots erstellt werden (Error creating snapshot: Operation not supported: internal snapshots of a VM with pflash based firmware are not supported).

VM-Disk vergrössern

Der Befehl kann nur ausgeführt werden, wenn keine Snapshots der VMs vorhanden sind. Ob Snapshots vorhanden sind, kann im Terminal wie folgt festgestellt werden:

virsh snapshot-list $DOMAIN

# delete a snapshot
virsh snapshot-delete --domain $DOMAIN --snapshotname <Name-des-Snapshots>

Virtuelle Disk um 20 GB erweitern:

qemu-img resize -f raw /path/to/image.raw +20G

Ablage ISO-Images

ISO-Images für die zu installierenden Gast-Betriebssysteme kann man erst einmal hier ablegen:

cd /var/lib/libvirt/images
wget http://mirror.switch.ch/ftp/mirror/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1503-01.iso

KVM/VirtIO Guest Tools für Windows

Die aktuellsten VirtIO-Driver für Windows können hier im ISO- und RPM-Format bezogen werden: https://github.com/virtio-win/virtio-win-pkg-scripts/blob/master/README.md. Mehr Informationen finden sich hier https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html.

Unter RHEL8, der als KVM-Hypervisor dient, können diese direkt per dnf -y install virtio-win und später von /usr/share/virtio-win/virtio-win.iso installiert werden.

Und so installiert man eine Windows-VM in KVM (mit VMM):

  • VM erzeugen - darauf achten, dass Disks und Netzwerkkarten auf Typ „VirtIO“ stehen.

  • Von der Windows-ISO booten.

  • Windows kann während des Setups die Disk nicht erkennen. Im VMM im CD-ROM die /usr/share/virtio-win/virtio-win.iso einlegen und im Windows-Setup auf „Load Driver“ klicken.

  • Nach der Auswahl der Storage-Treiber im VMM wieder auf das Windows-ISO wechseln und Windows-Setup fortführen.

Sobald Windows installiert ist, kann man später im Geräte-Manager die Treiber für den Netzwerk-Anschluss nachinstallieren (auch von dem oben angebenenen VirtIO ISO-File).

OVA-Appliance in KVM importieren

Das OVA-Format ist nichts anderes als ein tar-Archiv, welches die VM-Konfiguration in Form einer Open Virtualization Format-Datei (.ovf) und deren Festplatten als Virtual Machine Disk-Dateien (.vmdk) enthält. Es lässt sich nicht direkt in KVM importieren, daher geht man wie folgt vor:

tar xvf appliance.ova
rm -f appliance.ova

Schauen, welche Disk-Formate unterstützt werden:

qemu-img -h | tail -n1

Umwandeln der vmdk-Dateien in das qcow2-Format, die in der Regel damit grösser werden:

qemu-img convert -O qcow2 appliance-disk1.vmdk appliance-disk1.qcow2
rm -f appliance-disk1.vmdk

Nach der Konvertierung der Disk(s) erzeugt man mit den Vorgaben aus der OVF-Datei manuell eine neue VM und hängt die erzeugte(n) .vmdk-Datei(en) ein.

Image-Datei verkleinern/shrinken (ohne Kompression):

qemu-img convert -O qcow2 image.qcow2 shrinked-image.qcow2

Nested Virtualization

Vorher prüfen:

  • Das Betriebssystem muss Nested Virtualization unterstützen: cat /sys/module/kvm_intel/parameters/nested (# => N = No, Y = Yes)

  • Kann die VM Virtualisierung bieten? In der VM: cat /proc/cpuinfo \| grep -E "vmx|svm"

So wird es auf Intel aktiviert:

  • Alle VMs herunterfahren.

  • Unload kvm_probe module: modprobe -r kvm_intel

  • Nesting-Feature zur Laufzeit aktivieren: modprobe kvm_intel nested=1

  • Dauerhaft einrichten: echo "options kvm_intel nested=1" >> /etc/modprobe.d/kvm.conf

  • CPU-Passthrough einrichten: Im KVM in der VM bei der CPU von Hand „host-passthrough“ eintippen.

Siehe auch https://fedoraproject.org/wiki/How_to_enable_nested_virtualization_in_KVM

Shutdown KVM

Wird der KVM-Host heruntergefahren, werden die Gastsysteme in der Standardeinstellung „suspended“. Sollen die Gastsysteme runterfahren, wenn der Host runtergefahren wird, ist folgendes anzupassen:

dnf -y install libvirt-client
/etc/sysconfig/libvirt-guests
ON_SHUTDOWN=shutdown
SHUTDOWN_TIMEOUT=20
systemctl enable libvirt-guests

Service aktivieren, jedoch nie auf einem Host, der gerade VMs ausführt. Damit werden alle VMs heruntergefahren:

systemctl start libvirt-guests

Guestfish

Guest filesystem shell for editing virtual machine filesystems and disk images.

Mounten eines Images:

virt-ls --add /path/to/vm-disk.raw /
guestfish --ro --add /path/to/vm-disk.raw

# automatically mount the disks
guestfish --ro --inspector --add /path/to/vm-disk.raw

Kommandos in Guestfish: https://www.libguestfs.org/guestfish.1.html

run
list-filesystems
mount-ro /dev/vg_guest/lv_root /
mount-ro /dev/rl/var_tmp /var/tmp
...

Troubleshooting

qemu: could not open disk image …: Permission denied
chmod 0660 auf-das-diskimage

Built on 2024-11-18