Firecracker — это монитор виртуальных машин с минимальным набором устройств, который AWS открыла в 2018 году и с тех пор использует в Lambda и Fargate. В отличие от QEMU, здесь нет эмуляции видеокарты, USB и десятков контроллеров: только VirtIO-диск, сеть, последовательный порт и небольшой HTTP-API поверх Unix-сокета. За счёт этого экземпляр запускается за десятые доли секунды и занимает единицы мегабайт памяти. Разберём, как поднять Firecracker на своём сервере.

Почему микровиртуальная машина, а не контейнер

Контейнер делит ядро с хостом. Это быстро и удобно, но граница изоляции проходит через namespaces, cgroups и seccomp, а ошибка в ядре или в настройке прав открывает путь к соседям. Firecracker даёт границу гипервизора: у каждого приложения собственное ядро. Накладные расходы ниже, чем у классической ВМ: нет BIOS и полной эмуляции оборудования.

Микровиртуальные машины уместны для multi-tenant-платформ, запуска недоверенного кода, изолированных CI-раннеров и функций, которые должны стартовать мгновенно. Они не заменяют контейнеры там, где нужен GPU, проброс USB или сложная эмуляция legacy-устройств.

Требования и проверка хоста

Нужен Linux с доступом к /dev/kvm, процессор с VT-x или AMD-V и права root для настройки сети и jailer. В облаке подойдёт bare metal либо экземпляр с вложенной виртуализацией; на обычной VPS без nested virtualization Firecracker не запустится. Сначала проверяем базу:

ls -l /dev/kvm
grep -cE 'vmx|svm' /proc/cpuinfo
sudo usermod -aG kvm "$USER"
newgrp kvm

Если /dev/kvm отсутствует, включите виртуализацию в BIOS или UEFI. Если файл есть, но доступ запрещён, проверьте группу kvm и права.

Установка

Бинарники распространяются статическими файлами, собранными на Rust. Скачаем последний релиз и положим в /usr/local/bin. Для разбора JSON в скрипте понадобится jq:

ARCH=$(uname -m)
TAG=$(curl -s https://api.github.com/repos/firecracker-microvm/firecracker/releases/latest | jq -r .tag_name)
curl -L -o fc.tgz "https://github.com/firecracker-microvm/firecracker/releases/download/${TAG}/firecracker-${TAG}-${ARCH}.tgz"
tar xzf fc.tgz
sudo install -m 0755 release-*/firecracker-* /usr/local/bin/firecracker
sudo install -m 0755 release-*/jailer-* /usr/local/bin/jailer

Проверьте установку командой firecracker --version. У процесса нет демона и конфигурационного файла по умолчанию: всем управляет API.

Корневая файловая система и ядро

Firecracker запускает несжатое ядро в формате ELF, а не bzImage. Возьмите готовый vmlinux из CI-артефактов Firecracker или соберите ядро со встроенными virtio_blk, virtio_net и ext4. Положите его в /srv/fc/vmlinux, а корневую систему соберите через debootstrap:

sudo apt install -y debootstrap
sudo debootstrap --variant=minbase bookworm /srv/fc/rootfs http://deb.debian.org/debian
sudo truncate -s 2G /srv/fc/rootfs.ext4 && sudo mkfs.ext4 -F /srv/fc/rootfs.ext4
sudo mount /srv/fc/rootfs.ext4 /mnt && sudo cp -a /srv/fc/rootfs/. /mnt/

Внутри образа нужно разрешить вход и включить последовательную консоль, иначе гостя будет не видно:

echo 'root:root' | sudo chroot /mnt chpasswd
sudo systemctl --root=/mnt enable serial-getty@ttyS0.service
sudo umount /mnt

Пароль root:root годится только для локального теста. Образ делайте небольшим и по возможности только для чтения, а данные выносите на отдельный диск.

Запуск через API

Процесс стартует с Unix-сокетом, после чего конфигурация отправляется HTTP-запросами. Порядок важен: сначала параметры машины, затем ядро и диски, и только потом команда запуска.

firecracker --api-sock /tmp/fc.sock --level Debug
curl --unix-socket /tmp/fc.sock -X PUT http://localhost/machine-config -H 'Content-Type: application/json' -d '{"vcpu_count":2,"mem_size_mib":512}'
curl --unix-socket /tmp/fc.sock -X PUT http://localhost/boot-source -H 'Content-Type: application/json' -d '{"kernel_image_path":"/srv/fc/vmlinux","boot_args":"console=ttyS0 reboot=k panic=1 root=/dev/vda rw"}'
curl --unix-socket /tmp/fc.sock -X PUT http://localhost/drives/rootfs -H 'Content-Type: application/json' -d '{"drive_id":"rootfs","path_on_host":"/srv/fc/rootfs.ext4","is_root_device":true,"is_read_only":false}'
curl --unix-socket /tmp/fc.sock -X PUT http://localhost/actions -H 'Content-Type: application/json' -d '{"action_type":"InstanceStart"}'

Сокет не имеет аутентификации: не выставляйте его в сеть и не давайте посторонним. API принимает запросы асинхронно: после InstanceStart дождитесь загрузки гостя.

Сеть и jailer

Гостю нужен tap-интерфейс на хосте. Простейшая схема — NAT через основной интерфейс. В госте поднимите eth0 с адресом 172.16.0.2/24 и шлюзом 172.16.0.1:

sudo ip tuntap add dev fc0 mode tap
sudo ip addr add 172.16.0.1/24 dev fc0
sudo ip link set fc0 up
sudo sysctl -w net.ipv4.ip_forward=1
HOST_IFACE=$(ip route show default | awk '{print $5; exit}')
sudo iptables -t nat -A POSTROUTING -o "$HOST_IFACE" -j MASQUERADE
curl --unix-socket /tmp/fc.sock -X PUT http://localhost/network-interfaces/eth0 -H 'Content-Type: application/json' -d '{"iface_id":"eth0","host_dev_name":"fc0","guest_mac":"AA:FC:00:00:00:01"}'

Для production-запуска используйте jailer: он делает chroot, сбрасывает привилегии и копирует бинарник внутрь. Ядро и диски тоже должны лежать внутри chroot. Запуск выглядит так:

sudo jailer --id fc-01 --exec-file /usr/local/bin/firecracker --uid 1000 --gid 1000 --chroot-base-dir /srv/jail -- --api-sock /fc.sock

Снаружи сокет окажется в /srv/jail/firecracker/fc-01/root/fc.sock. Не запускайте машины с одинаковым --id.

Снимки и восстановление

Firecracker умеет сохранять память и состояние устройств. Перед снимком машину нужно поставить на паузу, иначе получите несогласованное состояние:

curl --unix-socket /tmp/fc.sock -X PATCH http://localhost/vm -H 'Content-Type: application/json' -d '{"state":"Paused"}'
curl --unix-socket /tmp/fc.sock -X PUT http://localhost/snapshot/create -H 'Content-Type: application/json' -d '{"snapshot_type":"Full","snapshot_path":"/srv/fc/snap.bin","mem_file_path":"/srv/fc/mem.bin"}'

Восстановление делается на новом процессе с другим сокетом. Снимок содержит дамп памяти, то есть потенциально ключи и токены: храните его как секрет. Снимок привязан к версии Firecracker и набору функций CPU, поэтому после обновления проверяйте совместимость на стенде.

Диагностика

Смотрите лог процесса: там видны ошибки KVM, загрузки ядра и монтирования корня. Полезные проверки:

  • sudo dmesg | grep -i kvm — доступна ли аппаратная виртуализация;
  • ss -xlp | grep fc.sock — слушает ли процесс управляющий сокет;
  • curl --unix-socket /tmp/fc.sock http://localhost/machine-config — применилась ли конфигурация;
  • curl --unix-socket /tmp/fc.sock -X PUT http://localhost/metrics -H 'Content-Type: application/json' -d '{"metrics_path":"/srv/fc/metrics.json"}' — включить сбор метрик.

Если гость не поднимается, чаще всего причина в сжатом ядре, неверном root= или отсутствии драйвера VirtIO.

Чек-лист перед production

  • Хост с KVM и подтверждённой вложенной виртуализацией.
  • Ядро в формате несжатого ELF, версия зафиксирована.
  • Каждая машина запущена через jailer со своим uid, gid и chroot.
  • Управляющий сокет недоступен другим пользователям.
  • Снимки шифруются, восстановление регулярно проверяется.
  • Настроены метрики и алерты по ошибкам запуска.

Итог

Firecracker даёт изоляцию гипервизора с почти контейнерной скоростью запуска. Цена — ручная сборка ядра и rootfs, настройка tap-сети и дисциплина вокруг API-сокета. Начните с одной машины на тестовом хосте, пройдите путь до снимка и восстановления, а затем переносите схему в оркестратор. Если нужен GPU или сложное оборудование, микровиртуальная машина не лучший выбор: там остаются обычные виртуальные машины и контейнеры.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте