Home Linux DistributionsCentOS Install And Configure KVM In CentOS 8 Server
How To Install And Configure KVM In CentOS 8 Server

Install And Configure KVM In CentOS 8 Server

By sk
465 Views

KVM, short for Kernel-based Virtual Machine, is a FreeBSD and Linux kernel module that allows the kernel to act as a hypervisor. Starting from kernel version 2.6.20, KVM is merged into Linux kernel mainline. Using KVM, you can easily setup a virtualization environment in a Linux machine and deploy a wide variety of guest operating systems including Linux, Windows, BSD, Mac OS and many. In this guide, we will look at how to install and configure KVM in CentOS 8 server edition.

Prerequisites

Before installing KVM, first make sure your system supports hardware virtualization. We have documented a few different ways to identify whether a Linux system supports Virtualization in the following guide.

If your system supports hardware virtualization, continue the following steps.

Install And Configure KVM In CentOS 8 Server

For the purpose of this guide, I will be using the following system:

KVM virtualization server:

  • OS – CentOS 8 minimal server (No GUI)
  • IP Address : 192.168.225.53/24

Even though it is tested on CentOS 8, this guide also should on fine on RHEL 8 as well.

Install KVM in CentOS 8

Note: All commands given through out this tutorial should be run as "root" user. If you've logged in as normal user, add "sudo" in-front of all commands give below.

Install Kvm and all required dependencies to setup a virtualization environment on your CentOS 8 sever using command as "root" user:

# dnf install qemu-kvm libvirt virt-install

Here,

  • emu-kvm - QEMU metapackage for KVM support (i.e. QEMU Full virtualization on x86 hardware),
  • libvirt - programs for the libvirt library,
  • virt-install - programs to create and clone virtual machines.

Once KVM is installed, enable and start libvertd service (If it is not started already):

# systemctl enable libvirtd
# systemctl start libvirtd

You can also combine both commands and run them as an one-liner like below:

# systemctl enable --now libvirtd

Check the status of libvirtd service with command:

# systemctl status libvirtd

Sample output:

● libvirtd.service - Virtualization daemon
   Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; vendor preset: enable>
   Active: active (running) since Wed 2020-07-15 14:27:32 IST; 5s ago
     Docs: man:libvirtd(8)
           https://libvirt.org
 Main PID: 1097 (libvirtd)
    Tasks: 17 (limit: 32768)
   Memory: 57.0M
   CGroup: /system.slice/libvirtd.service
           └─1097 /usr/sbin/libvirtd

Jul 15 14:27:28 centos8.ostechnix.lan systemd[1]: Starting Virtualization daemon...
Jul 15 14:27:32 centos8.ostechnix.lan systemd[1]: Started Virtualization daemon.

The libvertd service is up and running!

Verify if the KVM modules are loaded:

# lsmod | grep kvm

Sample output:

kvm_intel             294912  0
kvm                   786432  1 kvm_intel
irqbypass              16384  1 kvm

Great! KVM modules are loaded. Let us create a network bridge now.

Setup Bridge networking with KVM in CentOS

A bridged network shares the real network interface of the host computer with other VMs to connect to the outside network. Therefore each VM can bind directly to any available IPv4 or IPv6 addresses, just like a physical computer.

By default KVM setups a private virtual bridge, so that all VMs can communicate with one another, within the host computer. It provides its own subnet and DHCP to configure the guest’s network and uses NAT to access the host network.

Have a look at the IP address of the KVM default virtual interfaces using “ip” command:

# ip a

Sample output:

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 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:b7:3a:84 brd ff:ff:ff:ff:ff:ff
    inet 192.168.225.52/24 brd 192.168.225.255 scope global dynamic noprefixroute enp0s3
       valid_lft 42217sec preferred_lft 42217sec
    inet6 2409:4072:918:98cf:ad3b:b969:8ec8:f9c7/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::b404:4d52:8bee:18bf/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:2a:be:53 brd ff:ff:ff:ff:ff:ff
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:41:91:4d brd ff:ff:ff:ff:ff:ff
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:5b:a4:cd brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:5b:a4:cd brd ff:ff:ff:ff:ff:ff

View KVM default virtual interface IP address using ip command

As you can see, KVM default network virbr0 uses 192.168.122.1/24 IP address. All the VMs will use an IP address in the 192.168.122.0/24 IP range and the host OS will be reachable at 192.168.122.1. You should be able to ssh into the host OS (at 192.168.122.1) from inside the guest OS and use scp to copy files back and forth.

It is OK if you only access the VMs inside from the host itself. However you can’t access the VMs from other remote systems in the network. Because they use different IP range i.e. 192.168.225.0/24 in my case. In order to access the VMs from other remote hosts, we must setup a public bridge that runs on the host network and uses whatever external DHCP server is on the host network. To put this in layman terms, we are going to make all VMs to use the same IP series used by the host system.

Before setting up a public bridged network, we should disable Netfilter for performance and security reasons. Netfilter is currently enabled on bridges by default.

To disable netfilter, create a file called /etc/sysctl.d/bridge.conf:

# vi /etc/sysctl.d/bridge.conf

Add the following lines:

net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-arptables=0

Save and close the file.

Then create another file called /etc/udev/rules.d/99-bridge.rules :

# vi /etc/udev/rules.d/99-bridge.rules

Add the following line:

ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", RUN+="/sbin/sysctl -p /etc/sysctl.d/bridge.conf"

This will set the necessary flags to disable netfilter on bridges at the appropriate place in system start-up. Save and close the file. Reboot your system to take effect these changes.

Next, we should disable the default networking that KVM installed for itself.

Find the name of KVM default network interfaces using "ip link" command:

# ip link

Sample output:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:b7:3a:84 brd ff:ff:ff:ff:ff:ff
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:2a:be:53 brd ff:ff:ff:ff:ff:ff
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:41:91:4d brd ff:ff:ff:ff:ff:ff
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
    link/ether 52:54:00:5b:a4:cd brd ff:ff:ff:ff:ff:ff
6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN mode DEFAULT group default qlen 1000
    link/ether 52:54:00:5b:a4:cd brd ff:ff:ff:ff:ff:ff

View KVM default network interfaces using ip command in CentOS

As you see in the above output, the entries "virbr0" and "virbr0-nic" are the KVM networks.

Let us remove the default KVM network with command:

# virsh net-destroy default

Sample output:

Network default destroyed

Undefine the default network with command:

# virsh net-undefine default

Sample output:

Network default has been undefined

Remove default KVM network interfaces using virsh command

If the above commands doesn't work for any reason, you can use these commands to disable and undefine KVM default network:

# ip link delete virbr0 type bridge
# ip link delete virbr0-nic

Now run "ip link" again to verify if the virbr0 and virbr0-nic interfaces are actually deleted:

# ip link

Sample output:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:b7:3a:84 brd ff:ff:ff:ff:ff:ff
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:2a:be:53 brd ff:ff:ff:ff:ff:ff
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:41:91:4d brd ff:ff:ff:ff:ff:ff

Well, the KVM default networks are gone.

Now, let us setup the KVM public bridge to use when creating a new VM.

Create a new bridged interface named "br0" using "nmcli"command:

# nmcli connection add type bridge autoconnect yes con-name br0 ifname br0

Set IP address for the bridge interface:

# nmcli connection modify br0 ipv4.addresses 192.168.225.53/24 ipv4.method manual

Set Gateway for the bridge interface:

# nmcli connection modify br0 ipv4.gateway 192.168.225.1

Set DNS for the bridge interface:

# nmcli connection modify br0 ipv4.dns 192.168.225.1

Next we need to remove one of your network interface cards and add it as slave to the bridge.

Please note that if your server has only one NIC and you are accessing the server via SSH, your connection will be terminated after removing the NIC. I suggest you to do the following steps in your server's console.

For example, I am going to add "enp0s8" interface as slave to the bridge interface br0.

To remove the network interface "enp0s8", run:

# nmcli connection del enp0s8

Replace "enp0s8" with your own network card.


Note:

Do not use wireless network interface cards for bridges. Most wireless interlaces do not support bridging. Always use wired network interfaces for seamless connectivity!


Next, add the "enp0s8" to the bridge using command:

# nmcli connection add type bridge-slave autoconnect yes con-name enp0s8 ifname enp0s8 master br0

Here, the bridge network interface “br0” is attached to host’s network interface “enp0s8”. Replace the above network interface names that matches with your network.

Restart the network manager to take effect the changes:

# systemctl restart NetworkManager

If possible, it is better to restart your system:

# reboot

Login to your server and check if the IP address has been assigned to the bridge interface:

$ ip a

Sample output:

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 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether 08:00:27:b7:3a:84 brd ff:ff:ff:ff:ff:ff
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether 08:00:27:2a:be:53 brd ff:ff:ff:ff:ff:ff
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:41:91:4d brd ff:ff:ff:ff:ff:ff
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 08:00:27:2a:be:53 brd ff:ff:ff:ff:ff:ff
    inet 192.168.225.53/24 brd 192.168.225.255 scope global noprefixroute br0
       valid_lft forever preferred_lft forever
    inet6 2409:4072:6084:198:df03:d9ed:62eb:df34/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::e8c8:e98b:7fef:5874/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

Check KVM bridge IP address from command line in Linux

As you see in the above output, the bridged network interface br0 is assigned with IP address 192.168.225.53 and the enp0s8 entry now has “master br0” entry. It means that enp0s8 belongs to the bridge.

You can also use “bridge” command to show the bridge status:

# bridge link show br0
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 100

We have successfully created a bridge interface and it is active. We need to do one last thing.

We should configure KVM to use this bridge interface as default interface. To do so, create a an XML file called host-bridge.xml :

# vi host-bridge.xml

Add the following lines:

<network>
  <name>host-bridge</name>
  <forward mode="bridge"/>
  <bridge name="br0"/>
</network>

Run the following commands to start the newly created bridge and make it as default bridge for VMs:

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

Configure KVM to use bridge interface as default interface for all VMs

Verify if the bridge is active and started using command:

# virsh net-list --all

Sample output:

Name          State    Autostart   Persistent
------------------------------------------------
 host-bridge   active   yes         yes

Verify KVM host bridge status using virsh command

Congratulations! We've successful installed and configured KVM in CentOS 8 headless server.

Create and manage KVM guest machines

We can create and manage VMs either from command line or using any KVM management tools like Cockpit and Virt-manager. Refer the following guides to for more details.

I will cover how to create and manage VMs from command line in a separate guide.

Enable Virsh Console Access For Virtual Machines

After creating the KVM guests, I can be able to access them via SSH, VNC client, Virt-viewer, Virt-manager and Cockpit web console etc. But I couldn't access them using "virsh console" command. To access KVM guests using "virsh console", refer the following guide:

Other KVM related guides

Hope this helps.

Resource:

Thanks for stopping by!

Help us to help you:

Have a Good day!!

You May Also Like

1 comment

MrCalvin July 16, 2020 - 5:05 pm

KVM/QEMU on CentOS?
Every time I tested CentOS as a virtualizor host candidate always run away when I see the versions of Kernel, QEMU & libvirt, they are even older than on Debian stable (which I end up using)!
Or I’m I wrong? Would love to be corrected 🙂

Reply

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More