Proxmox Cloud-init image using Ansible

Whelp, I'm not really certain how I got here.. but at some point, I wound up with a pair of computers running Proxmox with the intent of running Kubernetes. It started out pretty innocently: I watched a TechnoTim video:

And it looked neat enough, so sure.. why not, let's try that out.

In the video, around the 6:00 minute mark, he makes reference to another video of his - using cloud-init images to make Ubuntu machines:

Until this time, I never really understood what cloud-init was, or how I could leverage it. I'd seen it in use in Azure (and seen it broken as heck too ...), but that's where my experience ended.

The end result enabled me to make a new VM in seconds, not minutes, which was a huge win for me.

Resource for doing this with Debian

I set out to do this for a Debian image (which I prefer for some reason.. I legit don't know why I lean that way each time), and found a healthy set of instructions on how to do this on the Proxmox host for Debian at https://gist.github.com/chriswayg/b6421dcc69cb3b7e41f2998f1150e1df#steps-for-creating-a-debian-10-cloud-template.

I would be using Debian 11 (Bullseye), and based on Debian's information at https://cloud.debian.org/images/cloud/, I opted to use the genericcloud image. The download directory is at https://cloud.debian.org/images/cloud/bullseye/latest/, and the specific image was found at https://cloud.debian.org/images/cloud/bullseye/latest/debian-11-genericcloud-amd64.qcow2.

Ansible

The gist I linked above gave me a good set of steps on how to execute this on the Proxmox host itself. I wanted to do this in Ansible so I could make it part of another playbook, as well as leverage data I already have in my Ansible repository (SSH public keys, specifically..).

At the initial outset, I also wanted to make multiple images - One would be a Kubernetes's master node template, which would need limited RAM, CPU and storage, and a Kubernetes' node .. node template, which would be a bit beefier and sport 2 NIC's - one for the "public" network of my LAN, and the other for my "ceph" network for Proxmox. I tried to template this in a variable with general success:

 1  - vm_defs:
 2      - id: 2000
 3        name: "cloudimage-Debian11-k3s-master"
 4        nets:
 5          - id: 0
 6            bridge: "vmbr0"
 7      - id: 2001
 8        name: "cloudimage-Debian11-k3s-node"
 9        nets:
10          - id: 0
11            bridge: "vmbr0"
12          - id: 1
13            bridge: "vmbr0"
14            tag: 100

My initial approach also included machine resource configurations (RAM, HDD, CPU), but this wound up being a bad idea: The template that was created was the size of the hard drive image, making future copy operations considerably more expensive. It wound up being faster to modify those parameters during the VM creation.

The playbook, posted as a gist here, does the following:

  • Installs pip on the proxmox host
  • Installs the proxmoxer package on the proxmox host (these could probably be executed locally, but..)
  • If force_download is set, downloads the cloud-init ISO image
  • Removes existing cloud init images from Proxmox
  • Creates new VM(s) that will become our image(s).
  • Assign network interfaces to the VM(s).
  • Import the downloaded ISO image to the VM.
  • Attach the cloned disk to the VM
  • Add the cloud-init drive
  • Set the boot disk configuration
  • Load the SSH public keys into one file, and attach them to the cloud-init image
  • Convert the VM to a template

To fix / work on:

  • Make the Import Disk more Ansible-y
  • Convert the VM to a template should be more Ansible-y

Follow-up

A little while after, I was reading a Reddit thread on the topic, which I stated that I had created a playbook to do this task for me.

While the playbook works, I was left with the feeling that it was incomplete - it felt like I was replacing the calls to qm with Ansible calls, but not much more. So, if I wanted to create an image that came with Docker pre-installed.. I wasn't positioned to do that.

I was also being rather vague about where machine configurations would take place. Should the number of NIC's be define in the cloud-init template? Should that get added when the VM's were being copied? If I think of the real-world analogy, I would likely buy a "basic" computer from a supplier, then add my extra NIC, storage and RAM upon receipt.. so if I'm following that approach, I should be waiting to add the NIC to when I copy the template into a new VM. This would leave me with one template VM, which is a bit.. tidier somehow?

Anyhow, in the same Reddit thread, it was suggested that I use packer to create these images (and pointed at https://www.youtube.com/watch?v=1nf3WOEFq1Y), so .. that's the next thing to try.

Posts in this Series