Skip to content

Instantly share code, notes, and snippets.

@StephenSorriaux
Last active November 27, 2018 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StephenSorriaux/eb83139a3d844dfcaa8bef46caab8987 to your computer and use it in GitHub Desktop.
Save StephenSorriaux/eb83139a3d844dfcaa8bef46caab8987 to your computer and use it in GitHub Desktop.
An overview of creating and playing with a µVM using Firecracker

Prerequisites

Follow Firecracker's guidelines. Be sure to download the rootfs and kernel files and to place it next to the firecracker binary.

VM creation

Shell 1 (soon to become VM shell):

sudo rm -rf /tmp/firecracker.sock
sudo ./firecracker --api-sock /tmp/firecracker.sock

Shell 2:

sudo curl --unix-socket /tmp/firecracker.sock -i \
    -X PUT 'http://localhost/drives/rootfs'      \
    -H 'Accept: application/json'                \
    -H 'Content-Type: application/json'          \
    -d '{
        "drive_id": "rootfs",
        "path_on_host": "./hello-rootfs.ext4",
        "is_root_device": true,
        "is_read_only": false
    }'

sudo curl --unix-socket /tmp/firecracker.sock -i \
    -X PUT 'http://localhost/boot-source'   \
    -H 'Accept: application/json'           \
    -H 'Content-Type: application/json'     \
    -d '{
        "kernel_image_path": "./hello-vmlinux.bin",
        "boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
    }'

sudo curl --unix-socket /tmp/firecracker.sock -i \
    -X PUT 'http://localhost/actions'       \
    -H  'Accept: application/json'          \
    -H  'Content-Type: application/json'    \
    -d '{
        "action_type": "InstanceStart"
     }'

Then login, on shell 1, using root:root.

Create a VM with network

Shell 1 (soon to become VM shell):

sudo rm -rf /tmp/firecracker.sock
sudo ./firecracker --api-sock /tmp/firecracker.sock

Shell 2:

sudo curl --unix-socket /tmp/firecracker.sock -i \
    -X PUT 'http://localhost/drives/rootfs'      \
    -H 'Accept: application/json'                \
    -H 'Content-Type: application/json'          \
    -d '{
        "drive_id": "rootfs",
        "path_on_host": "./hello-rootfs.ext4",
        "is_root_device": true,
        "is_read_only": false
    }'

sudo curl --unix-socket /tmp/firecracker.sock -i \
    -X PUT 'http://localhost/boot-source'   \
    -H 'Accept: application/json'           \
    -H 'Content-Type: application/json'     \
    -d '{
        "kernel_image_path": "./hello-vmlinux.bin",
        "boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
    }'

# This will create a veth1337 bridge on the host that
# will be eth0 on the guest. Be sure to randomize
# the guest_mac option.
sudo curl --unix-socket /tmp/firecracker.sock -i \
    -X PUT 'http://localhost/network-interfaces/eth0' \
    -H 'Accept: application/json' \
    -H 'Content-type: application/json' \
    -d '{
        "iface_id": "eth0",
        "host_dev_name": "veth1337",
        "state": "Attached",
        "guest_mac": "00:16:3e:27:d7:85"
    }'

sudo curl --unix-socket /tmp/firecracker.sock -i \
    -X PUT 'http://localhost/actions'       \
    -H  'Accept: application/json'          \
    -H  'Content-Type: application/json'    \
    -d '{
        "action_type": "InstanceStart"
     }'

Once the VM is up, login using root:root.

Network configuration

On the host:

  • set up the bridge using sudo ip link set veth1337 up
  • add an address to your new bridge sudo ip addr add 172.99.0.1/24 dev veth1337

On the guest:

  • be sure that the loopback device is up ip link set lo up
  • bring the newly created interface eth0 up ip link set eth0 up
  • add a new adress to the eth0 interface ip addr add 172.99.0.2/24 dev eth0
  • add the default route if you want to communicate with the outside route add default gw 172.99.0.1

If you want to communicate with the outside, only 1 iptables' rule on the host are missing, on the host:

sudo iptables -t nat -A POSTROUTING -s 172.99.0.0/24 -j MASQUERADE

You should now be abble to ping Google from the guest:

localhost:~# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=123 time=5.740 ms
64 bytes from 8.8.8.8: seq=1 ttl=123 time=3.524 ms
64 bytes from 8.8.8.8: seq=2 ttl=123 time=3.397 ms
64 bytes from 8.8.8.8: seq=3 ttl=123 time=3.335 ms
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss

DNS

Simply use any public DNS available or yours

echo "nameserver 8.8.8.8" >> /etc/resolv.conf

If you are behind a proxy and if you haven't access to any public DNS server, you can:

  • use dnsmasq on your host and configure it to listen on the veth1337 interface, on your guest you would only need to echo "nameserver 172.99.0.1" >> /etc/resolv.conf
  • or add an iptables' rule on your host to redirect the traffic incomming from veth1337 and port 53 to another destination
sudo iptables -t nat -A PREROUTING -p tcp -s 172.99.0.0/24 --dport 53 -j DNAT --to XX.XX.XX.XX:53
sudo iptables -t nat -A PREROUTING -p udp -s 172.99.0.0/24 --dport 53 -j DNAT --to XX.XX.XX.XX:53

then, on the guest echo "nameserver 172.99.0.1" >> /etc/resolv.conf

Defining a logger

Logger are using fifo. Creates two fifo using mkfifo:

mkdir -p /var/log/firecracker/
mkfifo /var/log/firecracker/log.fifo
mkfifo /var/log/firecracker/metrics.fifo

Creates the object using the API:

sudo curl --unix-socket /tmp/firecracker.sock -i \
    -X PUT 'http://localhost/logger'       \
    -H  'Accept: application/json'          \
    -H  'Content-Type: application/json'    \
    -d '{
        "log_fifo": "/var/log/firecracker/log.fifo",
        "metrics_fifo": "/var/log/firecracker/metrics.fifo",
        "level": "Info",
        "show_level": true,
        "show_log_origin": true
     }'

Start the VM and you will be abble to get logs and metrics using cat on the fifo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment