Mi clúster de Proxmox de 3 nodos, tal como funciona hoy
Tres máquinas, un clúster, sin almacenamiento compartido, sin Ceph. Todo lo de abajo está copiado del clúster en marcha. Copia lo que necesites. Cuando algo cambia agrego una línea con fecha al log y actualizo la salida.
Log
- 2026-10-17 sevro pasó a 10G. El DAC que antes iba de nodo a nodo ahora va al switch, en bond activo-pasivo con el puerto de 2.5G. reaper y sevro actualizados a 9.2.21. La BIOS F41 de skynet rompió el passthrough de GPU, arreglado en la BIOS (esa entrada).
- 2026-10-16 Se saltó la BIOS 1.03 de la MS-A2 en ambas minis. Rompe el passthrough de PCI y la opción que lo arregla está bloqueada [3]. Me quedo en 1.02.
Las máquinas
| Nodo | Hardware | PVE | Pools |
|---|---|---|---|
| reaper | Minisforum MS-A2, Ryzen 9 9955HX, 32G, BIOS 1.02 | 9.2.21, kernel 7.0.14-24 | rpool 472G, data-zfs 952G |
| sevro | Minisforum MS-A2, Ryzen 9 9955HX, 32G, BIOS 1.02 | 9.2.21, kernel 7.0.14-24 | rpool 472G, data-zfs 952G, nas-pool 952G |
| skynet | Gigabyte B650 AORUS ELITE AX V2, Ryzen 9 7950X3D, 96G, RTX 5070 Ti | 9.2.20, kernel 7.0.14-19 | rpool 1.81T, tank 476G |
skynet es la rara. Es una placa de escritorio con la GPU pasada a mi VM de escritorio de cada día, así que se actualiza al final.
Quorum
$ pvecm status
Cluster information
-------------------
Name: howlers
Config Version: 9
Transport: knet
Secure auth: on
Votequorum information
----------------------
Expected votes: 3
Highest expected: 3
Total votes: 3
Quorum: 2
Flags: Quorate
Membership information
----------------------
Nodeid Votes Name
0x00000001 1 192.168.1.14
0x00000002 1 192.168.1.13 (local)
0x00000003 1 192.168.1.166
Tres votos, se necesitan dos. Cualquiera de las máquinas puede caerse y las otras dos siguen. Con dos nodos necesitas un QDevice; un tercer nodo real me resolvió eso.
corosync.conf
$ cat /etc/pve/corosync.conf
nodelist {
node {
name: reaper
nodeid: 1
quorum_votes: 1
ring0_addr: 192.168.1.14
}
node {
name: sevro
nodeid: 2
quorum_votes: 1
ring0_addr: 192.168.1.13
}
node {
name: skynet
nodeid: 3
quorum_votes: 1
ring0_addr: 192.168.1.166
}
}
quorum {
provider: corosync_votequorum
}
totem {
cluster_name: howlers
config_version: 9
interface {
knet_link_priority: 10
linknumber: 0
}
ip_version: ipv4-6
link_mode: passive
secauth: on
token_coefficient: 125
version: 2
}
Un enlace en la LAN de la casa. La documentación quiere un segundo enlace de corosync, separado [1]. Todavía no tengo uno. Eso es lo que sigue.
Red: 10G con respaldo de 2.5G
$ cat /etc/network/interfaces
auto bond0
iface bond0 inet manual
bond-slaves nic2 nic0
bond-mode active-backup
bond-primary nic2
bond-miimon 100
auto vmbr0
iface vmbr0 inet static
address 192.168.1.13/24
gateway 192.168.1.1
bridge-ports bond0
bridge-vlan-aware yes
bridge-vids 2-4094
bridge-stp off
bridge-fd 0
$ grep -E "Mode|Active|Interface|Speed" /proc/net/bonding/bond0
Bonding Mode: fault-tolerance (active-backup)
Currently Active Slave: nic2
Slave Interface: nic2
Speed: 10000 Mbps
Slave Interface: nic0
Speed: 2500 Mbps
nic2 es el DAC de 10G, nic0 es el cobre de 2.5G. Desconecta el DAC y el tráfico pasa a nic0. Active-backup no necesita nada del switch [2]. El bridge es VLAN-aware, así que un guest solo recibe tag=101 en su NIC.
Aplícalo con red de seguridad. El rollback corre como un timer de systemd, así que se dispara igual si tu sesión ssh se cae:
cp /etc/network/interfaces /root/interfaces.bak
systemd-run --on-active=2min --unit=net-rollback sh -c 'cp /root/interfaces.bak /etc/network/interfaces && ifreload -a'
ifreload -a
# still in? cancel the rollback
systemctl stop net-rollback.timer
storage.cfg
$ cat /etc/pve/storage.cfg
dir: local
path /var/lib/vz
content vztmpl,import,iso,backup
zfspool: local-zfs
pool rpool/data
content rootdir,images
sparse 1
zfspool: data-zfs
pool data-zfs
content images,rootdir
mountpoint /data-zfs
nodes sevro,reaper
sparse 1
cifs: nas-iso
path /mnt/pve/nas-iso
server 192.168.1.20
share share
content iso
subdir /lab/images/iso
username neal
La replicación necesita almacenamiento ZFS con el mismo storage ID en ambos nodos [4]. Por eso ambas minis tienen data-zfs. Las ISOs viven en el NAS para que todos los nodos vean la misma lista.
Replicación en vez de almacenamiento compartido
$ pvesr status
JobID Enabled Target LastSync NextSync Duration FailCount State
100-0 Yes local/reaper 2026-10-17_14:50:00 2026-10-17_14:55:00 1.647333 0 OK
103-0 Yes local/reaper 2026-10-17_14:50:02 2026-10-17_14:55:00 1.470997 0 OK
106-0 Yes local/reaper 2026-10-17_14:50:03 2026-10-17_14:55:00 1.581741 0 OK
108-0 Yes local/reaper 2026-10-17_14:50:05 2026-10-17_14:55:00 1.914492 0 OK
109-0 Yes local/reaper 2026-10-17_14:50:07 2026-10-17_14:55:00 1.929232 0 OK
Cada 5 minutos cada guest toma una snapshot y envía la diferencia a la otra mini. Tarda menos de 2 segundos. Crea una:
pvesr create-local-job 109-0 reaper --schedule "*/5"
Mover un guest replicado es rápido porque casi todo el disco ya está ahí:
qm migrate 105 reaper --online --with-local-disks
pct migrate 109 reaper --restart
HA está apagado. No hay dispositivo de fencing, así que cuando un nodo muere arranco la réplica en el otro a mano. En el peor caso pierdo 5 minutos.
Actualizar un nodo
# empty the node first
qm migrate <id> <other-node> --online --with-local-disks
pct migrate <id> <other-node> --restart
apt update && apt full-upgrade -y
reboot
pveversion
Un nodo a la vez. Los otros dos siguen arriba, el quorum se mantiene.
Qué cambiaría
- Un segundo enlace de corosync en su propia red.
- Cada pool aquí es un solo disco. Dos discos de 12TB vienen en camino como espejo ZFS.
- reaper y skynet a 10G como sevro. Los DACs ya están pedidos.