Home KVM Install And Configure KVM In CentOS 8 Server

Install And Configure KVM In CentOS 8 Server

By sk
Published: Last Updated on 113.2K views

This step by step guide explains what is KVM, and how to install and configure KVM in CentOS 8 Linux operating system.

This guide is officially tested in CentOS 8 minimal server edition. However, it should also work in RHEL 8 and its clones like AlmaLinux 8 and Rocky Linux 8.

What is KVM?

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 range of guest operating systems including Linux, Windows, BSD, Mac OS and many.

Now let us see how to install and configure KVM in CentOS 8 Linux.

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.

1. 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.

1.1. 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.

1.2. 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
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
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
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 interfaces' 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
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 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
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
Verify KVM host bridge status using virsh command

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

2. 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.

3. 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:

Conclusion

In this guide, we discussed how to install and configure KVM in CentOS 8 server edition.

We also looked at how to create and manage KVM virtual machines from command line using virsh tool and using GUI tools named Cockpit and Virt-manager.

Finally, we saw how to enable virsh console access for KVM virtual machines.

At this stage, you should have fully working virtualization environment in your CentOS 8 server.

Resource:

You May Also Like

4 comments

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
Nishith N. Vyas May 25, 2023 - 6:12 pm

Hello,

Using this document, I’ve configured a total of 5 KVM Hypervisors based on CentOS 7.9 & 8.2.

Now, I want to change the IP Address as those servers are moving to another data center where the IP Address will be different.

So, please guide what changes needs to be done.

Reply
sk May 26, 2023 - 1:43 pm

Just change the IP address of the servers and recreate the bridge matching to the new IP series.

Reply
Joel March 16, 2024 - 5:23 pm

I succeeded setting up KVM bridge network using this article. Thanks for writing detailed steps!

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. By using this site, we will assume that you're OK with it. Accept Read More