Proxmox Cloud-Init lab

Cloud-init in Proxmox

This explores how cloud-init works in Proxmox. You will be working in your normal groups.

Inspect cloud-init for the groupXY-web VM

Your existing VM was configured using cloud-init; we can now look at how the data was passed to it.

Login to VM

Get a console on the VM you created earlier, groupXY-web. If necessary, start it.

Login (username is “ubuntu”, password is whatever you set when creating the VM), and get a root shell:

sudo -s

so that the prompt ends with a hash (#), like this:

root@group12-web:/home/ubuntu# 

Examine cloud-init data inside VM

Let’s look at how Proxmox was able to pass your login credentials and network configuration to the VM when it started.

It does this by creating a small virtual CD-ROM image which is attached to the VM. Most VM images these days include the “cloud-init” tool which runs at first boot, reads this data, and configures the VM accordingly.

Still inside your VM, type the following:

mount -r /dev/cdrom /mnt
ls /mnt

(Flag -r means “read-only”)

You chould see some files: meta-data, network-config, user-data, vendor-data. Look at the contents of the two most important ones:

cat /mnt/network-config
cat /mnt/user-data

In the user-data file, look for these settings:

hostname: groupXY-web
fqdn: groupXY-web

These are how the VM has learned its hostname. Also:

password: $5$.....etc....
chpasswd:
  expire: False

provides the (hashed) password, and tells it not to expire.

The cloud-init online documentation gives you more information about what these settings mean.

Reading metadata from a disk image is what cloud-init calls the “nocloud” data source. In a public cloud, the metadata is usually provided via some other mechanism - in the case of AWS it’s a webserver on the local IP address 169.254.169.254.

Log files created by cloud-init while it ran are available at /var/log/cloud-init-output.log and /var/log/cloud-init.log

Unmount the CD:

umount /mnt

When cloud-init ran on first VM boot, it wrote out the data it used. So you can also find what data was used to boot this VM even with the CD unmounted. Look at the files in the directory /var/lib/cloud/instance:

cd /var/lib/cloud/instance
ls
cat user-data.txt
cat network-config.json

Examine from Proxmox node

You can also see the cloud-init data that Proxmox had prepared, before starting the VM.

Get a shell on the Proxmox node in your cluster (nodeXY) where your VM is running. That is:

Now run these commands, where <VMID> is the numeric ID of your groupXY-web virtual machine:

qm cloudinit dump <VMID> user
qm cloudinit dump <VMID> network

You should see the YAML-format cloud-init data which Proxmox used to build the ISO (virtual CD-ROM). Any changes you make in the GUI to the cloud-init settings should be reflected here.

Reference: Manually configuring user-data and vendor-data

(The following is for reference only)

Only a handful of settings for cloud-init are provided in the Proxmox GUI. Any further customisation has to be done at the command line.

You can provide customised user-data or network-data for any VM, before you boot it for the first time, by putting it in a file and telling Proxmox to use that file (don’t do it now, since your VM has already booted):

### DON'T DO THIS NOW: FOR REFERENCE ONLY
### Put your user-data config in /var/lib/vz/snippets/vm123-user-data.yml
# qm set 123 --cicustom "user=local:snippets/vm123-user-data.yml"

It’s also possible to set your own user-data on the VM template that you clone from, so that all the child VMs inherit these settings. But if you do that, it completely replaces the automatically-generated user-data which Proxmox supplies for each child VM. In particular, your VM won’t learn its hostname.

The solution is to pass vendor-data, which is normally empty, and is merged with user-data.

OPTIONAL EXERCISE: Add vendor-data to the VM template

This exercise is done cluster-wide: just ONE user logs into nodeX1 while everyone else in the same cluster watches

Get a shell on nodeX1 in your cluster.

Using a text editor like nano or vi, create a file called /var/lib/vz/snippets/init-web.yml, for example:

nano /var/lib/vz/snippets/init-web.yml

Insert the following text (all three lines exactly like this):

#cloud-config
packages:
  - apache2

Save it and exit. If using nano: ctrl-X, Y (for yes), Enter to accept filename.

Now back at the nodeX1 shell, enter this command:

qm set 9001 --cicustom "vendor=local:snippets/init-web.yml"

This tells your template to use the vendor-data file you created.

Test by cloning the template

Now in the GUI, under nodeX1 find your template 9001 and clone it:

Wait a few seconds for the clone to take place. The clone should be created on node X1. It will take a few seconds to appear in the GUI.

Click on your new VM “testweb” in the first column, then “Cloud-Init” in the second column.

Click on “Console” in the second column, and “Start Now”. Watch it boot.

Login to the VM as username “ubuntu” and the password you set, then use sudo -s to get a root shell.

You should find that the apache2 webserver has been installed automatically:

dpkg-query -l apache2

If this comes back with “no packages found matching apache2”, then it may still be in the process of installing. Type:

cloud-init status --wait

which should return status: done when cloud-init has finished. Then try the dpkg-query command again.

If it’s still not working, check that the vendor-data has been picked up and is correct:

cat /var/lib/cloud/instance/vendor-data.txt
cat /var/lib/cloud/instance/vendor-cloud-config.txt

NOTE: if both the vendor-data and user-data supply the same configuration key (such as packages or runcmd), these may or may not be merged in a way that you expect. See the documentation for details.

Shutdown this VM when finished.

References