Skip to content

QEMU-KVM

KVM QEMU virtio(para virtualization)

KVM/QEMU KVM/virtio (para virtualization)

Intel VT-x AMD AMD-V

three mode - user - kernel - guest

libvirt

# default image dir
/var/lib/libvirt/images

# log
/var/log/libvirt/qemu/Window11-clone1.log

# QEMU driver configuration file
/etc/libvirt/qemu.conf

# config xml
/etc/libvirt/qemu/

# Runtime configurations and snapshots
/var/lib/libvirt/qemu/

# default OVMF_VARS for EFI Variables
/var/lib/libvirt/qemu/nvram/

EDITOR=vim virsh edit Window11-clone1

# Restart services
sudo systemctl restart libvirtd
sudo systemctl restart qemu-kvm

journalctl -u libvirtd

# check what firmware files QEMU can find
/usr/local/bin/qemu-system-x86_64 -L help

# Check libvirt daemon version
libvirtd --version

# Or check client library version
virsh version

# Verify new version
qemu-system-x86_64 --version
virsh list --all
EDITOR=vim virsh edit Window11-clone1
qemu-img info windows11.qcow2
# displays the IP addresses and MAC addresses of network interfaces inside a running KVM/QEMU virtual machine (domain)
virsh domifaddr rocky9-1 --source agent


virsh domblklist rocky9-1
#  Target   Source
# -----------------------------------------------------------------
#  vda      /var/lib/libvirt/images/rocky9-1.img
#  sda      /var/lib/libvirt/boot/virtinst-b2trnlhb-cloudinit.iso
virsh change-media rocky9-1 sda --eject
virsh change-media rocky9-1 sda --eject --config

virsh detach-disk rocky9-1 sda 
virsh detach-disk rocky9-1 sda --config

# Replace "my-vm" with your actual VM name
virsh destroy my-vm --graceful    # if running
virsh undefine rocky9-1 --remove-all-storage

QEMU

sudo apt install ninja-build \
  zlib1g zlib1g-dev \ 
  libglib2.0-dev \
  libspice-server-dev libspice-protocol-dev \
  libusbredirhost-dev libusbredirparser-dev \
  libpixman-1-dev
wget https://download.qemu.org/qemu-7.2.0.tar.xz
tar xvJf qemu-7.2.0.tar.xz
cd qemu-7.2.0
./configure --enable-kvm --enable-spice -enable-usb-redir  | tee /tmp/qemu_configure.log
grep -i 'usbredir' /tmp/qemu_configure.log
make
make install

Failed to start QEMU binary /usr/local/bin/qemu-system-x86_64 for probing: libvirt: error : cannot execute binary /usr/local/bin/qemu-system-x86_64: Permission denied - libvirt for qemu | Winddoing's Notes

sudo aa-status
vim /etc/apparmor.d/usr.sbin.libvirtd
# add bellow line
# /usr/local/bin/* PUx,
systemctl restart apparmor.service

OR stop the apparmor to test

systemctl stop apparmor

Virt Manager

virt-install --osinfo list
osinfo-query os

Ubuntu

if the node is the vmware vm, enable "向客體作業系統公開硬體協助虛擬化" in "硬體虛擬化"

sudo apt-get -y install bridge-utils cpu-checker libvirt-clients libvirt-daemon libvirt-daemon-system qemu qemu-kvm
sudo kvm-ok
lsmod | grep kvm
modinfo kvm
modinfo kvm_amd
systemctl status libvirtd
virsh list --all
sudo apt-get -y install virt-manager

GUI

sudo apt-get install slim ubuntu-desktop
sudo reboot
systemctl status slim.service

Web Console

sudo apt-get install cockpit cockpit-machines
# for error "sscg: command not found"
sudo apt-get install libgnutls-openssl27

sudo systemctl start cockpit
sudo systemctl status cockpit
sudo ufw allow 9090/tcp
sudo ufw reload

For Ubuntu 22.04 guest - basic concept

wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
cp jammy-server-cloudimg-amd64.img /var/lib/libvirt/images/
qemu-img create -F qcow2 -b jammy-server-cloudimg-amd64.img -f qcow2 my-ubuntu-vm.img 10G
cp my-ubuntu-vm.img /var/lib/libvirt/images/

virt-install --name my-first-vm --ram 6144 --vcpus 2 --import --disk path=/var/lib/libvirt/images/my-ubuntu-vm.img,format=qcow2 --cloud-init root-password-generate=on,disable=on,meta-data=/root/meta-data,user-data=/root/user-data --os-variant ubuntu22.04 --network bridge=virbr0 --graphics vnc,listen=0.0.0.0 --console pty,target_type=serial --noautoconsole

virsh net-dhcp-leases default

meta-data

# meta-data
instance-id: my-ubuntu-vm
local-hostname: my-ubuntu-vm

user-data - https://bugs.launchpad.net/cloud-images/+bug/2049860/comments/15

#cloud-config
ssh_pwauth: true
users:
  - name: root
    lock_passwd: false
    hashed_passwd: $6$P2LlhzIYWXC4XyCa$JzSWM6UBQ3BNLtQXO2jKTIhkBQyNl8DuhJ6tx8kovCtiick0mXMWE6z12HGBhTzAPW0EpDglWn7j.W9XZoaBl0
  - name: ubuntu
    lock_passwd: false
    hashed_passwd: $6$P2LlhzIYWXC4XyCa$JzSWM6UBQ3BNLtQXO2jKTIhkBQyNl8DuhJ6tx8kovCtiick0mXMWE6z12HGBhTzAPW0EpDglWn7j.W9XZoaBl0
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
:::info \$6\$P2LlhzIYWXC4XyCa$JzSWM6UBQ3BNLtQXO2jKTIhkBQyNl8DuhJ6tx8kovCtiick0mXMWE6z12HGBhTzAPW0EpDglWn7j.W9XZoaBl0 => foo@123

from openssl passwd -6 foo@123 :::

whole thing for Ubuntu

ssh-keygen -t ed25519 -C "KVM VM Instance" -f ~/.ssh/kvm-vm-instance

# Launch the Ubuntu 22.04 Guest OS
wget -O /var/lib/libvirt/images/jammy-server-cloudimg-amd64.img https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img

# Launch the Ubuntu 24.04 Guest OS
wget -O /var/lib/libvirt/images/noble-server-cloudimg-amd64.img https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img

cat <<'EOF' >> /root/meta-data
# meta-data
instance-id: k8s-ubuntu-vm
local-hostname: k8s-ubuntu-vm
EOF

# ubuntu/foo@123
# note: shell is interpreting the $ characters in your hashed password as variable expansions. so use single quote 'EOF'

cat <<'EOF' >> /root/user-data
#cloud-config
ssh_pwauth: true
users:
  - name: root
    lock_passwd: false
    hashed_passwd: $6$P2LlhzIYWXC4XyCa$JzSWM6UBQ3BNLtQXO2jKTIhkBQyNl8DuhJ6tx8kovCtiick0mXMWE6z12HGBhTzAPW0EpDglWn7j.W9XZoaBl0
  - name: ubuntu
    lock_passwd: false
    hashed_passwd: $6$P2LlhzIYWXC4XyCa$JzSWM6UBQ3BNLtQXO2jKTIhkBQyNl8DuhJ6tx8kovCtiick0mXMWE6z12HGBhTzAPW0EpDglWn7j.W9XZoaBl0
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
    #ssh_authorized_keys:
    #  - ssh-ed25519 AAAAC3NzaC1lZDI1NT... your-public-key-here
EOF

# For Ubuntu 22.04 Guest OS
qemu-img create -F qcow2 -b /var/lib/libvirt/images/jammy-server-cloudimg-amd64.img -f qcow2 /var/lib/libvirt/images/k8s-ubuntu-vm-worker-2.img 30G

virt-install --name k8s-worker-2 --ram 4096 --vcpus 4 --import --disk path=/var/lib/libvirt/images/k8s-ubuntu-vm-worker-2.img,format=qcow2 --cloud-init root-password-generate=on,disable=on,meta-data=/root/meta-data,user-data=/root/user-data --os-variant ubuntu22.04 --network bridge=virbr0 --graphics vnc,listen=0.0.0.0 --console pty,target_type=serial --noautoconsole

# For Ubuntu 24.04 Guest OS
qemu-img create -F qcow2 -b /var/lib/libvirt/images/noble-server-cloudimg-amd64.img -f qcow2 /var/lib/libvirt/images/ubuntu-noble-1.img 20G

virt-install --name ubuntu-noble-1 \
  --ram 4096 --vcpus 4 --import --disk path=/var/lib/libvirt/images/ubuntu-noble-1.img,format=qcow2 \
  --cloud-init root-password-generate=on,disable=on,meta-data=/root/meta-data,user-data=/root/user-data --os-variant ubuntu24.04 \
  --network bridge=virbr0 \
  --graphics vnc,listen=0.0.0.0 --console pty,target_type=serial --noautoconsole

Redhat

For redhat guest

  1. fetch Red Hat Enterprise Linux x.x KVM Guest Image
    • example: rhel-8.8-x86_64-kvm.qcow2
  2. Creating a virtual machine from a KVM guest image
mkdir cloudinitiso
cd cloudinitiso

meta-data

instance-id: citest
local-hostname: vm-rhel

user-data

#cloud-config
ssh_pwauth: true
users:
  - name: root
    lock_passwd: false
    hashed_passwd: $6$P2LlhzIYWXC4XyCa$JzSWM6UBQ3BNLtQXO2jKTIhkBQyNl8DuhJ6tx8kovCtiick0mXMWE6z12HGBhTzAPW0EpDglWn7j.W9XZoaBl0
  - name: rhel
    lock_passwd: false
    hashed_passwd: $6$P2LlhzIYWXC4XyCa$JzSWM6UBQ3BNLtQXO2jKTIhkBQyNl8DuhJ6tx8kovCtiick0mXMWE6z12HGBhTzAPW0EpDglWn7j.W9XZoaBl0
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL

cp rhel-8.8-x86_64-kvm.qcow2 /var/lib/libvirt/images/
qemu-img create -F qcow2 -b rhel-8.8-x86_64-kvm.qcow2 -f qcow2 my-rhel-vm.img 20G
mv my-rhel-vm.img /var/lib/libvirt/images/

method 1: use cloud-init.iso

genisoimage -output cloud-init.iso -volid cidata -joliet -rock user-data meta-data
cp cloudinitiso/cloud-init.iso /var/lib/libvirt/images/
virt-install \
    --memory 4096 \
    --vcpus 4 \
    --name myvm \
    --disk /var/lib/libvirt/images/my-rhel-vm.img,device=disk,bus=virtio,format=qcow2 \
    --disk /var/lib/libvirt/images/cloud-init.iso,device=cdrom \
    --os-variant rhel8.8 \
    --virt-type kvm \
    --graphics vnc,listen=0.0.0.0 \
    --console pty,target_type=serial \
    --noautoconsole \
    --import

method 2: use --cloud-init argument

virt-install  \
    --memory 4096  \
    --vcpus 4  \
    --name myvm2  \
    --disk /var/lib/libvirt/images/my-rhel-vm.img,device=disk,bus=virtio,format=qcow2  \
    --cloud-init root-password-generate=on,disable=on,meta-data=/root/cloudinitiso/meta-data,user-data=/root/cloudinitiso/user-data  \
    --os-variant rhel8.8  \
    --virt-type kvm  \
    --graphics vnc,listen=0.0.0.0  \
    --console pty,target_type=serial  \
    --noautoconsole  \
    --import

For rocky linux guest

wget -O /var/lib/libvirt/images/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2 https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2

cat <<'EOF' >> /root/meta-data-rocky9
# meta-data
instance-id: rocky9-vm
local-hostname: rocky-vm
EOF

cat <<'EOF' >> /root/user-data-rocky9
#cloud-config
ssh_pwauth: true
users:
  - name: root
    lock_passwd: false
    hashed_passwd: $6$P2LlhzIYWXC4XyCa$JzSWM6UBQ3BNLtQXO2jKTIhkBQyNl8DuhJ6tx8kovCtiick0mXMWE6z12HGBhTzAPW0EpDglWn7j.W9XZoaBl0
  - name: rocky
    lock_passwd: false
    hashed_passwd: $6$P2LlhzIYWXC4XyCa$JzSWM6UBQ3BNLtQXO2jKTIhkBQyNl8DuhJ6tx8kovCtiick0mXMWE6z12HGBhTzAPW0EpDglWn7j.W9XZoaBl0
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
    #ssh_authorized_keys:
    #  - ssh-ed25519 AAAAC3NzaC1lZDI1NT... your-public-key-here
EOF

# For Rocky Linux 9 Guest OS
qemu-img create -F qcow2 -b /var/lib/libvirt/images/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2 -f qcow2 /var/lib/libvirt/images/rocky9-1.img 20G


virt-install  \
    --name rocky9-1  \
    --memory 4096  \
    --vcpus 4  \
    --disk path=/var/lib/libvirt/images/rocky9-1.img,device=disk,bus=virtio,format=qcow2  \
    --cloud-init root-password-generate=on,disable=on,meta-data=/root/meta-data-rocky9,user-data=/root/user-data-rocky9  \
    --os-variant rocky9  \
    --virt-type kvm  \
    --graphics vnc,listen=0.0.0.0  \
    --console pty,target_type=serial  \
    --noautoconsole  \
    --import

for multiple vms at one time

#!/bin/bash

IMAGES=("rocky9-1" "rocky9-2")
BASE_IMAGE="/var/lib/libvirt/images/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2"
META_DATA="/root/meta-data-rocky9"
USER_DATA="/root/user-data-rocky9"

for img in "${IMAGES[@]}"; do
  qemu-img create -F qcow2 -b "$BASE_IMAGE" -f qcow2 "/var/lib/libvirt/images/${img}.img" 20G
  virt-install \
    --name "$img" \
    --memory 4096 \
    --vcpus 4 \
    --disk path="/var/lib/libvirt/images/${img}.img",device=disk,bus=virtio,format=qcow2 \
    --cloud-init root-password-generate=on,disable=on,meta-data="$META_DATA",user-data="$USER_DATA" \
    --os-variant rocky9 \
    --virt-type kvm \
    --graphics vnc,listen=0.0.0.0 \
    --console pty,target_type=serial \
    --noautoconsole \
    --import \
    --network bridge=br0 --network bridge=virbr0

  # Wait for VM to appear in list (optional: adjust as needed)
  echo "Waiting for VM $img to boot and acquire IP..."
  sleep 10

  # Try for up to 30 seconds to get IP
  for attempt in {1..6}; do
    VM_IP=$(virsh domifaddr "$img" --source agent | awk '/ipv4/ {print $4}' | cut -d'/' -f1)
    if [[ -n "$VM_IP" ]]; then
      echo "VM $img IP address: $VM_IP"
      break
    else
      sleep 5
    fi
  done
  if [[ -z "$VM_IP" ]]; then
    echo "Unable to determine IP address for $img."
  fi
done

command

network

virsh net-list --all
bridge fdb show