Firecracker and Go Application — Quickstart

Swarvanu Sengupta
4 min readJan 15, 2019

After a very basic hands-on on firecracker and firectl in the earlier blog, in this blog we will check how run our GO application and later build a GO HTTP Sever and run inside Firecracker.

If you are not familier with firecracker and firectl yet, you can check out the earlier blog:

Firecracker works by creating a micro VM using KVM. Each of the microVM has a Kernel and a RootFS. In the previous example when we started the microVm with firectl, we used the downloaded Kernel and RootFS from official example.

firectl \
--kernel=/tmp/hello-vmlinux.bin \
--root-drive=/tmp/hello-rootfs.ext4 \
--kernel-opts="console=ttyS0 noapic reboot=k panic=1 pci=off nomodules rw"

The RootFS ( — root-driv) provides all the root files that lies inside the microVM. In order to run our GO application inside firecracker, we can create a RootFS which has our go application inside of it.

Creating a ROOTFS

To create a ROOTFS for GO application we can use UNIK aka UNIKERNEL Firecracker-go-builder. Although UNIK is a great tool to compile application sources into unikernels, it adds abstractions on the generated filesystems and includes overhead to setup and start UNIK daemon. To know more on UNIK click here.

For simplicity we can instead use the tiny and modified version of a UNIK firecracker compiler to build our ROOTFS available as firecracker-go-template.

Running a simple GO Application in Firecracker

Prerequisites

dockerfirecrackerfirectl

1. Clone firecracker-go-template

Get the firecracker-go-template and build the template docker container.

git clone https://github.com/s8sg/firecracker-go-template.git
make

2. Write your Demo Go application

Below is an example demo GO application that will print Hello message in a loop.

mkdir demo
cat > demo/main.go <<EOF
package main
import (
“fmt”
“os/exec”
“time”
)
func main() {
for {
fmt.Println(“Hello from firecracker”)
out, _ := exec.Command(“uname”, “-a”).CombinedOutput()
fmt.Printf(“OS Version: %s\n”, string(out))
time.Sleep(10 * time.Second)
}
}
EOF

3. Build root filesystem using `build` script

build script takes the name of the application folder and RootFS desired name.

./build demo my_root_fs

After the script we will have RootFS file as ./my_root_fs.

ll ./my_root_fs
-rw-r--r-- 1 root root 52428800 Jan 15 15:48 my_root_fs

4. Use `firectl` to run firecracker with generated rootfs

ROOTFS="$(readlink -f my_root_fs)"
sudo firectl \
--kernel=/tmp/hello-vmlinux.bin \
--root-drive=$ROOTFS \
--kernel-opts="console=ttyS0 noapic reboot=k panic=1 pci=off nomodules rw"

It will start your demo application and start printing Hello message on the console. Here you successfully created a Go application running in the firecracker.

Although this application doesn’t really interact with outside world. So instead we can create a Go HTTP server running inside firecracker.

Running a simple GO HTTP Server in Firecracker

HTTP request need the MicroVM to have network connection. In order to enable networking in Firecracker VM you need to setup a tap interface discussed in the previous blog. Alternatively you can follow the below quick steps.

Setup tap interface — Skip if you already created

sudo ip tuntap add tap0 mode tap # user $(id -u) group $(id -g)
sudo ip addr add 172.20.0.1/24 dev tap0
sudo ip link set tap0 up

Set your main interface device. If you have different name check it with ifconfig command.

DEVICE_NAME=eth0

Provide iptables rules to enable packet forwarding.

sudo sh -c “echo 1 > /proc/sys/net/ipv4/ip_forward”
sudo iptables -t nat -A POSTROUTING -o $DEVICE_NAME -j MASQUERADE
sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i tap0 -o $DEVICE_NAME -j ACCEPT

1. Write your Demo Go HTTP Server

Below is an example demo GO HTTP Server. It spit back a Hello message with the PATH.

mkdir demoHTTP
cat > demoHTTP/main.go <<EOF
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
EOF

2. Build root filesystem using `build` script

build script takes the name of the application folder and RootFS desired name along with the intended ip and gateway address.

./build demoHTTP my_root_fs 172.20.0.2/24 172.20.0.1

The IP address and Gateway is stored inside the RootFS, which is applied at MicroVM startup.

3. Use `firectl` to run firecracker with your rootfs

MAC="$(cat /sys/class/net/tap0/address)"
ROOTFS="$(readlink -f my_root_fs)"
sudo firectl \
--kernel=/tmp/hello-vmlinux.bin \
--root-drive=$ROOTFS \
--kernel-opts="console=ttyS0 noapic reboot=k panic=1 pci=off nomodules rw" \
--tap-device=tap0/$MAC

It will start your demo application server and auto configure it to listen on http://172.20.0.2:8080.

4. Validate connectivity

curl http://172.20.0.2:8080/firecracker

it will spit back

Hi there, I love firecracker!

Now you successfully ran your Go HTTP Server inside firecracker. You can now try to port your own application in firecracker.

If you enjoyed this article, please spare me some claps :)

Feel free to provide feedback. Thank You :)

--

--

Swarvanu Sengupta

Senior Full Stack Engineer at GoJek, Love Creating Stuff, Extremely Curious, Anxious and Laborious. Into outdoor and Reading | He/Him | Views are my own