Managing KVM with Mist.io

Introduction

This guide will help you setup KVM on an Ubuntu 14 server, add it to Mist.io and use it to manage the VMs. Mist.io offers:
1) Listing existing VMs and performing actions including reboot, start destroy, shutdown, resume, suspend and undefine
2) Deploying new VMs using disk images, iso images, or using the preferred way of cloudinit based images. 
3) Connecting with ssh through mist.io web terminal. If the VMs have public ips then mist.io can connect through them. If the VMs have only private ips, then we can still be able to connect through the  VPN functionality that is available through the mist.io Saas - https://mist.io

Launching a new KVM server

Let's begin by launching an Ubuntu 14.04 server. This example uses a bare metal server on  packet.net, which offers the ability to launch bare metal servers through their API. We bought a server with 4 cores and 32GB RAM. Packet.net also gives us the choice to purchase a public net with 4 ip addresses, we'll buy one and make sure they are assigned to the KVM server in order to be used by the VMs. If you already have a KVM hypervisor up and running, skip on the "How to create VMs", section below.

Deploying a new VM on packet.net through the mist.io wizard.


Packet.net's network dashboard for assigning an ipv4 block. 

The following command will install KVM on Ubuntu 14. There's a good guide on  https://help.ubuntu.com/community/KVM/Installation on how to install KVM on Ubuntu. 

root@kvm-dbg-002:~# apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils uml-utilities genisoimage wget vim -y && apt-get update ; apt-get -y upgrade
The package  genisoimage is required for the cloudinit based images that we'll use. We will also need uml-utilities plus we'll install some utilities like wget and vim.
After installing KVM, if we runrun virsh list, we should see no VMs running, as expected. 
root@kvm-dbg-002:~# virsh list
Id    Name                           State 
----------------------------------------------------

Adding KVM to Mist.io

To add a KVM hypervisor to Mist.io click on Add Cloud and fill out the form as shown below

If you're having trouble, you can find more info on  http://docs.mist.io/article/24-adding-kvm

Launching VMs

There are two ways to launch a new VM:
1) Creating  a VM from an existing disk image (.qcow, .qcow2, .raw or .img). This will copy the disk image, resize it and try to start it. If the disk image is cloudinit based, you can specify an ssh key (and/or a cloudinit script). Major linux distros ship their cloudinit based images so you can download the images that interest you, put them on /var/lib/libvirt/images and deploy VMs through them (if you specify ssh key and/or cloudinit script, they will be deployed) 
If you're not familiar with cloudinit you can have a look at  https://cloudinit.readthedocs.org/en/latest/. It is the defacto way of handling the initialization of a Linux server (on KVM, OpenStack and other cloud environments). The cloud images are ready to use and are usually not very big (eg Debian 8.2.0 amd qcow2 image is 500MB.
You can also specify and use one of your images, but we suggest starting with a cloudinit based image.
We've tested these following cloudinit images:

More cloudinit based images can be found on  http://docs.openstack.org/image-guide/obtain-images.html

Cloudinit based images -compared to local images (netiso or normal ISOs)- are ready to use, so no extra installation or configuration is required.
The VM will be created and the SSH key will automatically be deployed (plus the cloudinit script will cofigure the VM, if it is specified). If KVM can assign public IPs to newly created VMs, Mist.io will be able to connect to it through SSH and the web terminal will be enabled. If it only assigns private IPs, then Mist.i won't be able to connect, however you can connect through the KVM server (arp -an will show it's private ip address so you can SSH with the key you have deployed). If you're using the Saas version of mist.io - https://mist.io - you can use the  VPN functionality to connect to private ips. 
2)  Creating a VM from an .iso file: this will create the configuration that KVM needs, create the disk image and will try to start the VM. VNC is going to be added soon but is not available currently, so you need to use virt-viewer to access the machine

Launching Linux VMs

1) Download a cloudinit-based image to use, and place it on /var/lib/libvirt/images/
root@kvm-reload2:~# cd /var/lib/libvirt/images/
root@kvm-reload2:/var/lib/libvirt/images# wget http://cloud-images.ubuntu.com/releases/14.04.4/14.04.4/ubuntu-14.04-server-cloudimg-amd64-disk1.img
	

make sure genisoimage tool is available on the KVM server. If not install it (apt-get install genisoimage -y # for Debian based OS)

3) Launch a new VM through Mist.io. This will take the default network settings of KVM, which is a private ip (192.168.122.1-254 range), as we haven't configured anything network related.  
On the Machines section, click on Create to launch the wizard and select the disk from the images drop down list, set name/size and choose an SSH key. This key will be deployed on the server. Optionally you can paste a cloudinit script (to install specific users, packages etc) but this is not mandatory.

Creating a VM through mist.io on a cloudinit based Ubuntu image, deploying an ssh key and running a cloudinit script

Since the IP is private, Mist.io won't be able to connect, however you can connect through the KVM server. Run the command arp -an to see the IP address of the created VM, so you can ssh with the key you have deployed to confirm that the VM has been created as requested.
The MAC address of the created VM is included on file /etc/libvirt/qemu/VM_name.xml which is the configuration file for VM_name.
root@kvm-reload2:/var/lib/libvirt/libcloud/proto# arp -an
? (192.168.122.85) at 52:54:00:ab:a0:c8 [ether] on eth0
root@kvm-reload2:/var/lib/libvirt/libcloud/proto# ssh ubuntu@192.168.122.85 -i /tmp/key

ubuntu@first-ubuntu-vm:~$ ls /
 bin  boot  dev  etc  home  initrd.img  lib  lib64  lost+found  media  mnt  OK  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  vmlinuz 

ubuntu@first-ubuntu-vm:~$ ping mist.io 
PING mist.io (54.67.73.187) 56(84) bytes of data. 
64 bytes from mist.io (54.67.73.187): icmp_seq=1 ttl=51 time=77.5 ms 
64 bytes from mist.io (54.67.73.187): icmp_seq=2 ttl=51 time=77.6 ms 

ubuntu@first-ubuntu-vm:~$ sudo su 
root@first-ubuntu-vm:/home/ubuntu#
	
The official Ubuntu cloudinit image creates the user ubuntu and sets passwordless sudo. We just made sure we can connect with the SSH key specified, the VM has gotten a private ip and has access to the net. Also the cloudinit script has run, and file /OK has been created.

Connecting to VMs that only have private ips through mist.io VPN

If you're using the Saas version of mist.io - https://mist.io - you can create a VPN tunnel on the KVM server and thus be able to probe/ssh/run scripts to the VMs no matter that they have only private ips. Enter the mist.io add VPN tunnel page and make sure you specify the CIDR or CIDRS that the VMs will be part of (example 192.168.122.0/24 in our case). Run the command on the VPN server, to setup the tunnel. More details can be on the VPN page. If the tunnel is setup correctly you will be able to start the ssh web shell on the VMs, that are now accessible to mist.io through the tunnel

Setting up the tunnel

Mist.io can see the private ip of the VM

...and we can initiate the web shell

Setting up KVM to provide public IPs to the VMs

Let's see how the network is configured
root@kvm-reload2:/var/lib/libvirt/libcloud/proto# vi /etc/libvirt/qemu/networks/default.xml
<network>
  <name>default</name>
  <bridge name="eth0"/>
  <forward/>
  <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>
KVM out of the box creates a default network for the VMs, and serves DHCP range 192.168.122.1-192.168.122.254, through a gateway of 192.168.122.1 for interface eth0. We can see that ifconfig shows eth0 has indeed the IP 192.168.122.1
eth0    Link encap:Ethernet  HWaddr fe:54:00:46:1d:2c
          inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:174 errors:0 dropped:0 overruns:0 frame:0
          TX packets:161 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:19791 (19.7 KB)  TX bytes:39905 (39.9 KB)
Lets change this to reflect a public network . The network setting vary per hypervisor and provider. In this case we have the public IPs 147.75.194.213 to 147.75.194.215 and the IP address we'll use for our bridge interface is 147.75.194.212 . The bridge interface will forward traffic to the interface eth0, which is the public interface our server has. Let's set this using the command virsh net-edit default
root@kvm-reload2:/var/lib/libvirt/libcloud/proto# virsh net-edit default
<network>
  <name>default</name>
  <uuid>3ed08eff-759a-49ac-9f10-ef9c72f8fc0a</uuid>
  <forward dev='eth0' mode='route'>
    <interface dev='eth0'/>
  </forward>
  <bridge name='br0' stp='on' delay='0'/>
  <mac address='52:54:00:37:96:0d'/>
  <ip address='147.75.194.212' netmask='255.255.255.0'>
    <dhcp>
      <range start='147.75.194.213' end='147.75.194.215'/>
    </dhcp>
  </ip>
</network>
Note that the uuid has to be the same as the one that was auto-generated for us by KVM, otherwise if we provide another one, or omit it, we will get prompted that the operation has failed. 
We'll specify the KVM default network to supply a dhcp pool of 147.75.194.213 to 147.75.194.215. The VMs will use 147.75.194.212 as their gateway ip which is the bridge interface of the KVM server, forwarding traffic to the eth0 interface.
We'll place the settings on /etc/rc.local to take effect once the system is rebooted.
brctl addbr br0 
ifconfig br0 147.75.194.212 netmask 255.255.255.0 up
tunctl -b -u root -t qtap0
brctl addif br0 qtap0
ifconfig qtap0 up 0.0.0.0 promisc
route add -host 147.75.194.213 dev br0
route add -host 147.75.194.214 dev br0
route add -host 147.75.194.215 dev br0
/etc/init.d/libvirt-bin restart
Then we reboot the server for these settings to take effect. After it goes up we check that br0 interface is loaded 
root@kvm-dbg-002:~# ifconfig br0
br0       Link encap:Ethernet  HWaddr 52:54:00:37:96:0d
          inet addr:147.75.194.212  Bcast:147.75.194.255  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
brctl command shows the bridge created
root@kvm-dbg-002:~# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.52540037960d yes br0-nic
Now let's create a VM. Using the wizard, we specify name, the cloudinit image, size, specs, ssh key and optionally a cloudinit script. 

After just 1-2 minutes the VM is created, gets one of the available public IPs and Mist.io can connect to it, thus it appears on the listing with the uptime icon. We can also use the web shell. 

Using the web shell on the newly created VM, after it has taken a public IP
If we open the logs we can see the DHCP request made by the VM and the IP it takes
==> /var/log/syslog <==
Jan 28 11:49:30 kvm-dbg-002 dnsmasq-dhcp[1940]: DHCPDISCOVER(br0) 52:54:00:89:ef:b1 
Jan 28 11:49:30 kvm-dbg-002 dnsmasq-dhcp[1940]: DHCPOFFER(br0) 147.75.194.215 52:54:00:89:ef:b1 
Jan 28 11:49:30 kvm-dbg-002 dnsmasq-dhcp[1940]: DHCPREQUEST(br0) 147.75.194.215 52:54:00:89:ef:b1 
Jan 28 11:49:30 kvm-dbg-002 dnsmasq-dhcp[1940]: DHCPACK(br0) 147.75.194.215 52:54:00:89:ef:b1 ubuntu
When the dhcp addresses are finished, we see a 'no address available' message on the logs, and the VM will not be able to get an ip on the default network. On our example we have 3 ip addresses available, so the forth VM that is created and started is requesting an ip address but can't take any since they are - 3 ip addresses are available 
==> /var/log/syslog <==
Feb  8 06:49:23 kvmi dnsmasq-dhcp[1947]: DHCPDISCOVER(br0) 52:54:00:3f:43:67 no address available
Finally, is is a good idea to configure /etc/rc.local so that the VMs are started when the KVM server is rebooted.  Example
virsh start centosVM.mist.io
virsh start ubuntu-server
		

Run actions on existing VMS

You can run the following actions on VMs: shutdown, reboot, destroy, undefine (destroy and remove XML configuration file), suspend, resume and start. 

Viewing the configuration of a VM

There is a quick way to view the VM configuration through the full metadata list on the VM page.

Still need help? Contact Us Contact Us