Rerun cloud-init on multipass
Today, I had the need to experiment with rerunning cloud-init on a virtual machine created with multipass. You can use cloud-init with multipass by specifying a cloud-init.yaml file when creating your instance. e.g,
multipass launch --name my-instance --cloud-init ./cloud-init.yaml
This is all well and good and works as you would expect.
However, today, I wanted to experiment with running cloud-init on an already-provisioned instance. My use case is that the lovely folks at Eclips.is (a project by Greenhost and the Open Technology Fund) who have given Ind.ie a generous amount of free hosting do not yet support cloud-init when provisioning a server. So I wanted to see if I can run my cloud-init script after I provisioned a server and I wanted to test that out locally using multipass.
How to rerun cloud-init
Ordinarily, it is actually quite simply to rerun cloud-init after a server has been provisioned.
First, you use the clean
command to remove the current build artifacts:
sudo cloud-init clean
Then, you specify your meta-data and user-data files in the /var/lib/cloud/nocloud-net/ directory, which you must create:
sudo mkdir /var/lib/cloud/nocloud-net/
sudo touch /var/lib/cloud/nocloud-net/meta-data
sudo nano /var/lib/cloud/nocloud-net/user-data
Then, paste your cloud-config file into the editor and save (in nano, Ctrl-o + Ctrl-x).
Finally, run the init
command to re-initialise your instance using cloud-init:
sudo cloud-init init
Now, in theory, this should work.
In practice, however, we end up with a /var/lib/cloud/instance/user-data.txt file that only contains the vendor-data provided by multipass, not our user-data.
Multipass
Say you have created a multipass instance without specifying a cloud-init.yaml file, like this:
multipass launch --name my-instance
To run your cloud-config file, you first have to SSH into the box. You can either do this by running multipass ls
and finding the IP address and then using the account and key that multipass automatically creates to ssh to it (e.g., ssh multipass@<ENTER THE IP-ADDRESS OF YOUR INSTANCE HERE> -i $(locate multipass | grep .*id_rsa)
) or you can use the handy shortcut that multipass provides:
multipass shell <NAME OF YOUR INSTANCE>
Then, to find the culprit, run the status
command in verbose mode:
sudo cloud-init status --long
Which should give you something along the lines of:
status: running
time: Sat, 15 Jun 2019 21:11:55 +0000
detail:
DataSourceNoCloudNet [seed=/var/lib/cloud/seed/nocloud-net,/dev/sr0][dsmode=net]
The first seed source you see is the one you defined. The second one is the one that multipass passes in. You can cat it to see what it has:
sudo cat /dev/sr0
You should see the vendor-data specified and, at the end of that, you should see an empty cloud-init section:
#cloud-init
{}
This is also what I saw at the end of /var/lib/cloud/instance/user-data.txt and that led to me to think that perhaps our datasource was being ignored or overwritten.
You can find the data sources defined in the file /etc/cloud/cloud.cfg.d/90_dpkg.cfg. To see its contents:
cat /etc/cloud/cloud.cfg.d/90_dpkg.cfg
And you should find a long list similar to:
datasource_list: [ NoCloud, ConfigDrive, OpenNebula, DigitalOcean, Azure, AltCloud, OVF, MAAS, GCE, OpenStack, CloudSigma, SmartOS, Bigstep, Scaleway, AliYun, Ec2, CloudStack, Hetzner, IBMCloud, None ]
I had a suspicion that the ConfigDrive
data source might have been overriding my user-data, so I edited that file and reduced the list down to:
datasource_list: [ NoCloud, None ]
Then, after running sudo cloud-init clean
and sudo cloud-init init
again, I had multipass successfully using my cloud-config from /var/lib/cloud/nocloud-net/user-data.
Information about cloud-init seems hard to come by so while I’m mostly documenting this for my own sake, I hope it also ends up helping someone else out in the future.
Useful resources
From Cloud-init docs
- Capabilities
- Datasources
- Instance Metadata
- User-Data Formats
- Vendor Data
- NoCloud
- Directory layout
- Merging User-Data Sections
Other
- Install cloud-init on Ubuntu and use locally… NoCloud
- Cloud-init page ArchLinux wiki
- Cloud-init v.18.2: CLI subcommands
- Using cloud-init with Multipass
- How to re-run cloud-init without reboot: answer with new cloud-init syntax
- How do I boot Ubuntu Cloud images in vmware
- How to use cloud-config for your intial server setup
- An introduction to cloud-config scripting