Doze construções

Proxmox em hardware dedicado, com máquinas virtuais aninhadas que funcionam

Uma máquina EPYC de locatário único executando Proxmox VE em NVMe espelhado, uma ponte roteada para convidados, e virtualização aninhada comprovada de dentro de um convidado.

O que isso constrói

Uma máquina bare metal rodando Proxmox VE como seu próprio hypervisor, com um espelho ZFS nos drives NVMe, uma ponte que entrega endereços reais aos convidados e virtualização aninhada ativada e verificada — ou seja, um convidado nesta máquina pode, ele mesmo, rodar convidados.

O aninhamento é a razão para fazer isso em metal, em vez de em uma instância virtual. Você não consegue aninhar dentro do hypervisor de outra pessoa com resultados previsíveis, e em uma BM-E não há hypervisor nosso no caminho: você tem IPMI, um botão de energia e a placa. O que roda nela é decisão sua.

Antes de começar

  • Uma BM-E: trinta e dois núcleos Zen 4, 256 GB de ECC, quatro drives NVMe e oito endereços IPv4. O IPMI é acessível por uma VPN, que o suporte configura quando a máquina é entregue.
  • Proxmox VE 8 selecionado no momento do pedido, ou um ISO personalizado enviado pelo painel. Ambos os caminhos terminam no mesmo instalador.
  • Meia hora quando ninguém precisar da máquina, porque o passo um a reinicia várias vezes.

1. Instalação

Conecte-se ao console pela VPN de gerenciamento, monte o ISO e inicialize-o. Na tela de seleção de discos, escolha todos os quatro dispositivos NVMe, selecione zfs (RAID10) e abra as opções avançadas:

  • ashift em 12, que é o valor correto para setores de quatro kilobytes e não pode ser alterado depois sem reconstruir o pool.
  • compress em lz4. Custa uma fração de núcleo e normalmente devolve um terço do espaço.
  • hdsize reduzido para deixar o resto para armazenamento de convidados, a menos que você queira que o pool raiz possua tudo.

Defina o endereço de gerenciamento e o gateway a partir dos detalhes do painel, e use o nome totalmente qualificado da máquina como hostname. Duas reinicializações depois, você tem um prompt de login e uma interface web na porta 8006.

2. Repositórios e pacotes

O repositório enterprise falhará sem assinatura e poluirá cada apt update até você resolvê-lo:

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. Memória para ZFS

O ARC, caso contrário, crescerá até metade da sua RAM, e em uma máquina cujo trabalho é rodar convidados, essa memória tem um uso melhor:

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

Trinta e dois gigabytes de ARC numa máquina de 256 GB deixam bastante para cache sem matar os convidados de fome. Reinicie para aplicar, ou defina ao vivo com echo em /sys/module/zfs/parameters/zfs_arc_max se não puder.

4. Rede

Oito endereços não é muito, então os convidados ficam em uma ponte privada e somente os que precisam de endereço público recebem um roteado para eles. Edite /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 não precisa de tradução de endereços, porque o /64 roteado para a máquina é genuinamente roteado: atribua endereços dele aos convidados na ponte e eles alcançam a internet diretamente. Essa assimetria entre as duas famílias não é elegante, mas é a forma honesta do espaço de endereços em que vivemos.

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. Virtualização aninhada

cat /sys/module/kvm_amd/parameters/nested

Em kernels atuais, isso já imprime 1. Se imprimir 0:

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

O aninhamento também exige que o convidado veja uma CPU que admita ter o recurso, o que significa que o tipo de processador deve ser host. Qualquer outra coisa apresenta um modelo de CPU sintético com as extensões de virtualização mascaradas, e o hypervisor interno se recusa a iniciar com um erro que não menciona nada disso.

6. Um convidado

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 com ssd=1 significa que exclusões dentro do convidado são devolvidas ao pool em vez de se acumularem como espaço perdido.

7. Firewall

A interface web na porta 8006 não deve ser publicamente acessível. Restrinja-a no nível do datacenter para o endereço de onde você administra — o endpoint do túnel do guia WireGuard é o candidato óbvio:

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

Verifique

Host primeiro:

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

O pool relata ONLINE com dois pares espelhados, e o alvo do ARC está nos trinta e dois gigabytes que você definiu, em vez de metade da máquina.

Agora o ponto real desta construção. Entre no convidado e verifique o processador que ele recebeu:

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

O nome do modelo deve ser a peça EPYC real, e a linha de virtualização deve reportar AMD-V. Um zero do terceiro comando significa que o tipo de processador não é host, e tudo abaixo falhará.

Então rode uma máquina dentro da máquina:

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 imprimindo que a aceleração pode ser usada, seguido por um boot Alpine que atinge o prompt de login em alguns segundos em vez de rastejar, é a verificação. Sem aninhamento, esse mesmo comando ou recusa diretamente ou emula em software a cerca de um vigésimo da velocidade, o que é inconfundível.

Por último, confirme que a interface está fechada para fora:

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

Um timeout de conexão é a resposta correta.

Depois

Snapshots em ZFS são gratuitos até divergirem, então um agendamento noturno zfs-auto-snapshot custa quase nada e já salvou mais máquinas do que qualquer política de backup. Reconstruções em metal são no mesmo dia, mas uma reconstrução devolve uma máquina vazia, que é algo diferente de devolver sua máquina.

Pronto quando você estiver

Escolha uma cidade. Escolha um tamanho. Pague em cripto.

Sem formulários sobre quem você é, sem esperar aprovação de um humano, sem ligação para verificar nada. O pagamento é confirmado e as credenciais chegam na sua caixa de entrada.