Create a KVM virtual server on CentOS

Creating a virtual server inside your host operating system/server can be incredibly useful for a number of reasons from staging to resource isolation to guest access to resources, this guide will give you a quick overview on how to get your very first virtual server up and running, this guide is based around CentOS 7.

First of all, you will need to install the required packages:

yum -y install qemu-kvm libvirt libvirt-python libguestfs-tools virt-install

Now Enable libvirtd:

systemctl enable libvirtd
systemctl start libvirtd

Now if you run ifconfig you will see you have a new interface ‘virbr0’ with IP address this is the default local IP/LAN IP range for guest virtual servers, as standard, the guest virtual servers can only talk to each other, and cannot reach the public internet this is obviously not ideal as you might want to do a network-based install or run updates or get packages so to give them internet access and use the host server as a gateway we need to add some SNAT iptables rules, the last IP is the IP address of your main interface:

iptables -t nat -A POSTROUTING -s -o virbr0 -j SNAT --to-source

We also need to add the following to /etc/sysctl.conf

net.ipv4.ip_forward = 1
net.ipv4.ip_forward = 1
net.ipv4.conf.default.proxy_arp = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.send_redirects = 1
net.ipv4.conf.all.send_redirects = 0

Then run ‘sysctl -p’ to load the above.

Now we will need to download some media to set up our new virtual server with, libvirt created an intuitive directory structure for you in /var/lib/libvirt/ we will grab the latest centos 7 ISO and put it in /var/lib/libvirt/boot/

wget -O /var/lib/libvirt/boot/CentOS-7-x86_64-Minimal-2009.iso

For speed in the future it is good to create deployment scripts per operating system, create a file with your favourite editor called centos7 in /var/lib/libvirt/boot with the following inside it:

virt-install \
--virt-type=kvm \
--name centos7 \
--ram 2048 \
--vcpus=1 \
--os-variant=centos7.0 \
--cdrom=/var/lib/libvirt/boot/CentOS-7-x86_64-Minimal-2009.iso \
--network network=default \
--graphics vnc,password=1234abcd,listen=,port=5901 --noautoconsole \
--disk path=/var/lib/libvirt/images/centos7.qcow2,size=40,bus=virtio,format=qcow2

Now you can start the script by running ‘sh /var/lib/libvirt/boot/centos7 &’, The & at the end of the command puts it to the background so you can continue in the current shell, once the install is complete the process will end.

You can now connect using a VNC client to your host servers main IP address on port 5901 using password 1234abcd as defined in the deployment script above and complete the install giving the virtual server an IP from the virtbr0 range e.g. subnet gateway DNS although you will be assigned an IP via the virtbr0 interface DHCP if you prefer.

You can change almost any line in the deployment script above to change your options for different operating systems. Just remember to give the disk ‘centos7.qcow2’ and the name ‘centos7’ a unique identifier. The VNC port and password should also be unique per virtual server.

Once the installation is complete from the host node you will need to boot the virtual server you just created with ‘virsh start centos7’ centos7 being the name given in the deployment script above then run ‘virsh list’ to see all running virtual machines:

# virsh start centos7
Domain centos7a started

[root@host libvirt]# virsh list
 Id    Name                           State
 7     centos7                        running

virsh is the main command tool for managing your virtual servers; take a look at our guide on it here.

Now we can connect to the running virtual server with ssh from the host server and then verify it has network access:

# ssh root@
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:ExlygakG39zcyMqCwx0PSDhiKaHqhesYCLDVGqbn/OE.
ECDSA key fingerprint is MD5:d4:e1:4c:4a:ef:d2:2b:ac:c3:68:9d:c2:2b:e4:88:95.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '' (ECDSA) to the list of known hosts.
root@'s password: 
[root@centos7 ~]# ip addr
1: lo: <loopback,up,lower_up> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <broadcast,multicast,up,lower_up> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:1d:43:9b brd ff:ff:ff:ff:ff:ff
    inet brd scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a5db:a32e:2369:3dcd/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[root@centos7 ~]# ping
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=116 time=0.446 ms
64 bytes from icmp_seq=2 ttl=116 time=1.04 ms
64 bytes from icmp_seq=3 ttl=116 time=1.03 ms
--- ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.446/0.840/1.041/0.278 ms</broadcast,multicast,up,lower_up></loopback,up,lower_up>

You can do port forwarding from the host server to the virtual server if you want to access it over ssh externally, but that is beyond the scope of this guide.