Virtualization

Setting Up FireCracker Microvm

Understand how Qemu/KVM plays a role in cloud computing

Setting Up FireCracker Microvm

Image of Kuldeep Ranjan
Published on June 30, 2024
6 min read

An open source Virtual Machine Monitor (VMM) specialized for serverless workloads, for containers, functions and other compute workloads by AWS.

This article focus on spinning up a micro VMs, and not on How and Working of FireCracker. I will soon write an article on that too.

A lot of commands are directly pasted from getting started doc provided in official repo, You can follow that or from here with some more explanation why are we executing that command in detail, Yes obviously If you are dig deeper person like me.

KVM as you should must be aware of is a linux kernel module which exposes Hardware functionality to support hardware assisted virtualization. It’s the core of FireCracker.

Generally projects like Kata Containers, Intel’s clear Containers choosen hypervisor based virtualization to achieve isolation, and in almost majority has chosen the QEMU/KVM as the base.

FireCracker goes slightly different than these traditional way and replaces QEMU completely but kept KVM intact. So we need KVM in order to work FireCracker.

So Starting with you need to choose whether you cpu supports Hardware assisted Virtualization.

Determine the System Architecture.

You can check KVM support by following command,

lsmod | grep kvm

Typical Output will be like,

kvm_intel             487424  0
kvm                  1409024  1 kvm_intel
irqbypass              12288  1 kvm

Generally KVM module is present in “/dev/kvm”

You as a user need to read and write permission to this file in order to start FireCracker.

This is generally managed by ACL(Access Control List), that which file has which kind of permission to the user.

We will now provide this user READ/WRITE permission to this file by following command,

sudo setfacl -m u:${USER}:rw /dev/kvm

Once executed You can check Whether you got the permission or not by executing this command.

[ -r /dev/kvm ] && [ -w /dev/kvm ] && echo "OK" || echo "FAIL"

Now we are done with checking the requirements and getting access to kvm module.

In order to run any VM, You need a kernel and root file system for getting started.

Linux kernel are maintained by Linus Torvalds and the Linux community, different distributions (distros) of Linux may use different versions of the kernel.

The term “root file system” in Linux refers to the primary filesystem that contains the operating system’s essential files and directories, including the kernel, system libraries, configuration files, and essential system utilities. It is denoted by the / (root) directory.

During boot process, boot loader like grub first loads the operating system kernel into the memory and then init process starts, one of the initialization process involves the mounting of root file system.

Let’s just simply fetch as it is mentioned in getting started doc according to our system architecture.

Getting Kernel and Rfs

ARCH="$(uname -m)"

wget https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.7/${ARCH}/vmlinux-5.10.204

wget https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.7/${ARCH}/ubuntu-22.04.ext4

wget https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.7/${ARCH}/ubuntu-22.04.id_rsa

chmod 400 ./ubuntu-22.04.id_rsa

SSH Key is used to get access to VM once started.

Once we have it we need FireCracker binary now, either build it by self using docker or download the latest release (here).

ARCH="$(uname -m)"
release_url="https://github.com/firecracker-microvm/firecracker/releases"
latest=$(basename $(curl -fsSLI -o /dev/null -w  %{url_effective} ${release_url}/latest))
curl -L ${release_url}/download/${latest}/firecracker-${latest}-${ARCH}.tgz \
| tar -xz

mv release-${latest}-$(uname -m)/firecracker-${latest}-${ARCH} firecracker

Okay, Now is the best part.

Setting up Networking

We have Network Sockets and Unix Sockets for communication.

Network Sockets are used for communication between processes on different host connected via network. whereas Unix Sockets are used for communication between processes like system services within the same host.

And they need file system path for address or as an identifier unlike ip address or port for network sockets.

Let’s Specify API Unix Socket path now and start the Cracker. It exposes Rest api for its functionality.

API_SOCKET="/tmp/firecracker.socket"
sudo rm -f $API_SOCKET
sudo ./firecracker --api-sock "${API_SOCKET}"

Okay so FireCracker Process started, Let’s start the Virtual Machine Now.

Let’s understand first some network nitty gritty details.

We need to create a tap pair in host in order to flow the traffic in and out from the VM.

Follow the steps below,

Specifying the variables in shell.

TAP_DEV="tap0"
TAP_IP="172.16.102.1" #Make sure this ip address should be out of host subnet
MASK_SHORT="/24"
sudo ip link del "$TAP_DEV" 2> /dev/null || true
sudo ip tuntap add dev "$TAP_DEV" mode tap
sudo ip addr add "${TAP_IP}${MASK_SHORT}" dev "$TAP_DEV"
sudo ip link set dev "$TAP_DEV" up

Above command will first delete the any tap device with name “tap0” if present, and add the new interface with the assigned ip address( should be out host subnet).

Ip forwarding and setting host interface variable, make sure to check your host interface name with command

ip add show
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
HOST_IFACE="eth0"

Finally we will configure iptables rules to allow NAT and packet forwarding to/from the microVM to external network.

sudo iptables -t nat -D POSTROUTING -o "$HOST_IFACE" -j MASQUERADE || true
sudo iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT \
    || true
sudo iptables -D FORWARD -i tap0 -o "$HOST_IFACE" -j ACCEPT || true
sudo iptables -t nat -A POSTROUTING -o "$HOST_IFACE" -j MASQUERADE
sudo iptables -I FORWARD 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo iptables -I FORWARD 1 -i tap0 -o "$HOST_IFACE" -j ACCEPT

Booting Up

So Networking part is done now.

Firecracker needs kernel image and rfs to start the microVM.

Let’s specify the same and some boot arguments and the architecture of the host system

KERNEL="./vmlinux-5.10.209"
KERNEL_BOOT_ARGS="console=ttyS0 reboot=k panic=1 pci=off"
ARCH=$(uname -m)
curl -X PUT --unix-socket "${API_SOCKET}" \
    --data "{
        \"kernel_image_path\": \"${KERNEL}\",
        \"boot_args\": \"${KERNEL_BOOT_ARGS}\"
    }" \
    "http://localhost/boot-source"

Similary for root file system,

ROOTFS="./ubuntu-22.04.ext4"

curl -X PUT --unix-socket "${API_SOCKET}" \
    --data "{
        \"drive_id\": \"rootfs\",
        \"path_on_host\": \"${ROOTFS}\",
        \"is_root_device\": true,
        \"is_read_only\": false
    }" \
    "http://localhost/drives/rootfs"

Set the mac address and the network interface,

FC_MAC="06:00:AC:10:00:02"

curl -X PUT --unix-socket "${API_SOCKET}" \
    --data "{
        \"iface_id\": \"net1\",
        \"guest_mac\": \"$FC_MAC\",
        \"host_dev_name\": \"$TAP_DEV\"
    }" \
    "http://localhost/network-interfaces/net1"

So All done setting up the configuration, let’s start the microVM now with the following command, If every command executed succesfully VM will spinUp.

curl -X PUT --unix-socket "${API_SOCKET}" \
    --data "{
        \"action_type\": \"InstanceStart\"
    }" \
    "http://localhost/actions"

That’s it for this article, Thanks for reading.

I will be writing more such articles on how to run firecracker inside docker and more network management configuration.