Onur Yasarlar
Search…
How to Install KVM on CentOS 7/8 and Ubuntu 18/20

Getting Started

I really like testing new things in my home lab but I also often break things. I am really bored with installing my home lab over and over again so I decided to create a series of posts to show how I automated my home lab provisioning. There are tons of writings on how to install KVM on various operating systems and I ensure you what I implemented here is no magic or different than what others already documented. I just wanted to keep it in an Ansible module under my own GitHub repository and refer to it if I need some time in the future. I will also mention here how I like to structure my Ansible roles and my habits while I am automating things.
Special thanks to Jeff Geerling. I learned a lot from his work while I am writing my own Ansible roles
You can find my Ansible role in Ansible Galaxy here.
I usually test things under CentOS but after Red Hat's recent announcement of converting CentOS into a beta version of RHEL, I decided to give it a try with Ubuntu and added Ubuntu support to this role recently. The role covers operating systems below but I can add more in the future:
  • CentOS 7
  • CentOS 8
  • Ubuntu 18.x
  • Ubuntu 20.x

Prerequisites

I usually prefer to have a separate prerequisite play and include it in my main.yml. I start checking if the role is being run for the operating systems that I tested. Here I added another check and verified if the CPU of the server supports virtualization and it is indeed 64-bit.
tasks/prereq.yaml
1
---
2
- name: Setting OS version fact
3
set_fact:
4
osversion: "{{ ansible_distribution | lower }}{{ ansible_distribution_major_version }}"
5
6
- name: Check OS version
7
fail:
8
msg: "OS Version( {{ ansible_distribution }}{{ ansible_distribution_major_version }} ) is not certified for the role"
9
when:
10
- osversion != "ubuntu20"
11
- osversion != "ubuntu18"
12
- osversion != "centos7"
13
- osversion != "centos8"
14
15
- name: Check CPU Virtualization Support
16
shell:
17
cmd: "egrep -c '(vmx|svm)' /proc/cpuinfo"
18
args:
19
warn: no
20
changed_when: no
21
register: cpuinfo_output
22
tags: ['skip_ansible_lint']
23
24
- name: Check CPU Virtualization Support
25
fail:
26
msg: "CPU does not support virtualization"
27
when:
28
- cpuinfo_output.stdout == "0"
29
30
- name: Check if your processor is 64-bit
31
shell:
32
cmd: "egrep -c ' lm ' /proc/cpuinfo"
33
args:
34
warn: no
35
changed_when: no
36
register: bitinfo_output
37
tags: ['skip_ansible_lint']
38
39
- name: Check if your processor is 64-bit
40
fail:
41
msg: "CPU is not 64-bit"
42
when:
43
- bitinfo_output.stdout == "0"
Copied!
So now we can start actual work. Let me first introduce you the vars/main.yml file so you can understand how I structure the global variables I will use in the tasks.
First of all, you will need to decide whether you will use an existing user for virtualization administration. You can for sure go with the root user, but I prefer to keep my own user. Here I define a user with admin user name and set its password to passw0rd so you can feel free to change it. The remaining variables are actually the packages required by each operating system. I could add them in separate variable files but since the number of variables is not that much, I decided to keep them all in a single variable file.
vars/main.yml
1
---
2
use_libvirt_user: yes
3
libvirt_user: "admin"
4
libvirt_user_passwd: "passw0rd"
5
6
libvirt_packages:
7
centos7:
8
- qemu-kvm
9
- libvirt
10
- libvirt-python
11
- libguestfs-tools
12
- virt-install
13
- virt-top
14
- virt-manager
15
centos8:
16
- '@virt'
17
- libguestfs-tools
18
- virt-top
19
- virt-manager
20
ubuntu18:
21
- qemu-kvm
22
- libvirt-daemon-system
23
- libvirt-clients
24
- bridge-utils
25
- virt-manager
26
ubuntu20:
27
- qemu-kvm
28
- libvirt-daemon-system
29
- libvirt-clients
30
- bridge-utils
31
- virt-manager
Copied!

Installation on CentOS 7/8

The remaining of this section is no magic. We will just install the required packages and add our non-root user to the required libvirt groups if we opted to use a non-root user in the variable file.
tasks/centos.yaml
1
- name: Setting OS version fact
2
set_fact:
3
osversion: "{{ ansible_distribution | lower }}{{ ansible_distribution_major_version }}"
4
5
- name: Install yum-utils
6
yum:
7
name: yum-utils
8
state: present
9
10
- name: Install Libvirt Packages
11
yum:
12
name: "{{ libvirt_packages[osversion] }}"
13
state: present
14
15
- name: Add libvirt non-root user
16
user:
17
name: "{{ libvirt_user }}"
18
shell: /bin/bash
19
groups: libvirt
20
append: yes
21
password: "{{ libvirt_user_passwd | password_hash('sha512') }}"
22
update_password: "on_create"
23
when: use_libvirt_user | bool
24
25
- name: Enable and start libvirt service
26
service:
27
name: libvirtd
28
state: started
29
enabled: yes
Copied!

Installation on Ubuntu 18.x / 20.x

The remaining of this section is no magic. We will just install the required packages and add our non-root user to the required libvirt groups if we opted to use a non-root user in the variable file.
tasks/ubuntu.yaml
1
- name: Setting OS version fact
2
set_fact:
3
osversion: "{{ ansible_distribution | lower }}{{ ansible_distribution_major_version }}"
4
5
- name: Install yum-utils
6
yum:
7
name: yum-utils
8
state: present
9
10
- name: Install Libvirt Packages
11
yum:
12
name: "{{ libvirt_packages[osversion] }}"
13
state: present
14
15
- name: Add libvirt non-root user
16
user:
17
name: "{{ libvirt_user }}"
18
shell: /bin/bash
19
groups: libvirt
20
append: yes
21
password: "{{ libvirt_user_passwd | password_hash('sha512') }}"
22
update_password: "on_create"
23
when: use_libvirt_user | bool
24
25
- name: Enable and start libvirt service
26
service:
27
name: libvirtd
28
state: started
29
enabled: yes
Copied!

Putting things together

Let me also show how all above put together in the main.yml. I tend to keep main.yml as simple as possible and perform tasks under their dedicated plays.
tasks/main.yml
1
---
2
- name: CPU support checks
3
include_tasks: prereq.yaml
4
5
- name: Install and Configure for CentOS
6
include_tasks: centos.yaml
7
when: ansible_distribution == "CentOS"
8
9
- name: Install and Configure for Ubuntu
10
include_tasks: ubuntu.yaml
11
when: ansible_distribution == "Ubuntu"
Copied!
So we are ready to call this role if we want to install KVM on top of CentOS 7/8 or Ubuntu 18.x/20.x
It is important to run this module as root. Otherwise, it will not be able to install packages and will eventually fail.