In EC2 and OpenStack cloud environments user data can be passed to the cloud instance to customize the cloud instance on the first boot. But what if your virtual machine doesn’t run in the cloud environment? In this article we’re going to configure our virtual machines with user data regardless if they’re running in the cloud or not.
Introducing Cloud-Init
Cloud-Init is a tool that handles early initialization of a cloud instance. The cloud-init
RPM package should be installed on the disk image which the cloud instance is going to boot up from. The package installs init scripts into /etc/rc.d/init.d
that makes Cloud-Init run early during the system initialization. Cloud-Init obtains user data passed to it by the cloud software and executes them. User data contains a set of configuration tasks for the cloud instance. For example, Cloud-Init can update machine’s hostname, configure /etc/hosts
, create users, configure SSH authorized keys, resize filesystems, manage disk mounts, run user-defined scripts and
much more.
Even if you’re not running your virtual machines in the cloud environment it’s worth it to deploy Cloud-Init.
Every cloud software comes with its own mechanism of how to pass the user data to the cloud instance. For example, EC2 provides a magic IP from which the instance can download its user data. OpenStack cloud attaches a special config drive to the cloud instance containing the user data to be consumed by Clout-Init. In order to pass the user data to our virtual machine let’s go the OpenStack way and assemble a minimum config drive.
Config drive assembly
First, we’re going to prepare the following file structure for our config drive:
|
|
Start by creating directories and the latest
symbolic link like this:
|
|
Next create a minimum metadata file required by Cloud-Init. I’m using a fully qualified domain name of the virtual machine as its UUID:
|
|
Cloud-Init supports many
formats for scripts within user data. One of the most popular formats is the cloud-config file format. Let’s create a cloud-config script that adds our SSH public key to the authorized keys for the user root
on the virtual machine. We can then login into the virtual machine as user root without using a password. If you don’t have a public-private SSH key pair you can quickly generate it using ssh-keygen
command:
|
|
Now create a user_data
file with the configuration instructions for Cloud-Init. In the following code block replace the value of the ssh-authorized-keys
field with the content of your generated mykey.pub
file:
|
|
The file structure for our config drive is ready. Let’s generate an ext2 filesystem and copy the files to it. The virt-make-fs
utility from the libguestfs-tools
package can help us with that:
|
|
In order for Cloud-Init to detect the attached drive as config drive the filesystem on the config drive needs to be labeled config-2
. You can use e2label
command from the e2fsprogs
package to label your config drive:
|
|
Cloud-Init in action
On my Linux host I’m running
libvirt to ease the management of virtual machines. You can install it by running sudo yum install libvirt
. There is a handy command-line utility virsh
which comes with libvirt in the extra package libvirt-client
.
Let’s create a virtual machine with the config drive attached. As a virtual machine boot image I’m using a CentOS-6 image from
cloud.centos.org which comes with Cloud-Init built in. Make sure that your virtual machine boot image has Cloud-Init installed. Following is a virtual machine definition file for the CentoOS-6 virtual machine. You might need to change the location of the disk image files and save it as CentOS-6.xml
:
|
|
Okay, everything is ready, let’s launch our Cloud-Init enabled CentOS-6 virtual machine:
|
|
If everything went fine you can watch the console output of the booting virtual machine at /tmp/CentOS-6.log
. Cloud-Init will print out the IP address obtained by the virtual machine (192.168.122.165 in my case) where we can login as root using the generated private key:
|
|
Congratulations, your virtual machine has just been configured by Cloud-Init the same way as any other virtual machine running in the cloud environment.