Ironic is an OpenStack project which provisions bare metal machines (as opposed to virtual).
A tool called Ironic Python Agent (IPA) is used to control and provision these physical nodes, performing tasks such as wiping the machine and writing an image to disk. This is done by booting a custom Linux kernel and initramfs image which runs IPA and connects back to the Ironic Conductor.
These have their limitations, however, for example they require root privileges to be built and, with the exception of TinyCore, are all hundreds of megabytes in size. One of the downsides of TinyCore is limited hardware support and although it’s not used in production, it is used in the OpenStack gating tests (where it’s booted in virtual machines with ~300MB RAM).
Large deployment images means a longer delay in the provisioning of nodes and so I set out to create a small, customizable image that solves the problems of the other existing images.
I chose to use Buildroot, a well regarded, simple to use tool for building embedded Linux images.
So far it has been quite successful as a proof of concept.
- Linux kernel is ~2MB
- Compressed initramfs image is ~25MB
- Passing the OpenStack Ironic gating tests
- Highly customisable (thanks to Buildroot)
Customization can be done via the menuconfig system, similar to the Linux kernel.
All of the source code for building the image is up on my GitHub account in the ipa-buildroot repository. I have also written up documentation which should walk you through the whole build and customisation process.
The ipa-buildroot repository contains the IPA specific Buildroot configurations and tracks upstream Buildroot in a Git submodule. By using upstream Buildroot and our external repository, the IPA Buildroot configuration comes up as an option for regular Buildroot build.
Buildroot will compile the kernel and initramfs, then post build scripts clone the Ironic Python Agent repository and creates Python wheels for the target.
The following finalised images will be found under ./output/images:
- bzImage (kernel)
- rootfs.cpio.xz (ramdisk)
- rootfs.iso9660 (ISO image)
These files can be uploaded to Glance for use with Ironic.
Buildroot lets you customize the build parameters, the target initramfs and the Linux kernel. Doing so also is pretty easy and each time you run make, it’ll pick up where you left off and re-create your images.
make menuconfig # do buildroot changes, e.g. change IPA Git URL make linux-menuconfig # do kernel changes make
The post build scripts fetch Ironic Python Agent directly so that the build is highly flexible, getting the exact release you want to use. You can specify the location and branch of the ironic-python-agent and requirements repositories by customizing settings in Buildroot’s menuconfig.
I created the kernel config from scratch (using tinyconfig) and deliberately tried to balance size and functionality. It should boot on most Intel based machines (BIOS and UEFI), however hardware support like hard disk and ethernet controllers is deliberately limited. The goal was to start small and add more support as needed so it may need to be modified to work on your hardware.
Automating builds with imagebuild scripts
Doing a build manually is good because it helps to understand how it’s pieced together, however it is slightly more involved.
The Ironic Python Agent (IPA) repo has some imagebuild scripts which make building the CoreOS and TinyCore images pretty trivial. I now have some patches which add support for creating the Buildroot images, too.
The patches consist of a few scripts which wrap the manual build method and a Makefile to tie it all together. Only the install-deps.sh script requires root privileges, if it detects missing dependencies, all other Buildroot tasks are run as a non-privileged user. It’s one of the great things about the Buildroot method!
Again, I have included documentation in the repo, so please see there for more details on how to build and customise the image. However in short, it is as simple as:
git clone https://github.com/csmart/ironic-python-agent.git cd ironic-python-agent/imagebuild/buildroot make # or, alternatively: ./build-buildroot.sh --all
These actions will perform the following tasks automatically:
- Fetch the Buildroot Git repositories
- Load the default IPA Buildroot configuration
- Download and verify all source code
- Build the toolchain
- Use the toolchain to build:
- System libraries and packages
- Linux kernel
- Python Wheels for IPA and dependencies
- Create the kernel, initramfs and ISO images
The default configuration points to the upstream IPA Git repository, however you can change this to point to any repo and commit you like. For example, if you’re working on IPA itself, you can point Buildroot to your local Git repo and then build and boot that image to test it!
To see available Makefile targets, simply run the help target:
Help is also available for the shell scripts if you pass the –help option:
./build-buildroot.sh --help ./clean-buildroot.sh --help ./customise-buildroot.sh --help
If this interests you, please check it out! Any suggestions are welcome.