Booting cloud images with libvirt

Most major distributions now provide “cloud-enabled” images designed
for use in cloud environments like OpenStack and AWS. These images
are usually differentiated by (a) being relatively small, and (b) running
cloud-init at boot to perform initial system configuration tasks
using metadata provided by the cloud environment.

Because of their small size and support for automatic configuration
(including such useful tasks as provisioning ssh keys), these images
are attractive for use outside of a cloud environment.
Unfortunately, when people first try to boot them they are met with
frustration as first the image takes forever to boot as it tries to
contact a non-existent metadata service, and then when it finally does
boot they are unable to log in because the images typically only
support key-based login.

Fortunately, there are ways to work around these issues. In addition
to working with various network-accessible metadata services,
cloud-init is also able to read configuration information from an
attached [virtual] CD-ROM device. This is known as a “configuration
drive”, and it is relatively easy to create.

For this purpose, the simplest solution is use cloud-init’s “no
cloud” data source. For this, we need to create an ISO filesystem
creating two files, meta-data and (optionally) user-data.

The meta-data file

The meta-data file is effectively a YAML version of the data
typically available in the EC2 metadata service, and will look
something like this:

instance-id: my-instance-id
local-hostname: my-host-name

The instance-id key is required. You can also include SSH public
keys in this file, like this:

You will see examples that place ssh keys in the user-data file
instead, but I believe this is the wrong solution, since it forces you
to use a “cloud-config” format user-data file. Putting ssh keys
into the meta-data provides you more flexibility with your
user-data content.

The user-data file

The user-data can be any of the various formats supported by
cloud-init. For example, it could simply be a shell script: