---
tags: [freebsd, tooling]
verified: 2026-09-02
---

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

## Обзор

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

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

Статья продолжает [FreeBSD: Jails](./freebsd-jails.md) и опирается на сетевую часть из [FreeBSD: сеть](./freebsd-networking.md) — мосты и 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`:

```sh
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` и трёх утилитах:

```sh
kldload vmm                    # либо vmm_load="YES" в /boot/loader.conf
```

- `bhyveload` — загрузчик для гостевой FreeBSD: читает ядро гостя прямо из образа и передаёт управление. Работает только с FreeBSD.
- `bhyve` — собственно гипервизор, он же описание виртуального железа: устройства перечисляются флагами командной строки.
- `bhyvectl` — управление созданной машиной, в первую очередь `--destroy`.

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

```sh
bhyvectl --vm=guest --destroy
```

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

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

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

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

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

```sh
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` при создании | зависит от способа создания |
| Просмотр содержимого с хоста | сложно | легко смонтировать |

```sh
zfs create -V 20G -o volmode=dev zroot/vm/linuxvm
```

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

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

## Сеть

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

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

Подробнее про мосты и клонируемые интерфейсы — в [статье про сеть FreeBSD](./freebsd-networking.md).

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

```sh
sysctl net.link.tap.up_on_open=1
```

Если виртуалки не должны быть видны в физической сети, вместо моста с `em0` строится изолированный мост с адресом на хосте и NAT через PF — конструкция та же, что для jail и для домашних сервисов за NAT, и она разобрана в [самохостинге за NAT](./selfhosting-behind-nat.md).

## Консоль

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

```sh
kldload nmdm
cu -l /dev/nmdm0B
```

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

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

```sh
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, автозапуск при загрузке и корректная уборка после остановки.

```sh
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`:

```conf
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](./freebsd-jails.md)): механизм в базе, минимальный и предсказуемый, а обвязка — дело портов и администратора.

## Источники

- [bhyve(8)](https://man.freebsd.org/cgi/man.cgi?bhyve8) — синтаксис устройств, слоты PCI, флаги `-H` и `-P`, загрузка через bootrom
- [vmm(4)](https://man.freebsd.org/cgi/man.cgi?vmm4) — требования к платформам, VT-d для passthrough, управление доступом
- [bhyveload(8)](https://man.freebsd.org/cgi/man.cgi?bhyveload8) — загрузка гостевой FreeBSD
- [bhyvectl(8)](https://man.freebsd.org/cgi/man.cgi?bhyvectl8) — уничтожение машины после остановки гостя
- [FreeBSD Handbook: Virtualization](https://docs.freebsd.org/en/books/handbook/virtualization/) — сборка типовой конфигурации
- [vm-bhyve](https://github.com/churchers/vm-bhyve) — конфигурация машин, коммутаторы, автозапуск

---

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

- [FreeBSD — Jails](./freebsd-jails.md) — уровень изоляции ниже: общее ядро, сотни экземпляров вместо десятков
- [FreeBSD — сеть](./freebsd-networking.md) — мосты, tap-интерфейсы и PF, на которых держится сеть виртуалок
- [FreeBSD — ZFS](./freebsd-zfs.md) — zvol под диски гостей, снепшоты и клоны как механизм отката
- [Linux — контейнеризация](./linux-containerization.md) — та же граница «общее ядро против своего», со стороны Linux
- [Самохостинг за NAT: VPS как точка входа](./selfhosting-behind-nat.md) — изолированный мост с NAT, если виртуалкам не нужен адрес в физической сети
- [Эксплуатация локальных ИИ-сервисов](./ai-services-operations.md) — проброс видеокарты в гостевой Linux как единственный путь к CUDA на машине с FreeBSD
- [Адресное пространство: зачем трансляция и какие есть альтернативы](./os-address-space-models.md) — почему изоляция unikernel'а и библиотечной ОС держится на гипервизоре
