A word from our sponsors

Creating a KVM Virtual Machine

  • Copy a virtual machine image from a virtual machine template:

    root@host:~# cp <path to vm template file> <path to new vm image file>

    or create a new image file:

    root@host:~# qemu-img create -f <type> -o <options> <path to new vm image file> <size>

    E.g. a QCOW2 image file with a size of 2GB:

    root@host:~# qemu-img create -f qcow2 -o lazy_refcounts=on slave1.qcow2 2G
  • Create a virtual machine description file:

    vm-template.xml
    <domain type='kvm'>
      <name>VMNAME</name>
      <memory unit='KiB'>MEMORY</memory>
      <vcpu placement='static'>CPUS</vcpu>
      <os>
        <type arch='x86_64' machine='pc-i440fx-2.1'>hvm</type>
        <boot dev='hd'/>
      </os>
      <features>
        <acpi/>
        <apic/>
        <pae/>
      </features>
      <cpu mode='custom' match='exact'/>
      <clock offset='utc'>
        <timer name='rtc' tickpolicy='catchup'/>
        <timer name='pit' tickpolicy='delay'/>
        <timer name='hpet' present='no'/>
      </clock>
      <on_poweroff>destroy</on_poweroff>
      <on_reboot>restart</on_reboot>
      <on_crash>restart</on_crash>
      <pm>
        <suspend-to-mem enabled='no'/>
        <suspend-to-disk enabled='no'/>
      </pm>
      <devices>
        <emulator>/usr/bin/kvm</emulator>
        <disk type='file' device='disk'>
          <driver name='qemu' type='qcow2'/>
          <source file='PATHTOVMIMAGE'/>
          <target dev='vda' bus='virtio'/>
          <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
        </disk>
        <controller type='pci' index='0' model='pci-root'/>
        <controller type='usb' index='0'>
          <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
        </controller>
        <controller type='virtio-serial' index='0'>
          <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
        </controller>
        <interface type='network'>
          <source network='NETWORK'/>
          <model type='virtio'/>
          <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
        </interface>
        <console type='pty'>
          <target type='virtio' port='0'/>
        </console>
        <input type='mouse' bus='ps2'/>
        <input type='keyboard' bus='ps2'/>
        <graphics type='vnc' port='-1' autoport='yes'/>
        <video>
          <model type='cirrus' vram='9216' heads='1'/>
          <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
        </video>
        <memballoon model='virtio'>
          <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
        </memballoon>
      </devices>
    </domain>

    Replace VMNAME, MEMORY, CPUS, PATHTOVMIMAGE and NETWORK, with the appropriate values and save the virtual machine description file as <VMNAME>.xml.

    With the virtual machine description file, define a virtual machine:

    root@host:~# virsh define <VMNAME>.xml
    root@host:~# virsh autostart <VMNAME>
  • Networking:

    • Private bridge, with access to networks outside of the KVM host for the virtual machines via NAT on the KVM host:

      • Create a virtual network description file:

        network-template.xml
        <network connections='1'>
          <name>default</name>
          <forward mode='nat'>
            <nat>
              <port start='1024' end='65535'/>
            </nat>
          </forward>
          <bridge name='virbr0' stp='on' delay='0'/>
          <ip address='192.168.122.1' netmask='255.255.255.0'>
            <dhcp>
              <range start='192.168.122.2' end='192.168.122.254'/>
            </dhcp>
          </ip>
        </network>

        Replace the IP addresses and the netmask with the appropriate values for the network environment and save the virtual network description file as network-default.xml

        With the virtual network description file, define a virtual network:

        root@host:~# virsh net-define network-default.xml
        root@host:~# virsh net-autostart default
        root@host:~# virsh autostart default
      • Optional: Add entries for each virtual machine to the file /etc/hosts on the KVM server if network access from the KVM server to the virtual machine is required.

      • Gather the MAC address for each virtual machine interface:

        root@host:~# virsh dumpxml <VMNAME> | egrep "<mac "
              <mac address='52:54:00:5a:3d:f0'/>
      • For each virtual machine insert a static entry to the virtual network. This will be used to map each virtual machines MAC address to a IP address via DHCP:

        root@host:~# virsh net-update default add ip-dhcp-host "<host mac='MAC' name='HOSTNAME' ip='IPADDRESS' />" --live --config

        Replace MAC, HOSTNAME and IPADDRESS with the appropriate values for each virtual machine.

      • Restart the libvirt service on the KVM host:

        root@host:~# systemctl restart libvirtd.service

        This will have created a virtual network in the form of a Linux bridge:

        root@host:~# brctl show
        bridge name     bridge id           STP enabled     interfaces
        virbr0          8000.fe54005a3df0   yes

        It will also have inserted appropriate IPtables NAT rules into the FORWARD chain:

        root@host:~# iptables -nL
        [...]
        Chain FORWARD (policy DROP)
        target     prot opt source               destination         
        ACCEPT     all  --  0.0.0.0/0            192.168.122.0/24     ctstate RELATED,ESTABLISHED
        ACCEPT     all  --  192.168.122.0/24     0.0.0.0/0           
        ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
        REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
        REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
        [...]

        In order to forward packets from and to the virtual machines, IP forwarding must also be enabled on the KVM host:

        root@host:~# sysctl net.ipv4.ip_forward 
        net.ipv4.ip_forward = 1
  • Start the virtual machine:

    root@host:~# virsh start <VMNAME>

    If the virtual machine was copied from a template and virtual machine networking is done with a private bridge and NAT, the hostname inside the virtual machine is currently still the wrong one in order to match the definition for a successful DHCP request. On the first boot of the virtual machine, the hostname needs to be changed via a login on the virtual machine console. See Debian - Necessary Changes After Cloning A System for the necessary steps. Afterwards the virtual machine should get an IP address assigned via DHCP.

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website. More information about cookies