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
- NAT (default) - VMs share host’s IP
- Bridge - VMs on same network as host
- Isolated - VMs can talk to each other only
- 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
- KVM Official: https://www.linux-kvm.org/
- libvirt Documentation: https://libvirt.org/docs.html
- QEMU Documentation: https://www.qemu.org/documentation/
- Red Hat Virtualization Guide: https://access.redhat.com/documentation/
- Ubuntu KVM Guide: https://help.ubuntu.com/community/KVM