Creating VM image out of thin air
thin air == access only to repo mirrors
I got a stupid problem: I need to run a VM on my hypervisor. It’s the problem because my hypervisor is very local (no Openstack infra, etc), and it’s stupid because I work in hosting company and we have trully amaizing image build/test/update pipelines for our clients, and I took a great deal of efforts in developing those.
My hypervisor host has only access to the global private network. No NAT, no internet connectivity. I got a few pro bono services (we provide them to all servers of our clients, including my own lab): DNS, NTP and mirror of Debian/Ubuntu repo. That’s all I have to use. Oh, and I have an SSH connection to the server, but you definitively don’t want to pass huge upload traffic from your machine to remote one. Moreover, it’s not very ansible-friendly (you can’t put this in a playbook without curses at a review time).
Now I need to find a way to make VM to boot out of this. 99 methods you find on the Internet says ‘download image bla-bla-bla’, or ‘run software which download image bla-bla-bla’. Nope, nope, nope. No more Internets jumping on the bed.
I was almost at the point of starting using debootstrap with thousands of following actions (install grub, make disk image, etc), when I realized, oh, I done something like this in the past. Our own pipelines for images. Of course we use diskimage-builder. Why not?
Naive run for Ubuntu has crashed, as there were few downloads required. Nope.
I found that Ubuntu has some issues with their images, and I wasn’t able to make it totally local. Good news, Debian is shining here.
The way to build images from thin air
apt install python3-diskimage-builderexport DIB_DISTRIBUTION_MIRROR=http://mirror.servers.com/debian
export DIB_RELEASE=buster
export DIB_DEBIAN_SECURITY_MIRROR=http://mirror.servers.com/debian/
export DIB_DEBIAN_SECURITY_SUBPATH=-updatesdisk-image-create -o test.img debian-minimal
And you have a bootable Debian image. It needs tons of tweaks, but generally, it’s the way. The image was created with zero Internet participation. Only Debian mirror was required, and that’s enough.
Now I’ll add pieces I need (like a good network configuration, etc). Diskimage-builder is unexpectedly good at doing this. The proper way it to create own elements, but I hope to deal with those pesky little issues with standard elements only.
Ansible integration
If you struggle with diskimage-builder as ‘command
’ for Ansible, there is a good pattern to follow. Ansible provides ‘creates
’ parameter for a ‘command
’ module. By using ‘creates
’ the non-idempotent command
become idempotent. For example above (which is not a ‘production grade image’, but nevertheless), it would look like this:
- name: Create an image
command: disk-image-create -o /var/cache/vm.img debian-minimal
args:
creates: /var/cache/vm.img.qcow2
environment:
DIB_DISTRIBUTION_MIRROR: http://mirror.servers.com/debian
DIB_RELEASE: buster
DIB_DEBIAN_SECURITY_MIRROR: http://mirror.servers.com/debian/
DIB_DEBIAN_SECURITY_SUBPATH: "-updates"
P.S.
Some people may not realize how important this for ‘streamlined’ playbooks. If you need to depend on some ‘golden image’ on some yet-another-nexus, that’s a big burden. You need to have connectivity, you need to care about that image, etc. Using repo mirror lifts all that burden. OS giving birth to the OS using own genetic material is a class better than relying on some surrogate vagranting.