While exploring some upcoming capabilities and providing early feedback to Engineering, I came to learn about a new Cloud-init datasource called VMware GuestInfo that was recently merged into the project last August. The Cloud-init Datasource for VMware GuestInfo started out as an OSS project created by Andrew Kutz of VMware and it provides an easy way for a vSphere-based VM to leverage the popular Cloud-init tool for OS initialization and configuration.
Unlike the recent vSphere Guest OS Customization with Cloud-init feature in vSphere 7.0 Update 3, the Cloud-init Datasource for VMware GuestInfo works by configuring specific guestinfo variables on a VM which are then transported into the guest operating system (GOS) using VMware Tools and is then processed by the cloud-init service that is running inside of the GOS. The nice thing about using this new Cloud-init datasource is that it is not tied to a specific release of vSphere and for those with Cloud-init experience, this is an easy way to incorporate your existing workflows. While I was somewhat familiar with Cloud-init and Linux GOS, I did not know that support for Microsoft Windows was also possible through the use of another project similiar to Cloud-Init called Cloudbase-Init.
It took me some time to figure out how to setup Cloudbase-init with Windows and I have to give a huge shoutout to Jay Vyas for pointing me over to one of his pet projects SIG Windows Development Environment that provided a clue to what the configuration file should look like. While learning about both Cloud-init Datasource for VMware GuestInfo and Cloudbase-init, I found that it was not trivial to get started and I wanted to document some concrete examples that can easily illustrate the power of this capability but also help anyone that might be interested in using this feature and how to quickly get started.
Linux
To demonstrate the use of the Cloud-init datasource for VMware GuestInfo with Linux, I will be using the new Rocky Linux 9 release, which just came out a week ago. You can use any Linux OS that you wish as long as you meet the requirements that VMware Tools is installed along with Cloud-init version 21.3 or later.
Step 1 - Download and install the Rocky Linux 9 release. Rocky Linux does not ship with the required version of Cloud-init, but it can be installed manually. In my example, I used Cloud-init 22.2.2 and followed these instructions for manual installation.
Step 2 - Prepare the GOS so that it can be cloned and customized using cloud-init. Follow the instructions here labeled "Prepare GuestOS for Customization" and then shutdown the VM.
Step 3 - Clone the VM and do NOT power it on as we need to configure the required guestinfo properties on the VM.
Step 4 - Create the required metadata and userdata fields that will be configured on the VM. To learn more about Cloud-init metadata and userdata, please refer to the official Cloud-init documentation. For our Linux example, we will be using this metadata-linux.yaml example to configure static networking and this metadata-linux.yaml for creating a file with some text stored in /tmp/vmware-guestinfo-cloudinit-datasource.txt.
We now need to encode these files using gzip+base64 and on a Linux or macOS system, you can run the following commands to retrieve the encoded values:
cat metadata-linux.yaml | gzip | base64
cat userdata-linux.yaml | gzip | base64
Note: You can also decode these values via the command-line (echo "encoded string" | gzip | base64 -d) or you can use an online tool like this one here to view the content.
Step 5 - Next, use either the vSphere UI or vSphere Automation tools like PowerCLI to configure the required guestinfo properties. The example below will configure the required guestinfo properties and be sure to replace the encoded values for both metadata and userdata if you end up modifying the example.
$vm = get-vm rocky-linux-9-01 $vm | New-AdvancedSetting -Name "guestinfo.metadata.encoding" -Value "gzip+base64" -Confirm:$false $vm | New-AdvancedSetting -Name "guestinfo.userdata.encoding" -Value "gzip+base64" -Confirm:$false $metadata = "H4sIAJRC12IAA22PXW7EIAyE33MKX4AUWIKCb+OA00S7CxJGXe3tS9Ssqv5IfvDnGY/sPUujHFntCcEv5Cc/OWUmtyiX1kXNF51UsnrlOJNZXRpuJdJNbUVapjsj1BKvTxWUNsO/w8ztUeoVB4APrrKXjGA7cNu4dlEOpWMWE+xXD3CnFrcXHBgppcoiCFrj1MsjBdQOnT9dp4HltaagB47Gz+NFjyaEN+tO5Z0aP+jp8IfjFI8HhOtx6/cBf8J/xdvhEy09s3lJAQAA" $vm | New-AdvancedSetting -Name "guestinfo.metadata" -Value $metadata -Confirm:$false $userdata = "H4sIAE8M12IAAx2OQQuCMBiG7/sVg46xViBCggcpMC2lLruGzbkGc5PtM3O/vtF7eS4PD++Gazv3hFszKIkWp0A8B6WFzxDBwnDbKyMzLMP2lSYI4yiCMJDhS+KrokivhzKCtlXgpmZ76VZ/ZKeGNivXTbizOrTsFjzVhTzTh/WhlEVcnsfW1ME7wxTGiX7GpXOCyFl4UGaw5H9LGQWk76DzdnZc7OAL6AduOZpxsQAAAA==" $vm | New-AdvancedSetting -Name "guestinfo.userdata" -Value $userdata -Confirm:$false
Step 6 - Lastly, power on the VM and if everything was setup correctly, the Cloud-init service should automatically pickup the guestinfo properties and configure the VM based on your input. You can also use the command: cloud-init query -a to see what was passed into the VM, which can be useful for debugging or troubleshooting purposes.
We can also login to the VM using the VM Console or access it over the network and look at the /var/log/cloud-init.log and we should find a simliar line where the network configurations are applied.
We can also check that our userdata had successfully ran by looking in /tmp where a file should have been created with our desired content.
Windows
To demonstrate the use of the Cloud-init datasource for VMware GuestInfo with Windows, I will be using Windows Server 2019 Standard (No-GUI). You can use any Windows OS version as long as you meet the requirements that VMware Tools is installed along with Cloudbase-init version 1.1.0 or later.
Step 1 - Download and install your desired version of Windows.
Step 2 - Install Cloudbase-Init and since I am using a non-GUI version of Windows Server, I have created the following PowerShell script called install-cloudbase-init-windows.ps1 that will automate the installation, required configuration and automatically enable the service. It is recommended that you use the script to ensure you have the correct configuration. You can perform additional Windows tasks to prepare the OS and then shutdown the VM.
Step 3 - Clone the VM and do NOT power it on as we need to configure the required guestinfo properties on the VM.
Step 4 - Create the required metadata and userdata fields that will be configured on the VM. To learn more about Cloud-init metadata and userdata, please refer to the official Cloud-init documentation. For our Windows example, we will be using this metadata-windows.yaml example to configure static networking and this metadata-windows.yaml for creating a file with some text stored in C:/vmware-guestinfo-cloudinit-datasource.txt.
We now need to encode these files using gzip+base64 and on a Linux or macOS system, you can run the following commands to retrieve the encoded values:
cat metadata-windows.yaml | gzip | base64
cat userdata-windows.yaml | gzip | base64
Note: You can also decode these values via the command-line (echo "encoded string" | gzip | base64 -d) or you can use an online tool like this one here to view the content.
Step 5 - Next, use either the vSphere UI or vSphere Automation tools like PowerCLI to configure the required guestinfo properties. The example below will configure the required guestinfo properties and be sure to replace the encoded values for both metadata and userdata if you end up modifying the example.
$vm = get-vm win-svr-2019-no-gui-01 $vm | New-AdvancedSetting -Name "guestinfo.metadata.encoding" -Value "gzip+base64" -Confirm:$false $vm | New-AdvancedSetting -Name "guestinfo.userdata.encoding" -Value "gzip+base64" -Confirm:$false $metadata = "H4sIACgX12IAA32KQQrDIBBF9znFXEDQVCWd2xgdqzQZi9qE3r4JpNvCX7zH+5lbd+xJ5IBgZ2eNNVooo2ehQ5zFdJNBhFFG8pNTUdOwFO8WkUrr7FZC2DO3rY5S3QWXxzsLqYb/lanvpT5xANiotlwYYTyEeqJ6xHYWAM7+IoDVdZ9+cqp3IVRqDUFKNMcsujvGGaW9XiH5l0b4UPsCM18bw+QAAAA=" $vm | New-AdvancedSetting -Name "guestinfo.metadata" -Value $metadata -Confirm:$false $userdata = "H4sIAGMM12IAAx2OQQuCMBiG7/sVg46xLBChgQcxMC2lLjsFYXOuwdpi+8zcr2/0Xp7Lw8O74tpOA+HWjEqi2SkQ91Fp4SkiWBhuB2UkxTKsH1mKMI4iCAMUH1NfF0V22lURSVcHbhq2lW7xe1a2Sbtw3YYLa0LHzsEnupCH5Gp9qGQRl+ex9e7hSXFJb7fPa+6dIHISHpQZLfm/UkYBGXrovZ0cFxv4AvoBwY6OM7AAAAA=" $vm | New-AdvancedSetting -Name "guestinfo.userdata" -Value $userdata -Confirm:$false
Step 6 - Lastly, power on the VM and if everything was setup correctly, the Cloudbase-init service should automatically pickup the guestinfo properties and configure the VM based on your input. You can also use the command: cloud-init query -a to see what was passed into the VM, which can be useful for debugging or troubleshooting purposes.
We can also login to the VM using the VM Console or access it over the network and look at the C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloud-init.log and we should see similiar lines where hostname is updated via cloudbase-init but no network changes will be applied and along with our userdata configuratoins.
We can also check that our userdata had successfully ran by looking in C:/ where a file should have been created with our desired content.
Oliver Gaida says
Hi William, many thanks for this post. It works for me! One hint, i did not need the instance_id in the metadata yaml file. Kind regards, Olli
Chris J says
William,
I was wondering, in your post you mentioned that the metadata-windows.yaml file would configure a static IP address. Looking at the file in the git repo it looks like it's only setting dhcp? Do you have an example of the static ip address configuration?
William Lam says
IIRC, at the time of publishing the article, cloud-init for Windows hadn't supported static IP or that our implementation didn't. I don't recall off hand ... but you should be able to confirm by following the Linux example https://github.com/lamw/cloudinit-vmware-guestinfo-examples/blob/master/metadata-linux.yaml as the format would be the same