Pulumi is an open sourced IaC SDK that allows you to define and manage infrastructure through the use of various programming languages. This helps reduce the need to learn another HCL-ish language and gives you the extensibility and toolkit of whatever (popular) programming language you are comfortable with.
For my usecase, I have a Promxox node (Minisforum 773 Lite, 64GB RAM, 1TB SSD) and would want to use it to host my VMs. Initially I want to run 3 VMs to host a kubernetes cluster that I can use to better learn the technology.
I’m assuming that Pulumi is already installed and configured. Let’s now create a new stack with pulumi new python -y. This will create a few new files for us: Pulumi.yaml(Project metadata), __main__.py(Program entrypoint), requirements.txt(dependencies), venv (virtual env for the project).
Proxmox has an API that allows us to provision resources, however we would need to know the calls to make. To simplify the process, we can use a pulumi proxmox provider, which can be installed as a basic pip package with venv/bin/pip install pulumi-proxmoxve (or install via the requirements.yaml). This will allow us to create a proxmox provider and to define the VM in an easier manner and the package takes care of the required API calls to provision the VM.
In order to make configuration of VMs a bit easier, lets also define a folder called vms that contains YAML files containing all the values that we’d want to configure. We can then read the files in said folder, parse the values and then configure the pulumi proxmox provider to create the VMs for us.
To start with, lets configure .gitignore to ignore the .env file that will be containing our secrets. Then create a .env file with the following contents:
for vm in parsed_data: disks = [] nets = [] ip_configs = [] ssh_keys = []
for v in vm: for vmcount inrange(v['count']): base_resource_name=v['resource_name'] name_counter = vmcount + 1 base_vm_id=v['vm_id'], for disk_entry in v['disks']: for d in disk_entry: disks.append( proxmox.vm.VirtualMachineDiskArgs( interface=disk_entry[d]['interface'], datastore_id=disk_entry[d]['datastore_id'], size=disk_entry[d]['size'], file_format=disk_entry[d]['file_format'], cache=disk_entry[d]['cache'] ) )
for ip_config_entry in v['cloud_init']['ip_configs']: ipv4 = ip_config_entry.get('ipv4')
for ssk_keys_entry in v['cloud_init']['user_account']['keys']: ssh_keys.append(ssk_keys_entry)
for net_entry in v['network_devices']: for n in net_entry: nets.append( proxmox.vm.VirtualMachineNetworkDeviceArgs( bridge=net_entry[n]['bridge'], model=net_entry[n]['model'] ) )
The values being configured are quite self-explanatory, if not there is a detailed documentation in the proxmox provider page.
Once done, all you have to do is run pulumi up in the folder and the pulumi interactive shell will guide you through the rest!
Once the pulumi job is done, you should be able to see brand new VMs created in your proxmox host. If you want to change a value, you can simply modify the YAML and run pulumi up again. To destroy the VMs, you can run pulumi down or set the count to 0 to not affect the rest of the pulumi stack.