Running commands during boot using cloud-init

When bootstrapping a new server or instance, the first boot is often very different from all the other boots the instance will experience in its life, and most often we want some commands to be executed very early or very late in the boot process. For example, let's say our cloud instance is launched with an attached block storage. We might want to format this storage space and be sure it's mounted on the host, but while we always want the disk to mount, we probably don't want it to be formatted at each boot! The bootcmd directive is there to handle everything related to commands to be executed very early in the boot process, while the runcmd directive is executed much later in the boot process (and only once).

Note

bootcmd will be executed at every boot of the instance.

Getting ready

To step through this recipe, you will need:

  • Access to a cloud-config enabled infrastructure

How to do it…

We'll launch three commands during boot. The first one is a simple file with a dynamic content (the $INSTANCE_ID variable made available to us by cloud-init), which will always be rewritten, no matter what, at each boot. The second command is printing the date in the logs (so we know when the boot process started). The final command is the ext4 formatting of a block device attached on /dev/xvdb. For the sake of the exercise, we'll also mount the new device under /srv/www on the host.

To launch any command at boot time that will be run as early as possible, every time the machine boots, simply add it to the list of the bootcmd directive:

#cloud-config
bootcmd:
  - echo bootcmd started at $(date)
  - echo $INSTANCE_ID > /etc/instance_id

If we delete or modify this file, at the next reboot it will be overwritten.

On the other hand, if we want to run a command only once inside the bootcmd directive, we can use the helper script cloud-init-per. You can choose to launch the command once per boot or once per instance. In our case, we want to format the /dev/xvdb device (so, unless we want to format our drive each time we reboot, we probably want this to happen only once on this instance. So let's add the instance argument to the cloud-init-per helper script):

#cloud-config
bootcmd:
  - cloud-init-per instance mkfs-xvdb mkfs -t ext4 /dev/xvdb

Finally, let's use the mounts directive to mount the now formatted /dev/xvdb on the /srv/www folder:

mounts:
  - [ /dev/xvdb, /srv/www ]

After boot, let's verify the block device is mounted:

# df -h /srv/www/
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvdb       4.8G   10M  4.6G   1% /srv/www

We can also test the existence of the file we created:

# cat /etc/instance_id
i-03005dd324599df11

Try to delete this file and reboot the server: the file will be there again.

Now, let's take a look at how different the runcmd directive is. Let's add a very similar command to the date output in the bootcmd directive:

runcmd:
 - 'echo runcmd started at $(date)'

Start a new instance, and observe the difference in timestamps:

$ grep "started at" /var/log/cloud-init-output.log
bootcmd started at Fri Sep 23 07:02:35 UTC 2016
+ echo runcmd started at Fri Sep 23 07:02:47 UTC 2016
runcmd started at Fri Sep 23 07:02:47 UTC 2016

The runcmd directive started 12 seconds later than the bootcmd directive.

Now reboot the instance, and observe that runcmd didn't run again:

$ grep "started at" /var/log/cloud-init-output.log
bootcmd started at Fri Sep 23 07:04:31 UTC 2016

Now we know what directive to use in each case.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.46.69