Cloud-init, Hyper-V and a custom image

Today I'm going to go over using Cloud-init with Hyper-V and customizing the base image.

Today I'm going to go over using Cloud-init with Hyper-V and customizing the base image.

Overview

I build a lot of VM's and tear them down throughout a general work week, I am tired of spending a bunch of time baby-sitting an installer to enter the same information all the time. I wanted to make this a single script that I can run to create an entire environment.

To accomplish this I needed an image that has Cloud-init setup in it that works with Hyper-V. I chose the Ubuntu cloud image for Azure. Azure runs on Hyper-V so it fit well right out of the box, mostly. I do need to pull out some of the Azure specific customizations. I'll cover that as well.

To customize the image and to remove the Azure components you'll need to be an Administrator on your computer. You will need Windows Subsystem for Linux installed from the Microsoft Store. The reason you need WSL from the store is that we mount the Ubuntu cloud image inside of it so we can customize it. That feature is only in the Store instance of WSL.

To create the virtual machine you will need the Windows Assessment and Deployment Kit with the Deployment Tools feature. This is used to create the iso image that contains the Cloud-init configuration.

Download and install the Windows ADK
Instructions on how to download and install the Windows ADK

Assumptions with this post

  1. You'll be using the Ubuntu Mantic distribution.
  2. You have admin rights on your computer
  3. You have Windows Subsystem for Linux already setup and running with default settings and a distribution with chroot.
  4. You're using a directory named  c:\Cloud-init to store everything.
  5. You have the Windows Assessment and Deployment Kit with a minimum, the Deployment Tools feature installed at the default location of C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit.
  6. You have this repository checked out
GitHub - EdwardCooke/hyperv-cloud-init: Easy scripts for creating a cloud-init based VM in Hyper-V
Easy scripts for creating a cloud-init based VM in Hyper-V - GitHub - EdwardCooke/hyperv-cloud-init: Easy scripts for creating a cloud-init based VM in Hyper-V

Create the base image

Download

First step in creating the base image, download the Azure Cloud-init image from Ubuntu's cloud image site linked here

Ubuntu Cloud Images - the official Ubuntu images for public clouds, Openstack, KVM and LXD
Ubuntu Cloud Images are the official Ubuntu images that have been customized by Canonical to run on public clouds that provide Ubuntu Certified Images, Openstack, KVM, LXD and more.

I'm going to be picking on the latest one, mantic. The image name for the mantic version of Ubuntu is mantic-server-cloudimg-amd64-azure.vhd.tar.gz.

Extract the vhd

Now that you have that downloaded, extract the vhd file from that archive. You can use WSL to do this, or an application like 7-zip.

7-Zip

Customize the base image

Now that you have the vhd extracted, we need to customize it.

Here is a link to the create-vm.ps1 script that will convert the vhd to a dynamically sizing vhdx, mount the vhdx in WSL, remove the Azure specific components, and finally chroot into the mounted vhdx so you can customize it.

hyperv-cloud-init/set-cloudinit.ps1 at main · EdwardCooke/hyperv-cloud-init
Easy scripts for creating a cloud-init based VM in Hyper-V - hyperv-cloud-init/set-cloudinit.ps1 at main · EdwardCooke/hyperv-cloud-init

You can execute this from where you checked out the repo in an administrator PowerShell window

./set-cloudinit-ubuntu.ps1 -Source C:\cloud-init\livecd.ubuntu-cpc.azure.vhd -Destination C:\cloud-init\ubuntu-mantric.vhdx

You should be greeted with output that looks very similar to this.

Converting image to a dynamic disk
Mounting in WSL
The disk was successfully mounted as '/mnt/wsl/61447da8-c86a-4526-b900-5048ec59d556'.
Note: The location will be different if you have modified the automount.root setting in /etc/wsl.conf.
To unmount and detach the disk, run 'wsl.exe --unmount \\?\C:\cloud-init\ubuntu-mantric.vhdx'.
Modifying the cloud-init data source
Removing the azure specific configuration
Entering your image environment
Press ctrl+d or type exit when you are done customizing your image
root@edslaptop:/#

You are now in the chroot environment of your golden image. Customize as you see fit. Once you are happy with your image, press ctrl+d or type exit and press enter to exit the chroot environment.

After you exit the chroot environment, you should now be greeted with the following

Unmounting from WSL
The operation completed successfully.

Your golden image is now setup and ready to be cloned.

Building your virtual machine

Setup Cloud-init files

We're going to now setup some basic example Cloud-init files. You can find the example Cloud-init configuration in the example directory here

hyperv-cloud-init/example at main · EdwardCooke/hyperv-cloud-init
Easy scripts for creating a cloud-init based VM in Hyper-V - hyperv-cloud-init/example at main · EdwardCooke/hyperv-cloud-init

Those example files will show how to build a VM with the hostname of example, a single user with username/password of example and install curl and ca-certificates. It will also enable password based ssh login, which is disabled by default and upgrade all of the currently installed packages.

Use the Cloud-init configurations and build the VM

Now that you have your Cloud-init configuration build, it's time to build the actual virtual machine. We'll use the create-vm.ps1 script for that. It is very simple to use, here is the minimal usage of the script. It creates a virtual machine named Test, with a root disk of 30 gigs, using the example directory, the base image we just created and 4 gigs of memory.

./create-vm.ps1 -VirtualMachineName Test -VirtualDiskSize 30 -CloudInitDirectory ./example -RootDiskPath C:\cloud-init\ubuntu-mantric.vhdx -MemorySize 4

You should now be greeted with an output looking like this.

Copying root disk from C:\cloud-init\ubuntu-mantric.vhdx to C:\ProgramData\Microsoft\Windows\Virtual Hard Disks\Test.vhdx
Resizing virtual disk to 30 gigabytes
Creating cloud init iso at C:\ProgramData\Microsoft\Windows\Virtual Hard Disks\Test-cidata.iso

OSCDIMG 2.56 CD-ROM and DVD-ROM Premastering Utility
Copyright (C) Microsoft, 1993-2012. All rights reserved.
Licensed only for producing Microsoft authorized content.


Scanning source tree
Scanning source tree complete (2 files in 1 directories)

Computing directory information complete

Image file is 57344 bytes

Writing 2 files in 1 directories to C:\ProgramData\Microsoft\Windows\Virtual Hard Disks\Test-cidata.iso

100% complete

Final image file is 57344 bytes

Done.
Creating virtual machine
Disabling dynamic memory
Setting secure boot settings
Adding cidata iso to the virtual machine
Starting virtual machine
Virtual machine creation complete

Check your virtual machine

Open the Hyper-V Manager application and check your Test virtual machine, if it's not the basic login screen then wait a couple of minutes.

Once the login screen is up, try logging in with the example user, the password is also example.

Conclusion

This is the under pinning of how to use Hyper-V, Cloud-init, PowerShell and WSL to customize a base image and actually use it in Hyper-V. Next post will be using PowerShell to easily create a set of Cloud-init files to quickly build a basic Ubuntu virtual machine.

This was a fun project to do. I'm glad I did it, even thought it was a little difficult to figure it all out.

Hopefully you find it useful as well.

cloud-init 23.2.1 documentation
Create and upload an Ubuntu Linux VHD in Azure - Azure Virtual Machines
Learn to create and upload an Azure virtual hard disk (VHD) that contains an Ubuntu Linux operating system.
Prepare Linux for imaging - Azure Virtual Machines
Learn to prepare a Linux system to be used for an image in Azure.
GitHub - EdwardCooke/hyperv-cloud-init: Easy scripts for creating a cloud-init based VM in Hyper-V
Easy scripts for creating a cloud-init based VM in Hyper-V - GitHub - EdwardCooke/hyperv-cloud-init: Easy scripts for creating a cloud-init based VM in Hyper-V
Ubuntu Cloud Images - the official Ubuntu images for public clouds, Openstack, KVM and LXD
Ubuntu Cloud Images are the official Ubuntu images that have been customized by Canonical to run on public clouds that provide Ubuntu Certified Images, Openstack, KVM, LXD and more.