Mirage OS Logo

Running MirageOS Xen kernels

By Anil Madhavapeddy - 2013-08-11


Building a MirageOS unikernel for the Xen backend results in a Xen PV kernel with a .xen extension. This must be booted as a normal Xen domU kernel. If you manage your own Xen, you'll be able to use configuration information automatically generated by mirage; some advice on booting with EC2 is also given below and we are curious to hear about others.

Locally Managed Xen

For recent Xen versions, Mirage will attempt to provide a reasonable configuration document for use with the xl tool. The filename will be based on the string argument given to register in the unikernel's config.ml. For instance, if your config.ml has lines like this:

let () =
  register "hello" [main $ default_posix_clock]

then running

    $ mirage configure -t xen

will generate a hello.xl file which references the location where the Xen machine image will be created. After running

    $ make depend
    $ make

the compiled machine image should be present at hello.xen:

    $ ls hello.xen
    ...
    $ sudo xl create hello.xl -c

will try to boot the unikernel and attach a console in the terminal from which the command was run. To detach the console and recover the terminal, use Ctrl-]. The unikernel will continue running, and you can resume viewing the console output with

    $ sudo xl console hello

mirage configure -t xen does its best to generate a good .xl, but frequently the file needs editing to reflect your local configuration. Common changes are the name of the network bridge given on a vif line, and the name or location of disks specified in a disk line.

Amazon EC2

Amazon's Elastic Compute Cloud supports booting user-specified kernels. Currently MirageOS only knows how to create paravirtualized Xen images, so only those instance types which support PV will boot MirageOS unikernels. To see a list of instance types which support PV guests, see the EC2 documentation on virtualization types. Users wishing to run unikernels on the t1.micro instance type will need to create EBS volumes usable in that configuration.

Automated Solutions

Adam Wick created ec2-unikernel for deploying HaLVM on EC2. For users who are happy to install an additional toolchain or outside dependencies, this may be a good, quick, and free solution for deploying Mirage unikernels to EC2.

Less-Automated Solutions

Booting the unikernel requires a two-stage boot process:

  • The VM is launched using a pvgrub stub domain that is a micro-kernel containing a small grub interpreter.
  • pvgrub mounts the root device, looks for /boot/menu.lst, and parses it for the default kernel location on that filesystem.
  • The actual kernel is loaded into memory, and pvgrub execs it, erasing it from memory.
  • From this point on, the second kernel is active and boot proceeds normally.

To boot a MirageOS kernel on EC2, it must first be copied onto a block device known to AWS. After that, the image needs to be bundled into an Amazon Machine Image (AMI), and then registered as a bootable image using the EC2 tools. Once there is a valid AMI registration, it's possible ot create and boot an instance based on the AMI.

Generating an AMI

First download the API tools and AMI tools from Amazon. Set the following environment variables:

  • EC2_USER: 12 digit account number (not email) obtained from the EC2 management console.
  • EC2_ACCESS: from Account/Access credentials in the EC2 management console.
  • EC2_ACCESS_SECRET: as above, in a different tab.
  • EC2_CERT: location of the certificate file you download from the Account/Access page.
  • EC2_PRIVATE_KEY: location of the private key.

There is a script that then takes care of packaging up the MirageOS kernel image and uploading it to Amazon automatically. It is found at scripts/ec2.sh in the mirage repository, and you specify your kernel.xen file as the first argument to the script.

Using micro instances

To use the EC2 t1.micro instances the kernel needs to reside inside an EBS volume. To create a bootable EBS volume containing an MirageOS kernel use the following steps:

  • Start a t1.micro Linux instance: ec2-run-instances ami-7f418316 -k mirage -t t1.micro - We need this instance to access the EBS volume which will later contain our MirageOS kernel
  • Create an EBS volume: ec2-create-volume --size 1 - We use the smallest possible size: 1G
  • Attach volume to your instance: ec2-attach-volume ${VOLUME} -i ${INSTANCE} -d /dev/sdh - Where $VOLUME is your volume id and $INSTANCE is your instance id
  • Login to the miro instance using ssh: ssh -i mirage-ssh-key.pem ec2-user@${PUBLIC-AWS-NAME} - Where $PUBLIC-AWS-NAME is your public DNS name of your running micro instance
  • Create a partition on /dev/sdh and format it using mkfs.ext2 /dev/sdh1 and mount the volume: sudo mount /dev/sdh1 /mnt
  • Copy a Xen MirageOS kernel (e.g. the http example with DHCP enabled) to the running micro instance
  • Login via ssh and move the kernel to /mnt/kernel
  • Create grub directories sudo mkdir -p /mnt/boot/grub/
  • Create grub menu.lst file in /mnt/boot/grub/menu.lst
    default 0
    timeout 1
    title Mirage-Test
         root (hd0,0)
         kernel /kernel
  • Log out of instance
  • Create EBS snapshot ec2-create-snapshot ${VOLUME}
  • You can stop the running micro instance now
  • Register your AMI using ec2-register --snapshot ${SNAPSHOT} --kernel aki-4e7d9527 --architecture x86_64 Note the familiar kernel id: This is the pv-grub kernel that is also used in scripts/ec2.sh.
  • Start your EBS backed MirageOS kernel in a micro instance: ec2-run-instances ${EBSAMI} -k mirage -t t1.micro

Rackspace? Other Xen-based Cloud Providers?

No one has tried this yet. If you do, please let us know.