Twaalf builds

Proxmox op bare metal, met nested virtual machines die werken

Een single-tenant EPYC-machine met Proxmox VE op gespiegelde NVMe, een routed bridge voor gasten en nested virtualisatie bewezen van binnenuit een gast.

Wat dit bouwt

Een bare metal machine met Proxmox VE als eigen hypervisor, met een ZFS-mirror over de NVMe-schijven, een bridge die gasten echte adressen geeft, en geneste virtualisatie ingeschakeld en geverifieerd — wat betekent dat een gast op deze machine zelf gasten kan draaien.

Nesten is de reden om dit op metaal te doen in plaats van op een virtuele instantie. Je kunt niet met voorspelbare resultaten nesten binnen de hypervisor van iemand anders, en op een BM-E is er geen hypervisor van ons in de weg: je krijgt IPMI, een powerknop en het moederbord. Wat erop draait, is jouw beslissing.

Voordat je begint

  • Een BM-E: tweeëndertig Zen 4-kernen, 256 GB ECC, vier NVMe-schijven en acht IPv4-adressen. IPMI is bereikbaar via een VPN, dat support opzet wanneer de machine wordt overgedragen.
  • Proxmox VE 8 geselecteerd bij bestelling, of een aangepaste ISO geüpload via het paneel. Beide routes eindigen bij dezelfde installer.
  • Een half uur wanneer niemand de machine nodig heeft, want stap één herstart hem meerdere keren.

1. Installeren

Verbind met de console via de beheer-VPN, mount de ISO en boot deze. Kies op het schijfselectiescherm alle vier NVMe-apparaten, kies zfs (RAID10) en open de geavanceerde opties:

  • ashift op 12, wat de juiste waarde is voor vier-kilobyte sectoren en achteraf niet kan worden gewijzigd zonder de pool opnieuw op te bouwen.
  • compress op lz4. Het kost een fractie van een kern en levert doorgaans een derde van de ruimte op.
  • hdsize verlaagd om de rest voor gastopslag te laten, tenzij je wilt dat de rootpool alles bezit.

Stel het beheeradres en de gateway in op basis van de paneelgegevens en gebruik de volledig gekwalificeerde naam van de machine als hostnaam. Twee herstarts later heb je een inlogprompt en een webinterface op poort 8006.

2. Repositories en pakketten

De enterprise-repository zal zonder abonnement falen en elke apt update vervuilen totdat je het aanpakt:

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. Geheugen voor ZFS

De ARC zal anders groeien tot de helft van je RAM, en op een machine waarvan de hele taak is om gasten te draaien, heeft dat geheugen een beter doel:

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

Tweeëndertig gigabyte ARC op een 256 GB-machine laat voldoende over voor caching zonder de gasten uit te hongeren. Herstart om het toe te passen, of stel het live in met echo in /sys/module/zfs/parameters/zfs_arc_max als dat niet kan.

4. Netwerken

Acht adressen is niet veel, dus gasten zitten op een private bridge en alleen degenen die een publiek adres nodig hebben, krijgen er een gerouteerd naar hen toe. Bewerk /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 heeft geen adresomzetting nodig, omdat de /64 die naar de machine wordt gerouteerd echt wordt gerouteerd: wijs er adressen uit toe aan gasten op de bridge en ze bereiken het internet rechtstreeks. Die asymmetrie tussen de twee families is niet elegant, maar het is de eerlijke vorm van de adresruimte waarin we leven.

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. Geneste virtualisatie

cat /sys/module/kvm_amd/parameters/nested

Op huidige kernels print dit al 1. Als het 0 print:

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

Nesten vereist ook dat de gast een CPU ziet die toegeeft de functie te hebben, wat betekent dat het processortype host moet zijn. Al het andere biedt een synthetisch CPU-model met de virtualisatie-extensies gemaskeerd, en de binnenste hypervisor weigert te starten met een fout die dit allemaal niet vermeldt.

6. Een gast

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 met ssd=1 betekent dat verwijderingen binnen de gast worden teruggegeven aan de pool in plaats van op te stapelen als ruimte waar je het overzicht over kwijt bent.

7. Firewall

De webinterface op poort 8006 heeft geen reden om publiek bereikbaar te zijn. Beperk het op datacentrumniveau tot het adres van waaruit je beheert — het tunnel-eindpunt uit de WireGuard-gids is de voor de hand liggende kandidaat:

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

Verifieer het

Host eerst:

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

De pool rapporteert ONLINE met twee gespiegelde paren, en het ARC-doel bevindt zich op de tweeëndertig gigabyte die je hebt ingesteld in plaats van op de helft van de machine.

Nu het eigenlijke punt van deze build. Log in op de gast en controleer de processor die deze heeft gekregen:

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

De modelnaam moet het echte EPYC-onderdeel zijn, en de virtualisatieregel moet AMD-V rapporteren. Een nul van de derde opdracht betekent dat het processortype niet host is, en alles hieronder zal falen.

Draai dan een machine binnen de machine:

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 die print dat acceleratie kan worden gebruikt, gevolgd door een Alpine-boot die binnen een paar seconden een inlogprompt bereikt in plaats van te kruipen, is de verificatie. Zonder nesten weigert dezelfde opdracht ronduit of emuleert in software op ongeveer een twintigste van de snelheid, wat onmiskenbaar is.

Controleer ten slotte of de interface van buitenaf gesloten is:

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

Een verbindingstime-out is het juiste antwoord.

Achteraf

Snapshots op ZFS zijn gratis totdat ze divergeren, dus een nachtelijk zfs-auto-snapshot-schema kost bijna niets en heeft meer machines gered dan welk back-upbeleid dan ook. Rebuilds op metaal zijn dezelfde dag, maar een rebuild levert je een lege machine op, wat iets anders is dan het teruggeven van je machine.

Klaar wanneer jij dat bent

Kies een stad. Kies een formaat. Betaal in munt.

Geen formulieren over wie je bent, geen wachten op een mens die je goedkeurt, geen telefoontje om iets te verifiëren. De factuur wordt betaald en de inloggegevens belanden in je inbox.