There are many ways to create virtual machines. In this article, we aim to leverage cloud images as our primary method for automation while provisioning on Proxmox.
Cloud Images
Cloud images are pre-configured disk images designed to be used in virtualized environments, such as cloud infrastructure or virtual machine hosts. These images include minimal operating system installation and are optimized for quick deployment and scalability. They have support for quick configuration tools, we will be using cloud-init for our example.
Script
You'll need a Proxmox Virtual Environment node with SSH access. In our script, we will perform some actions to download and prepare a cloud image.
- Variable and packages First, we set up some variables and install some useful packages we will be using in the script.
### variables
VM_TEMPLATE_ID=999
TEMPLATE_NAME='ubuntu-2204-template'
UBUNTU_IMAGE='ubuntu-22.04-server-cloudimg-amd64-disk-kvm.img'
UBUNTU_IMAGE_QCOW2='ubuntu-22.04.qcow2'
USERNAME='cap'
PASSWORD='12345'
MEMORY='4096'
CPUS='2'
apt update -y && apt install nano wget curl libguestfs-tools -y
- Idempotency Run a couple of commands to make our script idempotent. We want a quick way of iteration, so we will be deleting the template in case of changes.
# remove old image
rm -rfv ${UBUNTU_IMAGE}
# remove old template container - WILL DESTROY COMPLETELY
qm destroy ${VM_TEMPLATE_ID} --destroy-unreferenced-disks 1 --purge 1
- Download the image:
# download new image
wget http://cloud-images.ubuntu.com/releases/22.04/release/${UBUNTU_IMAGE}
- Customize the image Add the QEMU guest agent to the image so we don't need to install it later. Here, you can use virt-customize to add other tools and have them pre-installed on the image.
virt-customize -a ${UBUNTU_IMAGE} --install qemu-guest-agent
QEMU guest agent is a daemon installed in the guest and helps us get information about our VMs in the Proxmox environment. See more documentation on PVE docs.
- Change image extension Change the img extension on the image file to QCOW2, if you don't rename it in some versions of proxmox qemu will not work
mv ${UBUNTU_IMAGE} ${UBUNTU_IMAGE_QCOW2}
Resize
Now we resize the image to a generic size. It doesn't really matter now; we will configure each clone based on the template later.Create the vm
Again, the values for resources here are not really important. Set up a generic value for memory and CPU. We are setting up a network interface. Another key configuration is the storage controller; we use virtio-scsi as it covers more use cases. To learn more about virtualization of 'physical' devices on the virtio family and emulated storage controllers of the virtio family, go to Virtio
qm create ${VM_TEMPLATE_ID} --memory ${MEMORY} --cores ${CPUS} --net0 virtio,bridge=vmbr0 --name ${TEMPLATE_NAME} --scsihw virtio-scsi-pci
After creating the vm we need to configure and convert to a template, so it can be cloned.
- Configure the vm
We will perform in order the following configuration:
- Import the image to a disk and attach to the vm
- attach a cloud-init drive to the vm via ide interface
- Configuring vga output for the console on serial0
- Setting up dhcp for the network so we have connection
- enabling the qemu agent
- seting default user and password
- adding ssh keys so we can have ssh access, it will use the same ssh keys from the host in witch you will be executing the script
qm set ${VM_TEMPLATE_ID} --scsi0 local-lvm:0,import-from=/root/${UBUNTU_IMAGE_QCOW2}
qm set ${VM_TEMPLATE_ID} --ide2 local-lvm:cloudinit
qm set ${VM_TEMPLATE_ID} --boot order=scsi0
qm set ${VM_TEMPLATE_ID} --serial0 socket --vga serial0
qm set ${VM_TEMPLATE_ID} --ipconfig0 ip=dhcp
qm set ${VM_TEMPLATE_ID} --agent enabled=1
qm set ${VM_TEMPLATE_ID} -ciuser ${USERNAME}
qm set ${VM_TEMPLATE_ID} -cipassword ${PASSWORD}
qm set ${VM_TEMPLATE_ID} --sshkeys ~/.ssh/authorized_keys
- Converting to template
In the last step, we convert this VM to a template. A template is a VM with a frozen state used as a base for many machines. It provides a stable starting point and makes it easy for provisioning automation.
qm template ${VM_TEMPLATE_ID}
The complete script can be found on my homelab github
To run over ssh we can pipe the output via ssh running:
cat ubuntu-22.04.sh | ssh root@your-PVE-ip /bin/bash
Result should be a template on your Proxmox node
Now you can run any number of copies, we can use qemu set to configure any variable to the clone we want to change from the template.
# clone
qm clone ${VM_TEMPLATE_ID} ${VM_ID} --name ${VM_NAME}
# configure the vm
qm set ${VM_ID} --scsi1 local-lvm:40
qm set ${VM_ID} --memory ${MEMORY}
qm set ${VM_ID} --cores ${CPUS}
qm set ${VM_ID} --boot order=scsi0
qm set ${VM_ID} --serial0 socket --vga serial0
qm set ${VM_ID} --ipconfig0 ip=dhcp
qm set ${VM_ID} --agent enabled=1
# start
qm start ${VM_ID}
Running again over ssh should create a new vm based on the template:
cat clone-templates.sh | ssh root@your-PVE-ip /bin/bash
Its as fast as it gets, less than 30 seconds and you have a vm running:
Now we know how to create vms based on templates we can explore more options of remote code execution for provisioning.
Socials:
Photo by Arno Senoner on Unsplash
Top comments (0)