Quick-start tutorial with LXD#
In this tutorial, we will create our first cloud-init
user data script
and deploy it into an LXD container.
Why LXD?#
We’ll be using LXD for this tutorial because it provides first class support
for cloud-init
user data, as well as systemd
support. Because it is
container based, it allows us to quickly test and iterate upon our user data
definition.
How to use this tutorial#
In this tutorial, the commands in each code block can be copied and pasted
directly into the terminal. Omit the prompt ($
) before each command, or
use the “copy code” button on the right-hand side of the block, which will copy
the command for you without the prompt.
Each code block is preceded by a description of what the command does, and followed by an example of the type of output you should expect to see.
Install and initialise LXD#
If you already have LXD set up, you can skip this section. Otherwise, let’s install LXD:
$ sudo snap install lxd
If you don’t have snap, you can install LXD using one of the other installation options.
Now we need to initialise LXD. The minimal configuration will be enough for the purposes of this tutorial. If you need to, you can always change the configuration at a later time.
$ lxd init --minimal
Define our user data#
Now that LXD is set up, we can define our user data. Create the
following file on your local filesystem at /tmp/my-user-data
:
#cloud-config
runcmd:
- echo 'Hello, World!' > /var/tmp/hello-world.txt
Here, we are defining our cloud-init
user data in the
#cloud-config format, using the
runcmd module to define a command to run. When applied, it
will write Hello, World!
to /var/tmp/hello-world.txt
(as we shall
see later!).
Launch a LXD container with our user data#
Now that we have LXD set up and our user data defined, we can launch an instance with our user data:
$ lxc launch ubuntu:focal my-test --config=user.user-data="$(cat /tmp/my-user-data)"
Verify that cloud-init
ran successfully#
After launching the container, we should be able to connect to our instance using:
$ lxc shell my-test
You should now be in a shell inside the LXD instance.
Before validating the user data, let’s wait for cloud-init
to complete
successfully:
$ cloud-init status --wait
Which provides the following output:
status: done
Verify our user data#
Now we know that cloud-init
has been successfully run, we can verify that
it received the expected user data we provided earlier:
$ cloud-init query userdata
Which should print the following to the terminal window:
#cloud-config
runcmd:
- echo 'Hello, World!' > /var/tmp/hello-world.txt
We can also assert the user data we provided is a valid cloud-config:
$ cloud-init schema --system --annotate
Which should print the following:
Valid cloud-config: system userdata
Finally, let us verify that our user data was applied successfully:
$ cat /var/tmp/hello-world.txt
Which should then print:
Hello, World!
We can see that cloud-init
has received and consumed our user data
successfully!
Tear down#
Exit the container shell (by typing exit or pressing ctrl-d). Once we have exited the container, we can stop the container using:
$ lxc stop my-test
We can then remove the container completely using:
$ lxc rm my-test
What’s next?#
In this tutorial, we used the runcmd module to execute a shell command. The full list of modules available can be found in our modules documentation. Each module contains examples of how to use it.
You can also head over to the examples page for examples of more common use cases.