By following this article to the end, you should be able to configure and use PXE and Kickstart server tools for Virtual Machine provisioning on KVM. KVM is an open source full virtualization solution for hardware architectures that support hardware virtualization. A library called libvirt provides a common API for managing KVM virtualization solution.

To create a fully automated installation of Virtual Machine on KVM, we need a network installation server that’s configured with TFTP, PXE, and a Kickstart file for initiating OS installation by booting from the network.

Preboot eXecution Environment (PXE) technology provides a mechanism for bootstrapping a computer using a network server. The computer where the operating system is installed should have a network interface that supports PXE, and the system firmware must enable PXE support.

The following list of services must be provided by the network boot infrastructure:

  • TFTP Server – Provides the boot images to start the installer, with the command-line options.
  • DHCP server – Provides initial client network configurations, and the location of TFTP server with a usable boot image
  • Kickstart and Media server – This can be HTTP, FTP, or NFS server to provide the installation media and a shared Kickstart file for OS installation.

PXE Booting Process

The following series of actions takes place when using PXE for automated OS installation.

  1. A client machine at boot, through its network interface card, sends a DHCPDISCOVER broadcast packet in the network with required PXE options
  2. Configured DHCP server on the network will respond with a DHCPOFFER. The offer contains the IP address the client will get, and information about location of the PXE server.
  3. The client then responds with a DHCPREQUEST – requesting for IP assignment
  4. DHCP server sends a DHCPACK, with this is the TFTP (Trivial FTP) server URL of a network boot loader
  5. Client downloads the boot file from TFTP server and loads it (pxelinux.0)
  6. The loaded boot loader gets configuration file and Kickstart files from TFTP and HTTP/FTP/NFS server respectively. The files instructs it how to download and start OS installer.
  7. The files are used to boot the client

Configuring the PXE Boot Environment

Our setup is based on these configuration options.

System typeHostnameIP Address
DHCP/TFTP/HTTP Serverbastion-server.kvmlab.net192.168.177.2
Kickstart serverbastion-server.kvmlab.net192.168.177.2
Virtual Machine deployed via PXEvm0.kvmlab.netAssigned by DHCP Server
Our Lab setup

KVM Hypervisor is required installed and configured on your host system. Check the guides in the following links for complete setup steps:

Step 1 – Create Virtual Network

A bridge used should not have DHCP function as this will be handled by a DHCP Server virtual machine that we’ll install. These operations are to be performed on your KVM hypervisor host.

Ensure bridge utility package is installed.

### RHEL Based systems ###
sudo yum -y install vim bridge-utils

### Debian Based systems ###
sudo apt update
sudo apt install vim bridge-utils

Create a new virtual network creation configuration file.

vim br-pxe-net.xml

Modify these contents. You can replace IP information and bridge name to your liking and paste them inside the file.

<network>
  <name>br-pxe</name>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='br-pxe' stp='on' delay='0'/>
  <ip address='192.168.177.1' netmask='255.255.255.0'>
  </ip>
</network>

Create a virtual network using this file file created; modify if need be:

$ sudo virsh net-define --file br-pxe-net.xml
Network br-pxe defined from br-pxe-net.xml

Enable automatic starting on the bridge created.

$ sudo virsh net-autostart br-pxe
Network br-pxe marked as autostarted

Then ensure the bridge interface is online

$ sudo virsh net-start br-pxe
Network br-pxe started

Confirm that the bridge is available and active:

$ sudo virsh net-list
 Name      State    Autostart   Persistent
--------------------------------------------
 br-pxe    active   yes         yes
 default   active   yes         yes

$ brctl show
bridge name	bridge id		STP enabled	interfaces
br-pxe		8000.525400d64edf	yes
virbr0		8000.525400929ef5	yes

OVS Bridge

If using Open vSwitch bridge instead of Linux bridge, network script configuration file will have contents similar to below

$ sudo vim /etc/sysconfig/network-scripts/ifcfg-br-pxe
DEVICE=br-pxe
BOOTPROTO=none
ONBOOT=yes
TYPE=OVSBridge
DEVICETYPE=ovs
USERCTL=yes
PEERDNS=yes
IPV6INIT=no
IPADDR=192.168.177.1
PREFIX=24

Start the interface and check IP configurations:

$ sudo ifup br-pxe
$ ip ad show dev br-pxe
12: br-pxe: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:d6:4e:df brd ff:ff:ff:ff:ff:ff
    inet 192.168.78.1/24 brd 192.168.78.255 scope global br-pxe
       valid_lft forever preferred_lft forever

Allowing nating using IPtables firewall:

sudo iptables -t nat -A POSTROUTING -o enp0s31f6 -s 192.168.78.1/24 -j MASQUERADE

Step 2 – Create Bastion Virtual Machine

Here we create a Virtual Machine that runs services to support network boot infrastructure.

  • Apache httpd web server
  • DHCP Server
  • PXE/TFTP services

Install libguestfs-tools package which provides virt-builder command line tool.

### RHEL Based systems ###
sudo yum -y install libguestfs-tools

### Fedora Linux systems ###
sudo dnf -y install guestfs-tools

### Debian Based systems ###
sudo apt -y install libguestfs-tools

List available OS templates:

sudo virt-builder -l

In this guide we’ll use Fedora template. Let’s create

sudo virt-builder fedora-38  --format qcow2 \
  --size 30G -o /var/lib/libvirt/images/kvm-bastion-server.qcow2 \
  --root-password password:StrongRootPassw0rd

Where:

  • fedora-38 is the template used to create a new virtual machine
  • /var/lib/libvirt/images/kvm-bastion-server.qcow2 is the path to VM qcow2 image
  • StrongRootPassw0rd is the root user password

Command execution output:

[   0.6] Downloading: http://builder.libguestfs.org/fedora-36.xz
############################################################################################################################################################################################### 100.0%############################################################################################################################################################################################### 100.0%
[  14.7] Planning how to build this image
[  14.7] Uncompressing
[  18.8] Resizing (using virt-resize) to expand the disk to 30.0G
[  42.7] Opening the new disk
[  47.2] Setting a random seed
[  47.2] Setting passwords
[  48.2] Finishing off
                   Output file: /var/lib/libvirt/images/kvm-bastion-server.qcow2
                   Output size: 30.0G
                 Output format: qcow2
            Total usable space: 30.0G
                    Free space: 28.9G (96%)

Create Virtual Machine from generated image.

Using Linux bridge:

sudo virt-install \
  --name kvm-bastion-server \
  --ram 2048 \
  --vcpus 2 \
  --disk path=/var/lib/libvirt/images/kvm-bastion-server.qcow2 \
  --os-type linux \
  --os-variant rhel8.0 \
  --network bridge=br-pxe \
  --graphics none \
  --serial pty \
  --console pty \
  --boot hd \
  --import