Thursday, March 15, 2018

Easy VMs in Ubuntu 17.10

Let's do some experimenting with QEUM/KVM Virtual Machines in Ubuntu.

I was, frankly, shocked at just how easy Linux VMs are to set up and manage.

Preparation

If the hardware supports hardware virtualization...

$ egrep -c '(vmx|svm)' /proc/cpuinfo 
2                // A result of '0' means no. '1' or higher means yes

...then reboot into BIOS and turn it on.


Creating the first VM:

Once virtualization is turned on, then from zero to fully operating is just three commands. The host is Ubuntu 17.10. The guest will also be 17.10, but that is merely because I lack imagination.

1) Install KVM, qemu, virt-manager and all the other tools you need. The are all dependencies of a single package:

$ sudo apt install uvtool

2) Download a cloud image of Ubuntu 17.10. Cloud images are headless - shell only. The download takes a few minutes (approximately  350 MB), so don't panic:

$ uvt-simplestreams-libvirt sync release=artful arch=amd64

3) Create and start VM Guest 'test1'

$ uvt-kvm create test1 release=artful



Starting, Stopping, Suspending, and Resuming the VM Guest from Host


$ virsh list              // Check status
 Id    Name                           State
----------------------------------------------------
 1     test1                          running

$ virsh suspend test1
Domain test1 suspended

$ virsh resume test1
Domain test1 resumed

$ virsh shutdown test1
Domain test1 is being shutdown

$ virsh list --all        // Use --all to show inactive VMs
 Id    Name                           State
----------------------------------------------------
 -     test1                          shut off

$ virsh start test1
Domain test1 started

$ virsh list
 Id    Name                           State
----------------------------------------------------
 2     test1                          running



Under the hood looking at storage


We didn't set up a any virtual storage, and we don't know where that Ubuntu Cloud image went. Let's take a moment and figure it out using virsh...

$ virsh dumpxml test2 | grep file
    <disk device="disk" type="file">
      <source file="/var/lib/uvtool/libvirt/images/test1.qcow"></source>
      <backingstore index="1" type="file">
        <source file="/var/lib/uvtool/libvirt/images/x-uvt-b64-Y29tLnVidW50dS5jbG91ZDpzZXJ2ZXI6MTcuMTA6YW1kNjQgMjAxODAzMTQ="></source>
    <disk device="disk" type="file">
      <source file="/var/lib/uvtool/libvirt/images/test1-ds.qcow"></source>
    </disk></backingstore>

There are the images for the virtual storage devices, and for the original cloud image ('backingstore') too. Looks like they are all in the same directory.

$ ls -l /var/lib/uvtool/libvirt/images/
total 1490572
-rw------- 1 libvirt-qemu kvm     458752 Mar 14 22:06 test1-ds.qcow
-rw------- 1 libvirt-qemu kvm  490471424 Mar 15 08:14 test1.qcow
-rw------- 1 libvirt-qemu kvm 1035468800 Mar 14 22:05 x-uvt-b64-Y29tLnVidW50dS5jbG91ZDpzZXJ2ZXI6MTcuMTA6YW1kNjQgMjAxODAzMTQ=

Aha. There's the cloud image is the third line - that's where it went! The actual VM Guest storage is the first and second lines - they are simply diffs from the original cloud image. Multiple Guests can base off the same cloud image, keeping storage tidy...and small.

Let's add another Guest VM and see how it changes.

$ uvt-kvm create test2 release=artful
$ ls -l /var/lib/uvtool/libvirt/images/
total 1491344
-rw------- 1 libvirt-qemu kvm     458752 Mar 14 22:06 test1-ds.qcow
-rw------- 1 libvirt-qemu kvm  490471424 Mar 15 08:29 test1.qcow
-rw------- 1 libvirt-qemu kvm     458752 Mar 15 08:34 test2-ds.qcow
-rw------- 1 libvirt-qemu kvm     393216 Mar 15 08:34 test2.qcow
-rw------- 1 libvirt-qemu kvm 1035468800 Mar 14 22:05 x-uvt-b64-Y29tLnVidW50dS5jbG91ZDpzZXJ2ZXI6MTcuMTA6YW1kNjQgMjAxODAzMTQ=

A whole fresh VM takes less than 1 MB. Of course, it will grow quickly once you start giving it work to do.

And here you can see how to destroy a VM Guest properly. The guest files are deleted, the cloud image is not.

$ uvt-kvm destroy test2
$ ls -l /var/lib/uvtool/libvirt/images/
total 1490572
-rw------- 1 libvirt-qemu kvm     458752 Mar 14 22:06 test1-ds.qcow
-rw------- 1 libvirt-qemu kvm  490471424 Mar 15 08:29 test1.qcow
-rw------- 1 libvirt-qemu kvm 1035468800 Mar 14 22:05 x-uvt-b64-Y29tLnVidW50dS5jbG91ZDpzZXJ2ZXI6MTcuMTA6YW1kNjQgMjAxODAzMTQ=


Securing VM Guest with a new admin account and SSH Keys

uvt-created guests start with the 'ubuntu' admin user, so you can start the process of customization without a lot of hassle. But they are insecure, so let's add our own admin user and delete that default fellow.

Step 1. On the HOST, login insecurely to the Guest

host$ uvt-kvm ssh test1

Step 2. On the GUEST, add the new admin user. Let's call her 'adminnnn', and let's make her part of the 'sudo' group (since she's an admin, of course). The 'adduser' command below asks a few questions, including a password. Give a password. We will need it once later to set up SSH keys, and --of course-- to use sudo in the Guest.

test1$ sudo adduser adminnnn --ingroup sudo

Step 3. Edit the SSH settings to briefly permit insecure login so we can place the ssh key. We will change this back in a later step. I use nano - you use whatever editor you wish.

test1$ sudo nano /etc/ssh/sshd_config

Make sure these settings are active:


     PubKey Authentication yes
     Password Authentication yes
     ChallengeResponseAuthentication no
     UsePAM yes
     (Remember to save your changes!)

Step 4. Restart SSH so the sshd config changes take effect, and logout from the 'ubuntu' user

test1$ sudo service sshd restart
test1$ exit

Step 5. Create an SSH key if you don't already have one. If you already have a key then use it, of course. Learn the IP address of the Guest. Copy the key across to the Guest. Login using the new key

host$ ssh-keygen
host$ uvt-kvm ip test1
192.168.122.249
host$ ssh-copy-id adminnnn@192.168.122.249
host$ ssh adminnnn@192.168.122.249

Step 6. Test adminnnn's new sudo powers. If they work then delete the 'ubuntu' user.

test1$ sudo apt update
test1$ sudo apt upgrade
test1$ sudo deluser ubuntu

Step 7. Tighten ssh to allow keys only. Finally, we will exit so the sshd changes take effect.

test1$ sudo nano /etc/ssh/sshd_config

Make sure these settings are active:



     PubKey Authentication yes
     Password Authentication no
     ChallengeResponseAuthentication no
     UsePAM no
     (Remember to save your changes!)

test1$ sudo service sshd restart
test1$ exit

...and that's all you need


Let's add a full Desktop Environment

In this case, let's add Lubuntu.

host$ ssh adminnnn@192.168.122.249

test1$ sudo apt install lubuntu-desktop --no-install-recommends
test1$ exit

A reboot is necessary for the new desktop to launch at startup. Let's use virt-viewer to watch the reboot process. We could also use remmina since we know the IP address.

host$ virt-viewer test1

test1$ sudo reboot

After reboot, the desktop should come up.


To eliminate the desktop, including another way to reboot:

host$ ssh adminnnn@192.168.122.249

test1$ sudo apt remove lubuntu-desktop
test1$ sudo apt autoremove
test1$ exit

host$ virsh reboot test1


Cleaning Up


It's poor practice to leave your system littered with old experiments. When finished playing, here's how to clean up. All of these commands, of course, are done on the HOST.

To delete just one Guest VM, but leave the VM Host software on your system:

$ uvt-kvm destroy test1

To delete the VM Host software from your system (Ubuntu), but leave guest Virtual Disks intact:

$ sudo apt remove uvtool
$ sudo apt autoremove

To delete any remaining Virtual Disks, including the cloud image(s) they are based upon.

sudo rm -r /var/lib/uvtool
References:
https://help.ubuntu.com/community/KVM
https://help.ubuntu.com/lts/serverguide/cloud-images-and-uvtool.html