Firecracker MicroVM

Amazon hat auf der AWS re:Invent das Virtualisierungs-Tool Firecracker OpenSource gestellt. Hauptziel bei der Entwicklung war, kleine VMs schnell zu starten die so sicher sind, dass fremder Code darin ausgeführt werden kann. Laut Amazon sind diese beim Serverless Dienst Lambda im Einsatz und dadurch schon millionenfach geprüft. In Zukunft möchte ich versuchen, dass Docker Container automatisch in VMs gestartet werden.

Teil der Serie
  1. Firecracker MicroVM Einstieg
  2. Firecracker VM sicher mit Jailer starten

Firecracker versucht dafür mit möglichst wenig Overhead vCPUs, Arbeitsspeicher und ein Dateisystem bereitzustellen. Es können flexibel über eine REST Schnittstelle Festplatten, Netzwerke und Limitierungen gesetzt werden. Aktuell werden nur Intel CPUs unterstützt. Dieses Jahr (2019) sollen AMD und ARM folgen.

Kurz zusammengefasst wird ein Kernel Image, Root Dateisystem und Startargumente gesetzt. In die VM konnte ich mich in unter 2 Sekunden nach Start bereits einloggen.

Firecracker in der Cloud link

Amazon selbst empfiehlt eine EC2 .metal instance. Ich habe Firecracker bei DigitalOcean mit dem kleinsten Droplet laufen lassen.

Installieren link

Die Firecracker Binary hat keine Software-Abhängigkeiten und kann einfach auf einem x86_64 Linux heruntergeladen und gestartet werden.

curl -LOJ https://github.com/firecracker-microvm/firecracker/releases/download/v${latest}/firecracker-v${latest}

Im Anschluss kann fürs einfachere Handling die Datei noch umbenannt und die Rechte gesetzt werden:

mv firecracker-v${latest} firecracker
chmod +x firecracker

Erste Schritte link

Für Produktionssysteme sollte Firecracker mit jailer abgesichert werden. Wie das funktioniert werde ich in einem extra Beitrag beschreiben. Eine (hoffentlich) immer aktuelle Installationsanleitung ist im Getting started Artikel zu finden.

Die Firecracker API läuft über einen Socket, der bei Start automatisch angelegt wird. Zur Sicherheit sollte der Pfad vor dem Start einmal gelöscht werden.

rm -f /tmp/firecracker.socket

./firecracker --api-sock /tmp/firecracker.socket

Um eine Firecracker VM zu starten wird ein Linux Kernel und ein ext4 Dateisystem benötigt. AWS stellt hier beides zum ausprobieren zur Verfügung.

curl -fsSL -o hello-vmlinux.bin https://s3.amazonaws.com/spec.ccfc.min/img/hello/kernel/hello-vmlinux.bin
curl -fsSL -o hello-rootfs.ext4 https://s3.amazonaws.com/spec.ccfc.min/img/hello/fsfiles/hello-rootfs.ext4

Anschließend kann in einer neuen Konsole die API genutzt werden. Dabei wird curl angewiesen die HTTP Requests über den erstellten Socket zu schicken.

Gast Kernel

curl --unix-socket /tmp/firecracker.socket -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"
    }'

Gast Rootfs

curl --unix-socket /tmp/firecracker.socket -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
    }'

Gast Maschine starten

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

In der ersten Konsole, in der Firecracker gestartet wurde, fährt nun die VM hoch. Bei Nutzung der AWS hello-rootfs.ext4 kann sich anschließend mit root und als Passwort root angemeldet werden. Zum Herunterfahren wird mit reboot ein Neustart erzwungen, denn die VM nicht durchführt.

In meinen Tests startet die VM mit 1GB Ram bei einer vCPU (DigitalOcean Droplet) in ca 1.1sek.

Ob die virtuelle Maschine läuft kann über den Prozessmanager mit dem Befehl ps aux | grep firecracker gesehen werden.

VM Limitieren

curl --unix-socket /tmp/firecracker.socket -i  \
    -X PUT 'http://localhost/machine-config' \
    -H 'Accept: application/json'            \
    -H 'Content-Type: application/json'      \
    -d '{
        "vcpu_count": 2,
        "mem_size_mib": 1024
    }'

Herunterfahren

Neben einem Neustart innerhalb der VM kann diese auch von außen über die API heruntergefahren werden.

curl --unix-socket /tmp/firecracker.socket -i \
    -X PUT "http://localhost/actions" \
    -H  "accept: application/json" \
    -H  "Content-Type: application/json" \
    -d "{
             \"action_type\": \"SendCtrlAltDel\"
    }"

Logs

# Create the required named pipes.
mkfifo logs.fifo
mkfifo metrics.fifo

# Configure the Logger.
curl --unix-socket /tmp/firecracker.socket -i \
    -X PUT "http://localhost/logger" \
    -H "accept: application/json" \
    -H "Content-Type: application/json" \
    -d "{
             \"log_fifo\": \"logs.fifo\",
             \"metrics_fifo\": \"metrics.fifo\"
    }"

CLI firectl link

Die Firecracker firectl ermöglicht über die Firecracker API eine VM zu starten. Der Vorteil gegenüber der direkten API Nutzung besteht darin, das nur ein Command mit vielen Flags genutzt wird anstatt mehreren REST Befehlen.

SDK link

Um programmatisch MicroVMs zu verwalten, gibt es eine Go SDK die auch von firectl verwendet wird.

Stand vom 19.03.2019