How to Install and Configure KVM on Ubuntu

Posted on

How to Install and Configure KVM on Ubuntu

How to Install and Configure KVM on Ubuntu

KVM (Kernel-based Virtual Machine) is an open-source virtualization technology that empowers you to create and run virtual machines (VMs) directly on your Linux system. It leverages the Linux kernel itself, turning it into a hypervisor. KVM requires hardware virtualization support, a feature present in most modern CPUs from Intel (VT-x) and AMD (AMD-V).

In this comprehensive guide, we’ll delve into how to install and configure KVM on Ubuntu 20.04/22.04. We will cover the following steps:

  • Checking hardware virtualization support.
  • Installing the necessary KVM packages.
  • Loading the required kernel modules.
  • Setting up the KVM user group.
  • Creating a KVM virtual machine using the command line interface (CLI).
  • Creating a KVM virtual machine using the graphical user interface (GUI) with Virt Manager.
  • Managing KVM virtual machines.
  • Optimizations and best practices for KVM.

By the end of this guide, you will have KVM installed and configured, and you will have created virtual machines using both CLI and GUI methods. Let’s get started!

Prerequisites

Before we install KVM, let’s go over the prerequisites:

  • A running Ubuntu 20.04/22.04 system.
  • A user account with sudo privileges.
  • Hardware virtualization support in your CPU.
  • Virtualization enabled in BIOS/UEFI settings.

To verify that your CPU supports hardware virtualization, run this command:

$ egrep -c '(vmx|svm)' /proc/cpuinfo

If the output is 1 or greater, your CPU supports hardware virtualization.

You also need to ensure virtualization is enabled in BIOS. Reboot your system, enter BIOS setup, and enable Intel VT-x/AMD-V.

Now let’s move on to installing KVM.

Install KVM and Other Required Packages

We need to install a few packages to use KVM. Run these commands to install KVM and other required utilities:

$ sudo apt update
$ sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager

This installs the main packages:

  • qemu-kvm: The core KVM package providing the virtualization functionality.
  • libvirt-daemon-system: The libvirt daemon, which manages virtual machines.
  • libvirt-clients: Command-line tools for managing libvirt.
  • bridge-utils: Utilities for creating and managing bridge devices for networking.
  • virt-manager: A graphical user interface for managing virtual machines.

Verify the installation by checking the version of KVM:

$ kvm --version

The output should display the installed KVM version:

QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.28)
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers

Now KVM and related utilities are installed. Next we’ll load the required kernel modules.

Load KVM Kernel Modules

KVM requires the kvm and kvm_intel/kvm_amd kernel modules to be loaded.

Check if they are loaded:

$ lsmod | grep kvm

If they are not loaded, run:

$ sudo modprobe kvm
$ sudo modprobe kvm_intel

This loads kvm and kvm_intel modules. Verify they are now loaded:

$ lsmod | grep kvm

The output should show the modules:

kvm_intel             204800  0
kvm                   593920  1 kvm_intel

KVM modules are now loaded and ready to use.

Set Up KVM User Group

For better security and access control, we will create a dedicated KVM group and add users to it.

Create a kvm group:

$ sudo groupadd kvm

Add your user to kvm group:

$ sudo usermod -aG kvm $USER

Add any other users who need KVM access to the kvm group as well.

Now we can continue with creating virtual machines.

Create a KVM Virtual Machine (CLI)

Let’s create a KVM virtual machine using command line tools.

We will perform the following steps:

  • Create a disk image for the VM.
  • Configure network bridging.
  • Define the VM resources using an XML definition file.
  • Start the VM installation.

First, create a disk image that will be used for VM storage:

$ sudo qemu-img create -f qcow2 /var/lib/libvirt/images/ubuntu-20.qcow2 10G

This creates a qcow2 format disk image at /var/lib/libvirt/images/ubuntu-20.qcow2 with 10GB capacity.

Next, we need to create a network bridge so the VM can connect to the network.

Edit /etc/netplan/00-installer-config.yaml and add a network bridge:

network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s3:
      dhcp4: no
    enp0s8:
      dhcp4: yes
  bridges:
    br0:
      interfaces: [enp0s3]
      dhcp4: no
      addresses: [192.168.122.1/24]
      gateway4: 192.168.122.1
      nameservers:
         addresses: [8.8.8.8,1.1.1.1]

This bridges the enp0s3 interface and assigns it an IP address of 192.168.122.1.

Apply the configuration:

$ sudo netplan apply

Now we have storage and networking ready. Let’s define the VM resources using a CLI definition file called ubuntu-vm.xml:

$ sudo nano ubuntu-vm.xml

Add this content:

<domain type='kvm'>
  <name>ubuntu-vm</name>
  <memory unit='GiB'>2</memory>
  <vcpu>2</vcpu>
  <os>
    <type arch='x86_64'>hvm</type>
  </os>
  <devices>
    <disk type='file' device='disk'>
      <source file='/var/lib/libvirt/images/ubuntu-20.qcow2'/>
      <target dev='vda'/>
    </disk>
    <interface type='bridge'>
      <source bridge='br0'/>
    </interface>
    <graphics type='vnc' listen='0.0.0.0' port='-1'/>
  </devices>
</domain>

This defines a KVM domain with:

  • Name: ubuntu-vm
  • Memory: 2GB
  • vCPUs: 2
  • Disk image: /var/lib/libvirt/images/ubuntu-20.qcow2
  • Network: bridged to br0
  • Graphics: VNC

Now let’s launch the VM installation:

$ sudo virt-install --import --name ubuntu-vm --ram 2048 --disk /var/lib/libvirt/images/ubuntu-20.qcow2,size=10 --vcpus 2 --os-type linux --os-variant ubuntu20.04 --network bridge=br0 --graphics vnc --noautoconsole --print-xml > ubuntu-vm.xml
$ sudo virsh define ubuntu-vm.xml
$ sudo virsh start ubuntu-vm

This will start the Ubuntu 20.04 installation from the ISO image. You can connect to the VNC console to complete the installation.

After installation completes and the VM boots up, verify it is running:

$ sudo virsh list

The output will show the running VM:

 Id    Name                           State
----------------------------------------------------
 2     ubuntu-vm                      running

We have successfully created a KVM virtual machine using CLI tools!

Create a KVM Virtual Machine (GUI)

We can also use a GUI like Virt Manager to manage KVM VMs.

Install Virt Manager if you haven’t already:

$ sudo apt install virt-manager

Launch Virt Manager either from the command line or desktop environment.

Click on Create a new virtual machine to begin the New VM wizard.

Step through the wizard to define the VM resources, storage, network, etc.

For example, select import existing disk image, enter the path to the qcow2 image created earlier e.g. /var/lib/libvirt/images/ubuntu-20.qcow2.

Complete the remaining steps, review the summary, and click Finish to create the VM.

The VM should now be created and powered off. Right click on it and select Run to start it.

Connect to the VNC console to complete OS installation.

We have now created a KVM virtual machine using the graphical virt-manager tool. Using the GUI can help simplify managing multiple VMs.

Manage KVM Virtual Machines

Now we have KVM installed and VMs created, let’s go over managing the VMs.

List all VMs:

$ sudo virsh list --all

This will list all active and inactive VMs.

Start a VM:

$ sudo virsh start ubuntu-vm

Shutdown a VM:

$ sudo virsh shutdown ubuntu-vm

Force power off a VM:

$ sudo virsh destroy ubuntu-vm

Delete a VM:

$ sudo virsh undefine ubuntu-vm

This will delete the VM configuration, but won’t delete the disk image.

Suspend/resume a VM:

$ sudo virsh suspend ubuntu-vm
$ sudo virsh resume ubuntu-vm

Reboot a VM:

$ sudo virsh reboot ubuntu-vm

Connect to VNC console:

$ sudo virt-viewer ubuntu-vm

This will open a VNC window to interact with the VM’s graphical console.

VM status:

$ sudo virsh domstate ubuntu-vm

VM statistics:

$ sudo virsh domstats ubuntu-vm

This covers the basic VM management tasks with KVM. You can refer to the virsh man pages for more advanced management operations.

Optimizations and Best Practices

Here are some tips for optimizing KVM performance and efficiency:

  • Use the virtio drivers: Virtio drivers provide optimized I/O performance for virtual machines.
  • Allocate sufficient RAM: Ensure VMs have enough RAM to avoid swapping.
  • Use a fast storage backend: SSDs or NVMe drives provide better performance than traditional HDDs.
  • Enable CPU pinning: Pinning VMs to specific CPU cores can improve performance by reducing context switching.
  • Monitor VM performance: Regularly monitor VM performance to identify bottlenecks.
  • Keep the host system updated: Regularly update the host system to ensure you have the latest security patches and performance improvements.
  • Use a dedicated network interface: Using a dedicated network interface for your VMs can improve network performance.

Following best practices helps ensure your KVM infrastructure remains secure, stable and scalable.

Conclusion

We have installed KVM on Ubuntu 20.04/22.04, created VMs using CLI and Virt Manager, and covered managing and optimizing KVM.

KVM provides an open-source and cost-effective virtualization solution on Linux. With its excellent performance and wide adoption, it is a great hypervisor for running Linux guest VMs.

We encourage you to further explore KVM capabilities and build robust virtualized environments. This will allow you to consolidate servers, isolate services, and take advantage of powerful VM management features.

Alternative Solutions for Virtualization on Ubuntu

While KVM is a robust and widely used virtualization solution, other viable alternatives exist. Here are two such options, along with explanations and code examples where applicable:

1. Docker Containers:

Docker, while not a traditional hypervisor like KVM, offers a powerful and lightweight approach to virtualization through containerization. Instead of virtualizing the entire operating system, Docker packages applications and their dependencies into isolated containers that share the host OS kernel. This results in significantly reduced overhead, faster startup times, and improved resource utilization compared to KVM-based VMs.

  • Explanation: Docker containers offer application-level virtualization. Each container runs as an isolated process in userspace on the host operating system. Docker leverages the host OS kernel’s resource isolation features (namespaces and cgroups) to provide isolation. Because containers share the host kernel, they are much smaller and faster to start than full VMs. This makes them ideal for microservices architectures and continuous integration/continuous deployment (CI/CD) pipelines. Docker is a good alternative to KVM when you need to run multiple instances of an application, or when you want to deploy applications quickly and easily. Docker also simplifies dependency management by packaging all dependencies within the container.

  • Installation and Usage:

    # Install Docker
    sudo apt update
    sudo apt install docker.io
    
    # Start and enable Docker service
    sudo systemctl start docker
    sudo systemctl enable docker
    
    # Verify installation
    docker --version
    
    # Run a simple container (e.g., Ubuntu)
    docker run -it ubuntu bash

    This sequence installs Docker, starts the service, and runs an interactive Ubuntu container. Inside the container, you’ll have a shell prompt, allowing you to install software and run commands as if you were in a standalone Ubuntu environment, but sharing the host kernel.

  • Example Dockerfile (for creating custom containers):

    # Use an official Ubuntu base image
    FROM ubuntu:latest
    
    # Update the package list
    RUN apt-get update
    
    # Install some software
    RUN apt-get install -y nginx
    
    # Expose port 80
    EXPOSE 80
    
    # Start nginx when the container starts
    CMD ["nginx", "-g", "daemon off;"]

    This Dockerfile defines a container based on Ubuntu, installs Nginx web server, exposes port 80, and starts Nginx when the container launches. You can build and run this image with:

    docker build -t my-nginx-image .
    docker run -d -p 80:80 my-nginx-image

    This builds an image named my-nginx-image and then runs a container based on that image, mapping port 80 on the host to port 80 inside the container.

2. LXC/LXD (Linux Containers):

LXC (Linux Containers) and its successor LXD provide a system container virtualization solution that’s lighter weight than full VMs but offers more isolation than Docker. LXC/LXD creates containers that are more like lightweight virtual machines, each with its own private process space, filesystem, and network interface. While still sharing the host kernel, LXC/LXD containers offer stronger isolation than Docker, making them suitable for running entire operating systems or complex applications that require a more traditional OS environment.

  • Explanation: LXC/LXD leverages the same kernel features as Docker (namespaces and cgroups) but provides a more complete OS-level virtualization. Each container has its own root filesystem, user accounts, and system processes. This allows you to run different Linux distributions within containers on the same host, something that is not easily achievable with Docker. LXC/LXD is a good alternative to KVM when you need to run full Linux distributions, but you want to avoid the overhead of a full virtual machine. It’s often used for testing, development, and running legacy applications. LXD simplifies the management of LXC containers with a REST API and command-line tools.

  • Installation and Usage:

    # Install LXD
    sudo snap install lxd
    
    # Initialize LXD (follow the prompts)
    sudo lxd init
    
    # Launch a container (e.g., Ubuntu 20.04)
    lxc launch ubuntu:20.04 my-container
    
    # List containers
    lxc list
    
    # Get a shell inside the container
    lxc exec my-container bash

    This installs LXD via snap (a package manager developed by Canonical), initializes it, launches an Ubuntu 20.04 container named "my-container", and gives you a shell inside the container.

  • Configuration Example (profiles for resource limits):

    LXD uses profiles to manage container configuration. You can create profiles to limit resources like CPU and memory.

    # Create a new profile
    lxc profile create limited-profile
    
    # Edit the profile
    lxc profile edit limited-profile

    This opens a YAML editor. Add the following to limit CPU and memory:

    config:
      limits.cpu: "1"  # Limit to 1 CPU core
      limits.memory: 1GB # Limit to 1 GB of memory
    description: Limited resources profile
    name: limited-profile
    used_by: []

    Then apply the profile to a container:

    lxc profile apply my-container limited-profile

Both Docker and LXC/LXD offer compelling alternatives to KVM for specific use cases. Docker excels in application-level virtualization and microservices, while LXC/LXD provides a lighter-weight alternative to full VMs with stronger OS-level isolation. The choice depends on the specific requirements of your virtualization needs.