Run CoreOS on FreeBSD's bhyve

No, I’m not following the hype, only I like to test things plus I feel there will be a growing demand for docker at ${DAYWORK}. I read here and there that CoreOS was the Linux distribution of choice to play with docker, so while at it, I picked up this one to dive into the container world. Finally, I’ve been willing to put my hands on bhyve for quite a while, so I took this opportunity to learn all those new (to me) technologies at once.

Here I’ll write down a quick set of commands and configuration files I found, discovered or modified.

First thing, we’ll have to prepare our FreeBSD system for bhyve. Load the vmm and mndm, respectively bhyve and the serial device module. We’ll also need a tap device and bridging capability in order to bring network to our future virtual machine:

$ cat /boot/loader.conf
vmm_load="YES"
nmdm_load="YES"
if_bridge_load="YES"
if_tap_load="YES"

In /etc/rc.conf, we’ll bring up the tap interface and attach it to a bridge, which will be bond to our physical interface:

cloned_interfaces="bridge0 tap0"
ifconfig_bridge0="addm em0 addm tap0 up"

In order to bring up the tap interface when it’s opened, add the following to /etc/sysctl.conf:

net.link.tap.up_on_open=1

Now that the host OS is ready, let’s fetch CoreOS ISO image. The following link might change, check https://coreos.com/os/docs/latest/booting-with-iso.html

$ curl -O https://stable.release.core-os.net/amd64-usr/current/coreos_production_iso_image.iso

Let’s create a ZFS volume to receive the system:

$ sudo zfs create -V16G -o volmode=dev zroot/coredisk0

To boot a Linux bhyve virtual machine, you’ll need the grub-bhyve package, simply install it using pkg(8):

$ sudo pkg install grub2-bhyve

You’ll then have to create a device.map file:

$ cat device.map
(hd0) /dev/zvol/zroot/coredisk0
(cd0) /usr/home/imil/iso/coreos_production_iso_image.iso

Copy the commands to give to grub in a text file:

$ cat grub-cd0.cfg
linux (cd0)/coreos/vmlinuz coreos.autologin                                     
initrd (cd0)/coreos/cpio.gz                                                     
boot

And load the kernel:

$ sudo grub-bhyve -m device.map -r cd0 -M 1024M coreos < grub-cd0.cfg

You can now fire up the virtual machine:

$ sudo bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s3:0,virtio-blk,/dev/zvol/zroot/coredisk0 -l com1,stdio -c 2 -m 1024M coreos

Once the OS has booted, you should be able to interact with the virtual machine serial console. If there’s no DHCP server on your network, you might have to add an IP address, default route and nameserver:

$ sudo -s
# ip a a 192.168.1.100/24 dev eth0
# route add default gw 192.168.1.254
# echo 'nameserver 8.8.8.8' > /etc/resolv.conf 

It is now time to install the OS to the ZFS volume, seen as a block device from the virtual machine point of view. You’ll find the associated device in /dev/disk/by-id:

$ sudo coreos-install -d /dev/disk/by-id/virtio-BHYVE-580E-3135-7E05 -C stable

Once finished, just shutdown the VM you booted from the ISO image:

$ sudo halt

And kill the virtual machine:

$ sudo bhyvectl --destroy --vm=coreos

Create a new set of grub commands in order to boot from the ZFS volume:

$ cat grub-hd0.cfg 
linux (hd0,gpt1)/coreos/vmlinuz-a console=ttyS0 ro root=LABEL=ROOT usr=LABEL=USR-A coreos.autologin
boot

Note the usr=LABEL=USR-A parameter, it took me a little while to figure out why the system would fail at mounting /usr, as no documentation I found mentionned this.

Load the commands using grub-bhyve:

sudo grub-bhyve -m device.map -r hd0 -M 1024M coreos < grub-hd0.cfg

And finally, fire up the resulting operating system:

$ sudo bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s3:0,virtio-blk,/dev/zvol/zroot/coredisk0 -l com1,stdio -c 2 -m 1024M coreos

You might want to run a headless system, in which case you’ll have to replace stdio with /dev/nmdm0A and connect to the other end of the serial device (/dev/nmdm0B) with any serial console utility like cu(1) or screen.

Resources: