2.9. Configuring instances at boot time

Introduction

Users often want to do some configuration to their instances after booting. For example, you may want to install some packages, start services, or manage the instance using a Puppet or Chef server. When launching instances in an OpenStack cloud, there are two technologies that work together to support automated configuration of instances at boot time: user data and cloud-init.

User data

User data is the mechanism by which a user can pass information contained in a local file to an instance at launch time. The typical use case is to pass something like a shell script or a configuration file as user data.
User data is sent using the --user-data /path/to/filename option when calling nova boot. The following example creates a text file and then send the contents of that file as user data to the instance.
$ echo "This is some text" > myfile.txt
$ nova boot --user-data ./myfile.txt --image myimage myinstance
The instance can retrieve user data by querying the metadata service through either the OpenStack metadata API or the EC2 compatibility API:
$ curl http://169.254.169.254/2009-04-04/user-data
This is some text
$ curl http://169.254.169.254/openstack/2012-08-10/user_data
This is some text
Note that the Compute service treats user data as a blob. While the example above used a text file, user data can be in any format.

CloudInit

To do something useful with the user data, the virtual machine image must be configured to run a service on boot that retrieves the user data from the metadata service and take some action based on the contents of the data. The cloud-init package was designed to do exactly this. In particular, cloud-init is compatible with the Compute metadata service as well as the Compute config drive.
Note that cloud-init is not an OpenStack technology. Rather, it is a package that is designed to support multiple cloud providers, so that the same virtual machine image can be used in different clouds without modification. CloudInit is an open source project, and the source code is available on Launchpad.
We recommend installing cloud-init on images that you create to simplify the task of configuring your instances on boot. Even if you do not wish to use user data to configure instance behavior at boot time, cloud-init provides useful functionality such as copying the public key to an account .
If you do not have cloud-init installed, you will need to manually configure your image to retrieve the public key from the metadata service on boot and copy it to the appropriate account.

CloudInit supported formats and documentation

We recommend taking a look at the cloud-init doc/userdata.txt file the examples directory for details on how to use cloud-init. We provide some basic examples here.
CloudInit supports several different input formats for user data. We briefly discuss two commonly used formats:
  • Shell scripts (starts with #!)
  • Cloud config files (starts with #cloud-config)

Running a shell script on boot

Assuming you have cloud-init installed, the simplest way to configure an instance on boot is to pass a shell script as user data. The shell file must begin with #! in order for cloud-init to recognize it as a shell script. Here's an example of a script that creates an account called clouduser.
#!/bin/bash
adduser --disabled-password --gecos "" clouduser
Sending a shell script as user data has a similar effect to writing an /etc/rc.local script: it will be executed very late in the boot sequence as root.

Cloud-config format

CloudInit supports a YAML-based config format that allows the user to configure a large number of options on a system. User data that begins with #cloud-config will be interpreted by cloud-init as cloud-config format.

Example: Setting hostname

This cloud-init user data example sets the hostname and the FQDN, as well as updating /etc/hosts on the instance:
#cloud-config
hostname: mynode
fqdn: mynode.example.com
manage_etc_hosts: true

Example: Configuring instances with Puppet

This cloud-init user data example, based on doc/examples/cloud-config-puppet.txt, would configure the instance to contact a Puppet server at puppetmaster.example.org and verify its identity using a certificate.
#cloud-config
puppet:
 conf:
   agent:
     server: "puppetmaster.example.org"
   ca_cert: |
     -----BEGIN CERTIFICATE-----
     MIICCTCCAXKgAwIBAgIBATANBgkqhkiG9w0BAQUFADANMQswCQYDVQQDDAJjYTAe
     Fw0xMDAyMTUxNzI5MjFaFw0xNTAyMTQxNzI5MjFaMA0xCzAJBgNVBAMMAmNhMIGf
     MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCu7Q40sm47/E1Pf+r8AYb/V/FWGPgc
     b014OmNoX7dgCxTDvps/h8Vw555PdAFsW5+QhsGr31IJNI3kSYprFQcYf7A8tNWu
     1MASW2CfaEiOEi9F1R3R4Qlz4ix+iNoHiUDTjazw/tZwEdxaQXQVLwgTGRwVa+aA
     qbutJKi93MILLwIDAQABo3kwdzA4BglghkgBhvhCAQ0EKxYpUHVwcGV0IFJ1Ynkv
     T3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwDwYDVR0TAQH/BAUwAwEB/zAd
     BgNVHQ4EFgQUu4+jHB+GYE5Vxo+ol1OAhevspjAwCwYDVR0PBAQDAgEGMA0GCSqG
     SIb3DQEBBQUAA4GBAH/rxlUIjwNb3n7TXJcDJ6MMHUlwjr03BDJXKb34Ulndkpaf
     +GAlzPXWa7bO908M9I8RnPfvtKnteLbvgTK+h+zX1XCty+S2EQWk29i2AdoqOTxb
     hppiGMp0tT5Havu4aceCXiy2crVcudj3NFciy8X66SoECemW9UYDCb9T5D0d
     -----END CERTIFICATE-----