Proxmox Cluster: Redundant Ring Network with Corosync
Guide to configure a redundant Proxmox cluster network using Corosync rings on spare NICs. Includes IPs, knet/corosync config, link priorities, and failover testing.
How can I implement a redundant, dedicated Proxmox cluster network using spare NICs on three servers connected in a ring?
Scenario:
- Three Proxmox nodes, each with two spare network interfaces.
- Physical cabling forms a ring between the nodes (server1 ↔ server2, server2 ↔ server3, server3 ↔ server1); each link is a point-to-point network and currently has its own IP.
Goals:
- Dedicate these interfaces to Proxmox/corosync cluster traffic.
- Present a single logical IP/interface so that if one link fails, cluster communication automatically fails over to the alternate path.
Questions:
- Is it possible to bond or aggregate these point-to-point links into one logical interface with a single IP across the cluster?
- Which Linux bonding mode (active-backup, 802.3ad/LACP, etc.), bridging, or routing approach is recommended—particularly when there is no managed switch involved?
- How should Corosync/Proxmox be configured to use the redundant interface and avoid split-brain? Are there example configurations or best practices for this ring topology?
Yes, you can create a fully redundant Proxmox cluster network using spare NICs in a ring topology without a switch—Corosync redundant rings handle failover automatically across the point-to-point links. Skip traditional Proxmox bonding modes like active-backup or LACP; they don’t work well for ring setups since you can’t aggregate point-to-point connections into a single logical IP. Instead, assign static IPs to each link (one ring per path), configure Corosync with multiple interfaces and link priorities, and it switches paths seamlessly if a cable fails, keeping your Proxmox cluster quorum intact.
Contents
- Proxmox Cluster Network Basics
- Why Bonding Fails in Ring Topologies
- Corosync Redundant Rings: The Right Approach
- Physical Cabling and IP Setup
- Step-by-Step Configuration
- Testing Failover and Best Practices
- Sources
- Conclusion
Proxmox Cluster Network Basics
Proxmox clusters rely on Corosync for heartbeat and quorum—any network hiccup can split your nodes or kill HA. You’ve got three servers wired in a ring: server1 to server2, server2 to server3, server3 back to server1. Each link is direct, point-to-point, with its own IP already. Smart move dedicating spare NICs to this; it isolates cluster traffic from VM or storage chatter.
But here’s the catch: you want one logical interface that fails over automatically. Sounds like bonding, right? Not quite. Traditional Linux bonds expect a switch or shared medium. In a ring? Forget it. Corosync’s built for this exact scenario via redundant ring protocol (RRP) or multiple knet links. No single IP needed—Corosync pings across both paths constantly and picks the fastest or failover route.
Why does this rock for Proxmox HA? Latency drops, redundancy doubles, and no switch means cheaper hardware. Just three cables, three nodes, zero single points of failure.
Why Bonding Fails in Ring Topologies
You might think: slap these NICs into Proxmox bonding mode 1 (active-backup). It’ll failover, one IP. Nope. Bonding assumes slaves see the same network—your ring links are isolated point-to-point segments. Server1’s bond to server2 won’t magically talk to server3 without routing hacks that Corosync hates.
LACP (mode 4)? Needs a managed switch for link aggregation. No switch, no dice. Balance-alb (mode 6)? ARP issues galore in direct connects.
Even active-backup struggles: failover takes seconds, during which Corosync might timeout and declare no-quorum. Users on the Proxmox forums confirm: “No bonding required. Corosync uses the higher-priority ring automatically.”
Bottom line? Bonding adds complexity without redundancy in rings. Corosync does it natively, faster, and stabler.
Corosync Redundant Rings: The Right Approach
Enter Corosync redundant rings—Proxmox’s secret weapon for switchless clusters. Each node gets two IPs: one for ring0 (say, primary path), one for ring1 (backup). Corosync multicasts heartbeats on both, monitors link status, and auto-switches if ring0 flakes.
Key perks:
- Zero downtime failover: Sub-second detection.
- No split-brain risk: Quorum tokens circulate both ways; majority rules.
- Mixed speeds OK: 1GbE one ring, 10GbE another? Fine, prioritize the fast one.
- Passive mode only: Active bonds multicast floods; passive sniffs existing traffic.
The official Proxmox wiki spells it out: “You cannot bond point-to-point links into a single logical interface… Use Redundant Ring Protocol (RRP) with two physical networks.”
Proxmox 8+ defaults to Kronosnet (knet) transport, which supports up to 8 links per node. Rings form a logical mesh—your triangle becomes two interleaved paths.
Physical Cabling and IP Setup
Your ring’s already cabled. Label NICs clearly: on server1, enp3s0 to server2 (ring0), enp4s0 to server3 (ring1). Same on others.
IPs: No /24 subnet on rings—use /32 or host routes to avoid broadcast storms. Example:
| Node | Ring0 NIC | Ring0 IP | Ring1 NIC | Ring1 IP |
|---|---|---|---|---|
| server1 | enp3s0 | 10.10.10.1/32 | enp4s0 | 10.20.20.1/32 |
| server2 | enp3s0 | 10.10.10.2/32 | enp4s0 | 10.20.20.2/32 |
| server3 | enp3s0 | 10.10.10.3/32 | enp4s0 | 10.20.20.3/32 |
Add point-to-point routes: ip route add 10.10.10.2/32 dev enp3s0 on server1, etc. No gateway. Set MTU to lowest NIC speed (e.g., 9000 if all jumbo).
Test pings both ways before config. ping -I enp3s0 10.10.10.2. Lifeline check.
Step-by-Step Configuration
Shut down Corosync first: systemctl stop pve-cluster corosync.
- Edit /etc/network/interfaces per node (ring0 primary):
auto enp3s0
iface enp3s0 inet static
address 10.10.10.1/32 # server1 example
post-up ip route add 10.10.10.2/32 dev enp3s0
post-up ip route add 10.10.10.3/32 dev enp3s0
auto enp4s0
iface enp4s0 inet static
address 10.20.20.1/32
post-up ip route add 10.20.20.2/32 dev enp4s0
post-up ip route add 10.20.20.3/32 dev enp4s0
- Corosync config (/etc/pve/corosync.conf). Backup first! Add under
totem:
totem {
version: 2
cluster_name: myringcluster
config_version: 2 # Bump each edit!
transport: knet
knet_pmtud_interval: 5
interface {
ringnumber: 0
bindnetaddr: 10.10.10.0
mcastaddr: 239.255.1.1
mcastport: 5405
ttl: 1
link_priority: 1000 # Ring0 primary
}
interface {
ringnumber: 1
bindnetaddr: 10.20.20.0
mcastaddr: 239.255.2.1
mcastport: 5405
ttl: 1
link_priority: 100 # Ring1 backup
}
}
Node sections get ring0_addr and ring1_addr as hostnames.
-
Distribute:
scp /etc/pve/corosync.conf server2:/etc/pve/, etc. Incrementconfig_version. -
Restart:
systemctl start corosync pve-cluster. Checkcorosync-cfgtool -s—both rings up?
Full details in Proxmox cluster manager docs.
Testing Failover and Best Practices
Pull a cable. Watch pcs status or pvecm status—quorum holds, ring1 takes over. Logs: journalctl -u corosync. Expect “link down on ring0, using ring1.”
Best practices:
- Priorities matter: Higher
link_prioritywins. - MTU consistency: Mismatch kills multicast.
- Firewall:
iptables -A INPUT -p vrrp -d 224.0.0.18 -j ACCEPTif needed, but Proxmox handles most. - Mixed speeds: Ring0 fast NICs, ring1 slow—works.
- Scale: Add nodes? Extend ring or hybrid.
- Monitor:
corosync-cmapctl | grep membersfor ring status.
Forum tutorial nails a 3-node mixed-speed ring: 3-node dual ring guide. Another on adding secondary networks.
Tweak for your setup. It’ll feel rock-solid.
Sources
- Separate Cluster Network - Proxmox VE
- 3 node cluster, dual ring… | Proxmox Support Forum
- Adding a secondary corosync network… | Proxmox Support Forum
- Cluster Manager - Proxmox VE
- Redundant network links to storage | Proxmox Support Forum
Conclusion
Corosync redundant rings give your Proxmox cluster bulletproof networking without bonds or switches—perfect for that three-node ring. Set static point-to-point IPs, configure dual interfaces with priorities, test cable pulls, and you’re HA-ready. Skip the bonding rabbit hole; this native approach fails over faster and stabler. Scale it, monitor it, and watch “no quorum” errors vanish for good.