← Back to all cheatsheets
Linux
kvmvirtualizationqemulibvirtvirshlinux

KVM Virtualization Cheat Sheet

Overview

KVM (Kernel-based Virtual Machine) is a full virtualization solution for Linux on x86 hardware containing virtualization extensions (Intel VT or AMD-V).

Components:

  • KVM: Kernel module providing virtualization infrastructure
  • QEMU: User-space emulator for hardware virtualization
  • libvirt: API and management tool for platform virtualization
  • virsh: Command-line interface for libvirt

Prerequisites & Installation

Check Hardware Support

# Check for virtualization support
egrep -c '(vmx|svm)' /proc/cpuinfo
# If output > 0, virtualization is supported

# Check if KVM modules are loaded
lsmod | grep kvm

# Detailed CPU info
lscpu | grep Virtualization

# Verify KVM acceleration
kvm-ok  # Ubuntu/Debian

Installation

Ubuntu/Debian:

sudo apt update
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager
sudo systemctl enable --now libvirtd
sudo usermod -aG libvirt $USER
sudo usermod -aG kvm $USER

RHEL/CentOS/Fedora:

sudo dnf install qemu-kvm libvirt virt-install virt-manager
sudo systemctl enable --now libvirtd
sudo usermod -aG libvirt $USER

Arch Linux:

sudo pacman -S qemu libvirt virt-manager dnsmasq bridge-utils
sudo systemctl enable --now libvirtd
sudo usermod -aG libvirt $USER

Verify Installation

# Check libvirt status
sudo systemctl status libvirtd

# Verify virsh connection
virsh list --all

# Check QEMU version
qemu-system-x86_64 --version

# List available networks
virsh net-list --all

VM Management with virsh

Creating Virtual Machines

Using virt-install:

# Basic VM creation
virt-install \
  --name vm1 \
  --ram 2048 \
  --vcpus 2 \
  --disk path=/var/lib/libvirt/images/vm1.qcow2,size=20 \
  --os-variant ubuntu20.04 \
  --network bridge=virbr0 \
  --graphics vnc,listen=0.0.0.0 \
  --cdrom /path/to/ubuntu-20.04.iso

# Unattended installation with kickstart
virt-install \
  --name centos-vm \
  --ram 4096 \
  --vcpus 4 \
  --disk path=/var/lib/libvirt/images/centos-vm.qcow2,size=40 \
  --os-variant centos8 \
  --network network=default \
  --location /path/to/centos.iso \
  --initrd-inject=/path/to/ks.cfg \
  --extra-args "ks=file:/ks.cfg console=tty0 console=ttyS0,115200n8"

# VM from existing disk
virt-install \
  --name vm-from-disk \
  --ram 2048 \
  --vcpus 2 \
  --disk /var/lib/libvirt/images/existing.qcow2 \
  --import \
  --os-variant ubuntu20.04 \
  --network network=default

VM Lifecycle Management

# List VMs
virsh list                    # Running VMs
virsh list --all              # All VMs
virsh list --inactive         # Stopped VMs

# Start/Stop VMs
virsh start vm1
virsh shutdown vm1            # Graceful shutdown
virsh destroy vm1             # Force stop
virsh reboot vm1

# Autostart VMs
virsh autostart vm1           # Enable autostart
virsh autostart --disable vm1 # Disable autostart

# Suspend/Resume
virsh suspend vm1
virsh resume vm1

# Save/Restore state
virsh save vm1 /path/to/vm1.state
virsh restore /path/to/vm1.state

# Delete VM
virsh undefine vm1
virsh undefine vm1 --remove-all-storage  # Delete VM and disks

VM Information

# VM details
virsh dominfo vm1
virsh domstats vm1

# CPU info
virsh vcpuinfo vm1
virsh vcpucount vm1

# Memory info
virsh dommemstat vm1

# Disk info
virsh domblklist vm1
virsh domblkinfo vm1 vda

# Network info
virsh domiflist vm1
virsh domifstat vm1 vnet0

# Full XML configuration
virsh dumpxml vm1
virsh dumpxml vm1 > vm1-backup.xml

VM Configuration

# Edit VM configuration
virsh edit vm1

# Set memory
virsh setmem vm1 4G --config
virsh setmaxmem vm1 8G --config

# Set CPUs
virsh setvcpus vm1 4 --config --maximum
virsh setvcpus vm1 2 --config

# Change boot order
virsh edit vm1  # Modify <boot order='1'/> in XML

# Attach/Detach devices (see sections below)

Disk Management

Creating Disks

# Create qcow2 disk
qemu-img create -f qcow2 /var/lib/libvirt/images/disk1.qcow2 20G

# Create with backing file (snapshot/clone)
qemu-img create -f qcow2 -b /path/to/base.qcow2 /path/to/snapshot.qcow2

# Create raw disk
qemu-img create -f raw /var/lib/libvirt/images/disk1.raw 20G

# Pre-allocate space (better performance)
qemu-img create -f qcow2 -o preallocation=metadata disk1.qcow2 20G

Disk Operations

# Disk information
qemu-img info /var/lib/libvirt/images/disk1.qcow2

# Convert disk formats
qemu-img convert -f qcow2 -O raw source.qcow2 destination.raw
qemu-img convert -f raw -O qcow2 source.raw destination.qcow2

# Resize disk
qemu-img resize disk1.qcow2 +10G
virsh blockresize vm1 vda 30G --config

# Compress qcow2 image
qemu-img convert -O qcow2 -c source.qcow2 compressed.qcow2

# Check and repair disk
qemu-img check disk1.qcow2
qemu-img check -r all disk1.qcow2

Attach/Detach Disks

# Attach disk (temporary)
virsh attach-disk vm1 /path/to/disk.qcow2 vdb --cache none

# Attach disk (persistent)
virsh attach-disk vm1 /path/to/disk.qcow2 vdb --config --persistent

# Detach disk
virsh detach-disk vm1 vdb

# Attach ISO/CD-ROM
virsh attach-disk vm1 /path/to/cdrom.iso hdc --type cdrom --mode readonly

# Change CD-ROM media
virsh change-media vm1 hdc /path/to/new.iso --insert
virsh change-media vm1 hdc --eject

Storage Pools

# List storage pools
virsh pool-list --all

# Create directory-based pool
virsh pool-define-as mypool dir --target /var/lib/libvirt/images/mypool
virsh pool-build mypool
virsh pool-start mypool
virsh pool-autostart mypool

# Pool information
virsh pool-info mypool
virsh vol-list mypool

# Create volume in pool
virsh vol-create-as mypool vol1.qcow2 10G --format qcow2

# Delete pool
virsh pool-destroy mypool
virsh pool-undefine mypool

Networking

Network Types

  1. NAT (default) - VMs share host’s IP
  2. Bridge - VMs on same network as host
  3. Isolated - VMs can talk to each other only
  4. Routed - VMs routed through host

Virtual Networks

# List networks
virsh net-list --all

# Default network info
virsh net-info default
virsh net-dumpxml default

# Start/Stop network
virsh net-start default
virsh net-destroy default
virsh net-autostart default

# Create NAT network
cat > nat-network.xml << EOF
<network>
  <name>nat-network</name>
  <forward mode='nat'/>
  <bridge name='virbr1' stp='on' delay='0'/>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.100.2' end='192.168.100.254'/>
    </dhcp>
  </ip>
</network>
EOF

virsh net-define nat-network.xml
virsh net-start nat-network
virsh net-autostart nat-network

# Delete network
virsh net-destroy nat-network
virsh net-undefine nat-network

Bridge Networking

# Create bridge interface
sudo nmcli connection add type bridge ifname br0
sudo nmcli connection add type ethernet slave-type bridge con-name br0-eth0 ifname eth0 master br0
sudo nmcli connection up br0

# Alternative: Using netplan (Ubuntu)
cat > /etc/netplan/01-bridge.yaml << EOF
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: no
  bridges:
    br0:
      interfaces: [eth0]
      dhcp4: yes
EOF
sudo netplan apply

# Create bridge network in libvirt
cat > bridge-network.xml << EOF
<network>
  <name>host-bridge</name>
  <forward mode="bridge"/>
  <bridge name="br0"/>
</network>
EOF

virsh net-define bridge-network.xml
virsh net-start host-bridge
virsh net-autostart host-bridge

Network Interface Management

# List VM interfaces
virsh domiflist vm1

# Attach network interface
virsh attach-interface vm1 bridge br0 --model virtio --config

# Detach network interface
virsh detach-interface vm1 bridge --mac 52:54:00:xx:xx:xx

# Get IP address
virsh domifaddr vm1

# Set bandwidth limit
virsh domiftune vm1 vnet0 --inbound 100,200,300 --outbound 100,200,300

Snapshots

Snapshot Management

# Create snapshot
virsh snapshot-create-as vm1 snapshot1 "Description"

# Create external snapshot (doesn't pause VM)
virsh snapshot-create-as vm1 snapshot1 --disk-only --atomic

# List snapshots
virsh snapshot-list vm1
virsh snapshot-list vm1 --tree

# Snapshot info
virsh snapshot-info vm1 snapshot1
virsh snapshot-dumpxml vm1 snapshot1

# Revert to snapshot
virsh snapshot-revert vm1 snapshot1

# Delete snapshot
virsh snapshot-delete vm1 snapshot1

# Current snapshot
virsh snapshot-current vm1

Cloning

# Clone VM
virt-clone --original vm1 --name vm1-clone --auto-clone

# Clone with specific disk
virt-clone --original vm1 --name vm1-clone \
  --file /var/lib/libvirt/images/vm1-clone.qcow2

Console Access

Connection Methods

# Serial console (text mode)
virsh console vm1

# VNC console
virsh vncdisplay vm1
vncviewer :0  # Connect to display :0

# SPICE console
remote-viewer spice://localhost:5900

# virt-viewer (GUI)
virt-viewer vm1

# SSH into VM
ssh user@$(virsh domifaddr vm1 | awk 'NR==3 {print $4}' | cut -d/ -f1)

Performance Tuning

CPU Configuration

# CPU topology (edit VM XML)
virsh edit vm1
<vcpu placement='static'>4</vcpu>
<cpu mode='host-passthrough'>
  <topology sockets='1' cores='4' threads='1'/>
</cpu>

Memory Optimization

<!-- Huge pages -->
<memoryBacking>
  <hugepages/>
</memoryBacking>

<!-- Ballooning -->
<devices>
  <memballoon model='virtio'/>
</devices>

<!-- Memory tuning -->
<numatune>
  <memory mode='strict' nodeset='0-1'/>
</numatune>

Disk I/O Tuning

# Set I/O throttling
virsh blkdeviotune vm1 vda --total-iops-sec 1000

# Disk cache modes
# none - No cache (best for safety)
# writethrough - Write cache, read-through
# writeback - Write-back cache (best performance, less safe)
# directsync - Direct I/O, no cache

# Edit disk in VM XML
virsh edit vm1
<disk type='file' device='disk'>
  <driver name='qemu' type='qcow2' cache='none' io='native'/>
  <source file='/var/lib/libvirt/images/vm1.qcow2'/>
  <target dev='vda' bus='virtio'/>
</disk>

Network Performance

<!-- Virtio with multiqueue -->
<interface type='network'>
  <source network='default'/>
  <model type='virtio'/>
  <driver name='vhost' queues='4'/>
</interface>

CPU Pinning

# Pin vCPUs to specific pCPUs
virsh vcpupin vm1 0 0
virsh vcpupin vm1 1 1
virsh vcpupin vm1 2 2
virsh vcpupin vm1 3 3

# View pinning
virsh vcpupin vm1

Live Migration

Migrate Between Hosts

# Prerequisites: Shared storage or storage migration

# Basic live migration
virsh migrate --live vm1 qemu+ssh://destination-host/system

# With storage migration
virsh migrate --live --copy-storage-all vm1 qemu+ssh://destination-host/system

# Persistent migration (re-define on destination)
virsh migrate --live --persistent vm1 qemu+ssh://destination-host/system

# Offline migration
virsh migrate vm1 qemu+ssh://destination-host/system

Monitoring

Resource Monitoring

# CPU usage
virsh cpu-stats vm1

# Memory stats
virsh dommemstat vm1

# Block device stats
virsh domblkstat vm1 vda

# Network stats
virsh domifstat vm1 vnet0

# Continuous monitoring
watch -n 1 'virsh domstats vm1'

# With virt-top
virt-top

Logging

# libvirt logs
sudo tail -f /var/log/libvirt/libvirtd.log
sudo tail -f /var/log/libvirt/qemu/vm1.log

# Enable debug logging
sudo virsh log --level 1 --outputs "1:file:/var/log/libvirt/debug.log"

Troubleshooting

Common Issues

# VM won't start
virsh start vm1 --console
sudo journalctl -u libvirtd -f

# Check for errors in VM XML
virsh dumpxml vm1 | xmllint --format -

# Verify disk accessibility
qemu-img check /var/lib/libvirt/images/vm1.qcow2

# Network issues
virsh net-list --all
sudo iptables -L -n -v | grep virbr
sudo firewall-cmd --list-all

# Permission issues
ls -la /var/lib/libvirt/images/
sudo chown -R libvirt-qemu:kvm /var/lib/libvirt/images/

Reset/Recover VM

# Force reset VM
virsh reset vm1

# Restore from XML
virsh define /path/to/vm1.xml

# Rebuild VM from disk
virt-install --name vm1-recovered \
  --disk /var/lib/libvirt/images/vm1.qcow2 \
  --import --ram 2048 --vcpus 2 --os-variant ubuntu20.04

Backup & Restore

Backup Strategies

# Backup VM XML definition
virsh dumpxml vm1 > vm1-$(date +%Y%m%d).xml

# Backup with external snapshot
virsh snapshot-create-as vm1 backup-$(date +%Y%m%d) --disk-only --atomic
# Backup the original disk (now frozen)
cp /var/lib/libvirt/images/vm1.qcow2 /backup/
# Merge snapshot back
virsh blockcommit vm1 vda --active --pivot

# Full VM backup script
#!/bin/bash
VM="vm1"
BACKUP_DIR="/backup/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

# Dump XML
virsh dumpxml $VM > $BACKUP_DIR/$VM.xml

# Create snapshot
virsh snapshot-create-as $VM backup --disk-only --atomic

# Copy disk
cp /var/lib/libvirt/images/$VM.qcow2 $BACKUP_DIR/

# Merge snapshot
virsh blockcommit $VM vda --active --pivot

Restore

# Restore VM
virsh define vm1-backup.xml
cp vm1-backup.qcow2 /var/lib/libvirt/images/vm1.qcow2
virsh start vm1

Best Practices

Security

# Use virtio-rng for entropy
virsh edit vm1
<devices>
  <rng model='virtio'>
    <backend model='random'>/dev/urandom</backend>
  </rng>
</devices>
# Secure VNC with password
virsh edit vm1
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='your-password'/>

Resource Management

  • Use virtio drivers for best performance
  • Enable huge pages for memory-intensive workloads
  • Pin vCPUs to physical CPUs for consistent performance
  • Use thin provisioning (qcow2) to save disk space
  • Regular snapshots for quick recovery
  • Monitor resource usage with virt-top

Naming Conventions

  • Use descriptive VM names: prod-web-01, dev-db-01
  • Tag VMs in XML with metadata
  • Organize storage pools by purpose
  • Document network configurations

Quick Reference

Essential Commands

# VM lifecycle
virsh list --all
virsh start <vm>
virsh shutdown <vm>
virsh destroy <vm>
virsh reboot <vm>

# VM info
virsh dominfo <vm>
virsh dumpxml <vm>
virsh console <vm>

# Storage
virsh pool-list
virsh vol-list <pool>
qemu-img info <disk>

# Network
virsh net-list
virsh domifaddr <vm>

# Snapshots
virsh snapshot-list <vm>
virsh snapshot-create-as <vm> <name>
virsh snapshot-revert <vm> <name>

Resources