KVM-QEMU HOWTO
This article presents a step-by-step guide on how to compile and boot kvm and Qemu.
References
Install KVM
Make sure that your CPU supports hardware virtualization.
egrep -c '(vmx|svm)' /proc/cpuinfo
If 0 it means that your CPU doesn't support hardware virtualization. If 1 or more it does - but you still need to make sure that virtualization is enabled in the BIOS.
Install KVM packages
sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils
Make sure your Ubuntu username is added to the group libvirtd
sudo adduser `id -un` libvirtd
Note: Because I focus on the NVMes SSD performance evaluation, the networking is not necessary and is not mentioned here.
Compile Qemu [Optional]
Actually, Qemu is installed when installing KVM. In the field of virtualizaton, Qemu is usually modified for specific usage. The executable file of Qemu is located at /usr/bin
, by default.
$ which is qemu-system-x86_64
/usr/bin/qemu-system-x86_64
Download Qemu repository
$ git clone https://github.com/qemu/qemu.git
Configure Qemu
$ cd qemu
$ git submodule update --init dtc
$ ./configure --prefix=/usr/local \
-- enable-kvm \
-- target-list=x86_64-softmmu
$ make -j8
$ make install [OPTIONAL]
--prefix
represents the location where Qemu is installed,/usr
is default, and we choose/usr/local
to avoid overlapping and keep both.enable-kvm
enables KVM support.-- target-list
specify the compile target, wo only needx86_64-softmmu
.make install
is not necessary, for me, I prefer not to make install. When running the Qemu compiled by myself, command/path/to/qemu/x86_64-softmmu/qemu-system-x86_64 -m 1024 -cpu host -hda guest.img ......
specifies the detailed path of Qemu executable file.
Boot Example
Here is an example script for booting the kvm guest, which can be considered as a template.
$ cat kvm-install.sh
#! /bin/bash
/usr/bin/qemu-system-x86_64 \
-m 1024 -smp 2 -M pc -name kvm-guest \
-cpu host -enable-kvm -machine kernel_irqchip=on \
-hda /path/to/guest.img \
-cdrom /path/to/install.iso
$ cat kvm-boot.sh
#! /bin/bash
/usr/bin/qemu-system-x86_64 \
-m 1024 -smp 2 -M pc -name kvm-guest \
-cpu host -enable-kvm -machine kernel_irqchip=on \
-hda /path/to/guest.img
$ cat kvm-boot-remotely.sh
#! /bin/bash
/usr/bin/qemu-system-x86_64 \
-m 1024 -smp 2 -M pc -name kvm-guest \
-cpu host -enable-kvm -machine kernel_irqchip=on \
-hda /path/to/guest.img \
-vnc :1
Networking
The lib bridge-utils
already sets up virbr0 for you. If you want to customize, you can do as follows.
$ cat /etc/qemu-ifup
#!/bin/sh
if [ ! -n "$1" ];then
echo "Error: no interface specified"
exit 1
fi
for dev_inf in $(ip addr show |grep 'scope global'|awk '{print $NF;}')
do
switch=$(brctl show |grep "^$dev_inf[[:space:]]"|awk '{print $1;}')
if [ $switch ];then
break
fi
done
if [ ! "$switch" ];then
echo "Error: no switch specified"
exit 1
fi
tunctl -u root -t $1
ip link set $1 up
sleep 1s
brctl addif $switch $1
exit 0
$ chmod 775 /etc/qemu-ifup
$ cat crbr.sh
[[ -c /dev/kvm ]] && TARGET_BRG=sw0
[[ -d /dev/xen ]] && TARGET_BRG=xenbr0
func_install_brctl()
{
which brctl 2>&1>/dev/null
local miss_brctl=$?
[[ $miss_brctl -eq 0 ]] && return
local TYPE_UNKNOW=0 TYPE_YUM=1 TYPE_APT=2
local install_type=TYPE_UNKNOW install_cmd
which yum 2>&1>/dev/null
[[ $? -eq 0 ]] && install_type=$TYPE_YUM
which apt-get 2>&1>/dev/null
[[ $? -eq 0 ]] && install_type=$TYPE_APT
case $install_type in
$TYPE_YUM) install_cmd="yum install -y bridge-utils" ;;
$TYPE_APT) install_cmd="apt-get install -y --force-yes bridge-utils" ;;
*) echo "Miss tool to install tools" && exit ;;
esac
$install_cmd
}
func_route_fix()
{
local dup_route=$(ip route list|grep -v 'default via'|sed -n 's/.*[^0-9]\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p'|uniq -dc)
[[ ! "$dup_route" ]] && echo "Current route is health" && return
echo "Catch duplicate route, start fix route process"
echo "Shutdown bridge $1"
ip addr flush $1
echo "Shutdown ethernet $2"
ip addr flush $2
echo "Kill dhclient"
pkill -f "dhclient $1"
echo "Turn on bridge $1"
ip link set dev $1 up
echo "Assign IP to $TARGET_BRG"
dhclient $1
echo "Route fix process finished"
}
func_setup_bridge()
{
local brg_name=$(brctl show|grep "^$TARGET_BRG[[:space:]]") dev_inf
if [ "$brg_name" ];then
echo "$TARGET_BRG exsit"
else
echo "Miss $TARGET_BRG, detect bridge effect"
for dev_inf in $(ip addr show |grep 'scope global'|awk '{print $NF;}')
do
brg_name=$(brctl show |grep "^$dev_inf[[:space:]]"|awk '{print $1;}')
if [ "$brg_name" ];then
dev_inf=$(brctl show $brg_name|sed -n '2p'|awk '{print $4;}')
echo "Already active bridge: $brg_name combine with $dev_inf, please manual check bridge create "
return
fi
done
echo "Create $TARGET_BRG"
brctl addbr $TARGET_BRG
fi
dev_inf=$(brctl show $TARGET_BRG|sed -n '2p'|awk '{print $4;}')
if [ "$dev_inf" ];then
echo "Already combine $dev_inf with $TARGET_BRG"
func_route_fix $TARGET_BRG $dev_inf
else
while [ true ]
do
dev_inf=$(ip addr show |grep 'scope global'|awk '{print $NF;}'|head -n 1)
[[ "$dev_inf" ]] && break
sleep 5s
done
echo "Shutdown interface $dev_inf"
ip addr flush dev $dev_inf
echo "Combine $dev_inf with $TARGET_BRG"
brctl addif $TARGET_BRG $dev_inf
echo "Turn on $TARGET_BRG"
ip link set dev $TARGET_BRG up
fi
local ip_assign=$(ps -ef|grep "dhclient $TARGET_BRG"|grep -v 'grep')
if [ "$ip_assign" ];then
echo "Already assign ip to $TARGET_BRG"
else
echo "Assign IP to $TARGET_BRG"
dhclient $TARGET_BRG
fi
}
func_install_brctl
func_setup_bridge
$ cat boot-with-networing.sh
/usr/bin/qemu-system-x86_64 \
-m 1024 -smp 2 -M pc -name kvm-guest \
-cpu host -enable-kvm -machine kernel_irqchip=on \
-hda /path/to/guest.img \
-net nic -net tap,script=/etc/qemu-ifup \
-net nic,model=e1000,macaddr=00:DE:EF:12:34:5D
There are other available network setup as follows.
-net nic,model=virtio,vlan=0,macaddr=00:16:3e:00:01:01
-net tap,vlan=0,script=/root/ifup-br0,downscript=/root/ifdown-br0
-net nic,model=virtio,vlan=1,macaddr=00:16:3e:00:01:02
-net tap,vlan=1,script=/root/ifup-br1,downscript=/root/ifdown