Using Dracut to Build Deployment Ramdisks

For TripleO I was tasked with enabling our deployment ramdisks to be built with Dracut. There are a couple of reasons we want to do this.

First, Dracut is a standard ramdisk tool and many people have experience with using it. This means users of TripleO won't necessarily have to re-learn a completely new ramdisk environment in order to use or debug TripleO ramdisks.

Second, Dracut can handle many of the networking and hardware things that had to be done manually in our old ramdisks. There's not really a good reason to reimplement all of that when it already exists. In addition, using Dracut will likely allow more exotic deployments to things like diskless systems if someone so desired. I don't believe our old ramdisks can handle the variety of setups that Dracut can.

The main purpose of this post is just to jot down some thoughts from the process of enabling Dracut to build our ramdisks.

  • Work with Dracut, not against it. It provides a very flexible module system that should allow you to do just about anything you need to. Initially I tried replacing Dracut's init (pid 0) with my own (which is how our old ramdisks worked), but that was the wrong approach and I never did get it working.
  • Speaking of Dracut's module system, here's a quick how-to on writing a module that I referenced: http://rich0gentoo.wordpress.com/2012/01/21/a-quick-dracut-module/
  • Dracut expects to boot off a hard disk. Basically everything in Dracut is designed around enabling that as simply as possible. The problem is that a deployment ramdisk never does boot off the hard drive, and the hard drive can't even be mounted because there's probably no filesystem on it yet. For TripleO, all the ramdisk does is export the hard disk as an iSCSI target and then signal the deploying system to copy the image to that target. Fortunately, this isn't really a problem. There is a pre-mount hook in Dracut where we can do all of that, and at the end we simply reboot. Dracut never has to know that we don't intend to let it mount the local disk. Essentially I moved our old init to a pre-mount hook and let it run (sans the hardware and networking bits) just as it did before. So far that has worked flawlessly.
  • Because (as noted above) Dracut is all about mounting the root partition, it ordinarily won't bring up networking at all if it thinks it is targeting a local disk. Since we definitely need networking for a deployment ramdisk, this can be worked around by passing the rd.neednet=1 parameter to Dracut as part of the kernel command-line

That's all I can remember off the top of my head. It's been a few weeks since I initially did this work so I may have forgotten something, but I think the main points are covered.

For reference, here is the dracut call I'm using to build the ramdisks:

dracut -N --install 'tail head awk ifconfig cut expr route ping tgtd tgtadm nc wget curl tftp' \
--kernel-cmdline "rd.shell rdinitdebug rd.neednet=1" \
--include $TMP_MOUNT_PATH/init-func /init-func \
--kver ${KERNEL_VERSION} \
--add-drivers "virtio virtio_net virtio_blk" \
/tmp/ramdisk