Библиотека — FreeBSD — bhyve: виртуализация после jails [X]
Шифр
freebsd-bhyve
Разделы
freebsd tooling
Сверено
2 сентября — в этот день утверждения статьи сверялись с первоисточниками, а не правился текст
Объём
14 449 знаков · 18 разделов · чтения около 15 минут

FreeBSD — bhyve: виртуализация после jails


Обзор

Jails решают задачу изоляции настолько хорошо, что вопрос «а зачем здесь вообще виртуальная машина» законен. Ответ у него ровно один, зато не обходимый: jail разделяет ядро с хостом. Всё, что упирается в ядро — другая операционная система, другая версия FreeBSD, отладка драйвера, тестирование обновления, которое может это ядро уронить, — в jail не помещается принципиально, а не по недоработке.

bhyve закрывает эту нишу. Это гипервизор второго типа, живущий в базовой системе с FreeBSD 10, устроенный минималистично: никакой эмуляции legacy-железа ради совместимости, ставка на virtio и UEFI, управление обычными утилитами командной строки. Он заметно проще KVM с libvirt и заметно менее функционален — и то, и другое стоит понимать до того, как строить на нём инфраструктуру.

Статья продолжает FreeBSD: Jails и опирается на сетевую часть из FreeBSD: сеть — мосты и tap-интерфейсы там уже разобраны.

Версии-якоря: FreeBSD 15.1 (актуальный релиз на момент написания) и 14.4 в параллельно поддерживаемой ветке 14; 14.5 на начало сентября 2026 в состоянии RC, релиз назначен на 8 сентября. vm-bhyve 1.6.2. Часть возможностей, о которых пойдёт речь в разделе про непривилегированный запуск, есть только в -CURRENT — это оговорено отдельно.

Где проходит граница

Разница между jail и виртуальной машиной — не в степени изоляции, а в том, что именно изолируется.

jail bhyve
Ядро общее с хостом своё
Гостевая ОС только FreeBSD (плюс Linux ABI) любая с поддержкой платформы
Загрузка секунды, фактически запуск процессов полный цикл, как у железа
Память берётся из общего пула по мере надобности резервируется целиком при старте
Накладные расходы CPU практически нулевые заметные, но небольшие благодаря virtio
Модули ядра, sysctl уровня ядра нет, ядро одно да, своё ядро
Плотность на хосте сотни десятки

Практическое правило: если гость — FreeBSD той же мажорной версии и ему не нужно трогать ядро, это jail, и обсуждать нечего. bhyve берут, когда нужен Linux, Windows, другая версия FreeBSD, или когда гость должен иметь возможность уронить своё ядро, не задев хост.

Главная цена — память. Jail берёт столько, сколько реально использует; виртуальной машине память отдаётся при старте целиком и хосту не возвращается. Механизма вроде ballooning у bhyve нет. На машине с 8 ГБ три виртуалки по 2 ГБ — это минус 6 ГБ, независимо от того, чем они заняты, и это чаще всего и определяет реальный предел плотности.

Архитектура

Требования к железу

На amd64 нужен процессор с VT-x и EPT (Intel) либо с SVM (AMD). Проверяется через sysctl:

sysctl hw.vmm 2>/dev/null || kldload vmm
grep -o 'VMX\|SVM\|POPCNT\|EPT' /var/run/dmesg.boot | sort -u

Помимо amd64, современный bhyve умеет arm64 (загрузочный CPU должен стартовать в EL2, нужен контроллер прерываний GICv3) и riscv (требуется расширение H). Это стоит знать, но основной сценарий по-прежнему amd64.

Отдельно: проброс PCI-устройств требует VT-d и доступен только на amd64.

Модуль и утилиты

Работа держится на модуле ядра vmm.ko и трёх утилитах:

kldload vmm                    # либо vmm_load="YES" в /boot/loader.conf
  • bhyveload — загрузчик для гостевой FreeBSD: читает ядро гостя прямо из образа и передаёт управление. Работает только с FreeBSD.
  • bhyve — собственно гипервизор, он же описание виртуального железа: устройства перечисляются флагами командной строки.
  • bhyvectl — управление созданной машиной, в первую очередь --destroy.

Последний пункт — источник самой частой ошибки новичка. Виртуальная машина в bhyve существует как объект ядра и переживает завершение процесса bhyve. Если гость выключился, а машина не уничтожена, повторный запуск с тем же именем упрётся в занятое имя:

bhyvectl --vm=guest --destroy

Обёртки вроде vm-bhyve делают это автоматически, и именно поэтому с ними жить проще.

Загрузка гостя

Способов два, и выбор определяется гостевой системой.

Для FreeBSD — bhyveload, исторически первый механизм: он понимает загрузчик FreeBSD и не требует прошивки.

Для всего остального — UEFI: bhyve загружает прошивку из порта uefi-edk2-bhyve и дальше ведёт себя как обычная машина с UEFI.

bhyve -c 2 -m 2G \
  -s 0,hostbridge \
  -s 3,virtio-blk,/vm/linux/disk.img \
  -s 5,virtio-net,tap0 \
  -s 29,fbuf,tcp=127.0.0.1:5900,w=1024,h=768 \
  -s 30,xhci,tablet \
  -s 31,lpc -l com1,/dev/nmdm0A \
  -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \
  -H -P linuxvm

Читается эта строка как список слотов PCI: -s <слот>,<устройство>,<параметры>. Слот 31 занят lpc не случайно — это устройство несёт последовательный порт и должно жить именно там.

Два флага в конце заслуживают отдельного внимания, потому что их отсутствие даёт неочевидный симптом. -H заставляет виртуальный процессор отдавать управление при инструкции HLT; без него простаивающий гость будет занимать 100% ядра хоста — виртуалка ничего не делает, а top на хосте показывает полную загрузку. -P делает то же для инструкции PAUSE.

Устройства virtio

Смысл virtio в том, что гость знает о виртуализации и не притворяется, будто общается с реальным контроллером. Вместо эмуляции регистров — кольцевые буферы в разделяемой памяти, то есть на порядок меньше переходов в гипервизор.

Основные типы: virtio-blk (диски), virtio-net (сеть), virtio-scsi, virtio-9p для проброса каталога хоста внутрь гостя, virtio-rnd (энтропия для гостя — на свежеразвёрнутой машине это не мелочь), virtio-console. Для гостей без драйверов virtio есть эмуляция: ahci-hd и ahci-cd для дисков, nvme для NVMe-контроллера, e1000 для сети. Пользоваться ими стоит только там, где иначе никак, — это медленнее в разы.

Хранилище: zvol или файл

zvol файл-образ
Производительность выше, минус слой файловой системы ниже на записи
Снепшоты ZFS-снепшоты и клоны как есть только снепшот всего датасета целиком
Перенос на другую машину zfs send обычный cp/scp
Разреженность -s при создании зависит от способа создания
Просмотр содержимого с хоста сложно легко смонтировать
zfs create -V 20G -o volmode=dev zroot/vm/linuxvm

Рекомендация простая: на хосте с ZFS — zvol. Аргумент не столько в скорости, сколько в снепшотах: снепшот zvol перед обновлением гостя — это откат одной командой, и работает он независимо от того, что за система внутри. Файл-образ оправдан на UFS-хосте и там, где важна тривиальность переноса.

Отдельно про volmode=dev: без него zvol получает запись в /dev/zvol и хост начинает пытаться разбирать таблицу разделов гостя — на хосте появляются лишние устройства, а при неудачном стечении обстоятельств гостевой пул может быть импортирован хостом. Для дисков виртуалок это правильный режим по умолчанию.

Сеть

Схема стандартная: на каждую машину по tap-интерфейсу, все они в мосту вместе с физическим интерфейсом.

sysrc cloned_interfaces="bridge0 tap0"
sysrc ifconfig_bridge0="addm em0 addm tap0 up"
service netif restart

Подробнее про мосты и клонируемые интерфейсы — в статье про сеть FreeBSD.

Один нюанс, на котором спотыкаются регулярно: tap-интерфейс поднимается только когда его открывает процесс, и мост может не пропускать трафик до старта виртуалки. Лечится переключателем:

sysctl net.link.tap.up_on_open=1

Если виртуалки не должны быть видны в физической сети, вместо моста с em0 строится изолированный мост с адресом на хосте и NAT через PF — конструкция та же, что для jail и для домашних сервисов за NAT, и она разобрана в самохостинге за NAT.

Консоль

Для текстовых гостей — nullmodem-пара nmdm: одна её сторона отдаётся виртуалке, ко второй подключаются с хоста.

kldload nmdm
cu -l /dev/nmdm0B

Выход из cu — ~., и это стоит запомнить до, а не после подключения.

Для графических гостей — VNC через устройство fbuf. Слушать он должен на 127.0.0.1 и пробрасываться по SSH: собственного шифрования у встроенного VNC-сервера нет, и выставлять его в сеть нельзя.

ssh -L 5900:127.0.0.1:5900 user@vmhost

Полезная деталь: устройство xhci,tablet даёт абсолютное позиционирование указателя. Без него курсор в VNC-клиенте живёт своей жизнью и «уезжает» относительно реального.

vm-bhyve

Голый bhyve — это ручная сборка командной строки на два десятка аргументов, ручное создание tap-интерфейсов, ручной bhyvectl --destroy и отсутствие автозапуска. Для одной тестовой машины терпимо, для постоянной эксплуатации — нет.

vm-bhyve (1.6.2) закрывает ровно это: конфигурация машин в текстовых файлах, управление мостами, интеграция с rc, автозапуск при загрузке и корректная уборка после остановки.

pkg install vm-bhyve
zfs create zroot/vm
sysrc vm_enable="YES" vm_dir="zfs:zroot/vm"
vm init
vm switch create public
vm switch add public em0
vm create -t freebsd-zvol -s 20G guest
vm install guest FreeBSD-15.1-RELEASE-amd64-disc1.iso
vm console guest

Автозапуск задаётся списком: sysrc vm_list="guest1 guest2", порядок в списке — порядок старта.

Существуют и альтернативы: CBSD — более крупный комбайн, управляющий и jail'ами, и виртуалками; bmd и chyves — другие обёртки разной степени живости. Для типовой задачи «несколько виртуалок на сервере» vm-bhyve — разумный выбор по соотношению возможностей к сложности.

Нюансы и trade-off'ы

PCI passthrough

Устройство отдаётся гостю целиком, минуя хост. Требует VT-d, доступен только на amd64, и хост должен заранее отпустить устройство драйверу ppt:

pptdevs="2/0/0"

Ограничения жёсткие. Устройство перестаёт быть доступно хосту полностью. Проброс не работает при запуске bhyve в jail или без прав root, поскольку требует записи в /dev/pci. Группировка устройств по IOMMU может заставить пробрасывать больше, чем хотелось: если видеокарта делит группу с контроллером USB, отдавать придётся оба. И миграция машины с проброшенным устройством невозможна в принципе.

Чего нет по сравнению с KVM

Честный список, который стоит прочитать до выбора платформы:

  • Живой миграции нет. Работа над ней ведётся давно, но полагаться на неё нельзя.
  • Ballooning отсутствует: память отдаётся при старте и не возвращается.
  • Снепшот работающей машины (suspend/resume состояния VM) — экспериментальная возможность, требующая сборки с отдельной опцией; сравнивать с virsh save рано. Снепшот zvol с выключенным гостем работает надёжно и закрывает большую часть потребности.
  • Экосистема управления несопоставима: нет libvirt и всего, что на него опирается — Terraform-провайдеров, оркестраторов, готового мониторинга.
  • Windows-гости работают, но требуют драйверов virtio отдельной установкой, и «просто работает» это назвать нельзя.

Из этого следует прямой вывод, который лучше сделать заранее: если задача — кластер с миграцией и оркестрацией, честнее взять Linux с KVM. bhyve хорош там, где хост уже FreeBSD, машин единицы-десятки, и нужен именно другой гость, а не платформа виртуализации как таковая.

Непривилегированный запуск

В -CURRENT появился режим, позволяющий запускать виртуальные машины не от root: управляющее устройство переименовано в /dev/vmmctl, и доступ к нему получают члены группы vmm. В релизах 15.1 и 14.4 этого ещё нет — там создание и уничтожение машины требует привилегий суперпользователя. Если вы читаете совет про группу vmm и он не работает, дело в версии, а не в конфигурации.

Сравнение с Linux: KVM и libvirt

bhyve KVM + libvirt
Где живёт базовая система FreeBSD модуль ядра Linux плюс QEMU
Конфигурация машины аргументы командной строки или конфиг обёртки XML, управляемый через virsh
Живая миграция нет да
Ballooning нет да
Снепшоты состояния VM экспериментально да
Проброс PCI есть, VT-d, только amd64 есть, зрелее по инструментарию
Экосистема vm-bhyve, CBSD libvirt и всё, что вокруг него
Сложность освоения низкая: три утилиты высокая: слоёв больше

Архитектурно они ближе, чем кажется: и там, и там гипервизор живёт в ядре, а эмуляция устройств — в пользовательском процессе. Разница в объёме этого процесса. QEMU умеет эмулировать десятки платформ и сотни устройств, bhyve сознательно ограничивается virtio и минимумом legacy. Отсюда и обе стороны сравнения: bhyve проще понять целиком и в нём меньше нечего ломаться, а всё, что выходит за рамки «запустить современного гостя», в нём просто отсутствует.

С точки зрения FreeBSD это ровно та же линия, что и с jail против Docker (см. FreeBSD: Jails): механизм в базе, минимальный и предсказуемый, а обвязка — дело портов и администратора.

Источники

  • bhyve(8) — синтаксис устройств, слоты PCI, флаги -H и -P, загрузка через bootrom
  • vmm(4) — требования к платформам, VT-d для passthrough, управление доступом
  • bhyveload(8) — загрузка гостевой FreeBSD
  • bhyvectl(8) — уничтожение машины после остановки гостя
  • FreeBSD Handbook: Virtualization — сборка типовой конфигурации
  • vm-bhyve — конфигурация машин, коммутаторы, автозапуск

Связанные заметки

Из библиотеки института уносят только знания. Читателей здесь не считают: посещение не регистрируется, отметок в издании не остаётся, счётчиков нет ни у одного издания фонда.

Издание пополняется и пересверяется. Текст доступен на условиях CC BY-SA 4.0 — унесённое можно передавать дальше на тех же условиях.