Firecracker and Go Application — Quickstart
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 mainimport (
"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 :)