Двенадцать сборок

Proxmox на голом железе, с рабочими вложенными виртуальными машинами

Однопользовательский сервер EPYC с Proxmox VE на зеркальных NVMe, маршрутизируемым мостом для гостей и вложенной виртуализацией, подтверждённой изнутри гостевой системы.

Что собираем

Выделенный сервер под управлением Proxmox VE как собственного гипервизора, с зеркалом ZFS на NVMe-дисках, мостом, который выдаёт гостям реальные адреса, и включённой и проверенной вложенной виртуализацией — то есть гость на этой машине может сам запускать гостей.

Вложенность — причина делать это на «железе», а не на виртуальном инстансе. В чужом гипервизоре вложенность с предсказуемым результатом невозможна, а на BM-E нашего гипервизора на пути нет: у вас есть IPMI, кнопка питания и плата. Что на ней запускать — ваше решение.

Перед началом

  • BM-E: тридцать два ядра Zen 4, 256 ГБ ECC, четыре NVMe-диска и восемь IPv4-адресов. IPMI доступен через VPN, который поддержка настраивает при передаче машины.
  • Proxmox VE 8, выбранный при заказе, или собственный ISO, загруженный через панель. Оба пути ведут к одному установщику.
  • Полчаса, когда машина никому не нужна, потому что первый шаг перезагружает её несколько раз.

1. Установка

Подключитесь к консоли через управляющий VPN, смонтируйте ISO и загрузите его. На экране выбора дисков выберите все четыре NVMe-устройства, укажите zfs (RAID10) и откройте расширенные опции:

  • ashift на 12 — правильное значение для секторов по четыре килобайта, изменить его позже без пересоздания пула нельзя.
  • compress на lz4. Это стоит доли ядра и обычно возвращает треть пространства.
  • hdsize уменьшите, чтобы оставить остальное под хранилище гостей, если только вы не хотите, чтобы корневой пул владел всем.

Задайте управляющий адрес и шлюз из данных панели, а в качестве имени хоста используйте полное доменное имя машины. Через две перезагрузки у вас будет приглашение входа и веб-интерфейс на порту 8006.

2. Репозитории и пакеты

Корпоративный репозиторий без подписки будет давать сбой и засорять каждый apt update, пока вы с ним не разберётесь:

rm -f /etc/apt/sources.list.d/pve-enterprise.sources
echo "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription" > /etc/apt/sources.list.d/pve-community.list
apt update && apt full-upgrade -y
apt install -y ifupdown2 chrony zfsutils-linux
reboot

3. Память для ZFS

Иначе ARC вырастет до половины вашей памяти, а на машине, чья работа — запускать гостей, этой памяти найдётся лучшее применение:

echo "options zfs zfs_arc_max=34359738368" > /etc/modprobe.d/zfs.conf
update-initramfs -u -k all

Тридцать два гигабайта ARC на машине с 256 ГБ оставляют достаточно для кэширования, не голодая гостей. Перезагрузитесь, чтобы применить, или установите вживую через echo в /sys/module/zfs/parameters/zfs_arc_max, если нельзя.

4. Сеть

Восемь адресов — это немного, поэтому гости сидят на приватном мосту, и только те, кому нужен публичный адрес, получают маршрутизируемый на них. Отредактируйте /etc/network/interfaces:

auto lo
iface lo inet loopback

auto enp1s0f0
iface enp1s0f0 inet static
  address <public address>/24
  gateway <gateway>

auto vmbr0
iface vmbr0 inet static
  address 10.20.0.1/24
  bridge-ports none
  bridge-stp off
  bridge-fd 0
  post-up   iptables -t nat -A POSTROUTING -s 10.20.0.0/24 -o enp1s0f0 -j MASQUERADE
  post-down iptables -t nat -D POSTROUTING -s 10.20.0.0/24 -o enp1s0f0 -j MASQUERADE

iface vmbr0 inet6 static
  address 2001:db8:1a2b:20::1/64

Для IPv6 не нужна трансляция адресов, потому что маршрутизируемый на машину /64 действительно маршрутизируется: назначайте адреса из него гостям на мосту, и они выходят в интернет напрямую. Такая асимметрия между двумя семействами не элегантна, но это честная форма адресного пространства, в котором мы живём.

sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/80-pve.conf
echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.d/80-pve.conf
ifreload -a

5. Вложенная виртуализация

cat /sys/module/kvm_amd/parameters/nested

На текущих ядрах это уже выводит 1. Если выводит 0:

echo "options kvm-amd nested=1" > /etc/modprobe.d/kvm-amd.conf
update-initramfs -u && reboot

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

6. Гость

cd /var/lib/vz/template/iso
wget https://cloud.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2

qm create 100 --name inner --memory 16384 --cores 8 --cpu host \
  --net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-single --ostype l26 \
  --agent enabled=1 --machine q35 --bios ovmf
qm set 100 --efidisk0 local-zfs:1
qm importdisk 100 debian-13-genericcloud-amd64.qcow2 local-zfs
qm set 100 --scsi0 local-zfs:vm-100-disk-1,discard=on,ssd=1
qm set 100 --boot order=scsi0
qm set 100 --ipconfig0 ip=10.20.0.100/24,gw=10.20.0.1
qm set 100 --sshkeys /root/.ssh/authorized_keys
qm set 100 --ciuser admin
qm start 100

discard=on с ssd=1 означает, что удаления внутри гостя возвращаются в пул, а не накапливаются как потерянное пространство.

7. Межсетевой экран

Веб-интерфейсу на порту 8006 нечего делать в публичном доступе. Ограничьте его на уровне дата-центра тем адресом, с которого вы администрируете, — конечная точка туннеля из руководства по WireGuard очевидный кандидат:

cat > /etc/pve/firewall/cluster.fw <<EOF
[OPTIONS]
enable: 1
policy_in: DROP

[RULES]
IN SSH(ACCEPT) -source 10.7.0.0/24
IN ACCEPT -source 10.7.0.0/24 -dport 8006 -proto tcp
IN ACCEPT -p icmp
EOF
systemctl restart pve-firewall

Проверка

Сначала хост:

pveversion -v | head -3
zpool status rpool
zpool list -o name,size,alloc,free,frag,cap
arc_summary | head -12

Пул показывает ONLINE с двумя зеркальными парами, а целевой размер ARC — тридцать два гигабайта, которые вы задали, а не половина машины.

Теперь суть этой сборки. Войдите в гостя и проверьте процессор, который ему выдан:

ssh [email protected]
lscpu | grep -E "Model name|Virtuali"
grep -c svm /proc/cpuinfo

Имя модели должно быть настоящим EPYC, а строка виртуализации должна сообщать AMD-V. Ноль от третьей команды означает, что тип процессора не host, и всё ниже провалится.

Затем запустите машину внутри машины:

apt install -y qemu-system-x86 qemu-utils cpu-checker
kvm-ok
wget https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/x86_64/alpine-virt-3.22.0-x86_64.iso
qemu-system-x86_64 -enable-kvm -m 2048 -cdrom alpine-virt-3.22.0-x86_64.iso -nographic

kvm-ok, печатающий, что ускорение может быть использовано, с последующей загрузкой Alpine, доходящей до приглашения входа за пару секунд, а не ползком, — это и есть проверка. Без вложенности та же команда либо outright отказывается, либо эмулирует программно примерно на одной двадцатой скорости, что невозможно не заметить.

Наконец, убедитесь, что интерфейс закрыт снаружи:

curl -m5 -k https://<public address>:8006/ ; echo "exit $?"

Таймаут соединения — правильный ответ.

После

Снапшоты на ZFS бесплатны, пока они не расходятся, поэтому ночной zfs-auto-snapshot-расписание стоит почти ничего и спасло больше машин, чем любая политика бэкапов. Пересборка на «железе» — в тот же день, но пересборка возвращает вам пустую машину, что отличается от возврата вашей машины.

Готовы, когда вы готовы

Выберите город. Выберите размер. Оплатите монетой.

Никаких форм о том, кто вы, никакого ожидания одобрения человеком, никаких звонков для проверки. Счёт оплачен — и учётные данные приходят на почту.