De switch die je niet koopt

Een Proxmox-cluster van drie nodes met Ceph wil een snel netwerk tussen de nodes. Het gebruikelijke antwoord is een switch van 100 Gbit, en het gebruikelijke bezwaar is wat die kost.

Er is voor drie nodes een ander antwoord: draad ze rechtstreeks aan elkaar in een driehoek en routeer eroverheen. Helemaal geen switch in het opslagpad.

Het goedkoopste onderdeel in elk ontwerp is dat wat je niet koopt, en het is het enige dat nooit stukgaat.

Dat levert vier dingen op.

De kosten van de switch verdwijnen. Je hebt netwerkkaarten en drie kabels nodig, geen switch van 100 of 200 Gbit met het bijbehorende aantal poorten.

Het datapad heeft geen enkel punt waar alles op stukloopt. Een switch die uitvalt of herstart neemt al het oost-westverkeer van het hele cluster mee. Nodes die rechtstreeks aan elkaar zijn gedraad kan het niet schelen wat er elders in het gebouw met een switch gebeurt.

Het zware verkeer zit op eigen draden. Live migratie en Ceph-replicatie blijven op het mesh in plaats van te concurreren met kantoor- en beheerverkeer.

Uitbreiden is draadwerk, geen kwestie van poortbudget. Er is geen centrale bak die als plafond voor bandbreedte of aantal poorten optreedt, dus de fabric groeit zolang elke server een vrij PCIe-slot heeft. OpenFabric routeert zelf over nieuwe links.

En één eerlijke grens, want die doet meer ter zake dan de vier voordelen. Een volledig mesh heeft een kabel tussen elk paar nodes nodig. Drie nodes is drie kabels. Vier is zes. Vijf is tien. Het draadwerk groeit sneller dan het aantal nodes, en dit ontwerp overleeft een klein cluster niet zonder over te stappen op iets met switches, zoals leaf-spine.

Drie nodes is precies waar een volledig mesh zin heeft. Daarboven, met twee meshpoorten per node, is wat je nog kunt bouwen een ring — en die heeft één ding nodig dat deze bouw verder juist vermijdt, hieronder behandeld.

Wat er wordt gebouwd

Drie Proxmox VE-hosts, elk met twee eigen interfaces van 100 Gbit, in een driehoek gedraad zodat elke node twee directe buren heeft.

Proxmox SDN doet de routering. OpenFabric is het protocol: het rekent het beste pad over het mesh uit, en als er een kabel wordt losgetrokken of een link wegvalt, routeert het via het overgebleven pad. Niemand hoeft in te loggen.

De fabric woont in 10.10.10.0/24, gereserveerd voor het mesh en niets anders — geen beheer, geen gasten, geen opslagadressering, niets externs.

NodeMeshadresMeshinterfaces
mesh110.10.10.1/32nic1, nic2
mesh210.10.10.2/32nic1, nic2
mesh310.10.10.3/32nic1, nic2

Elke node krijgt een /32, geen stuk van het subnet. Dat is het punt van een gerouteerd mesh in plaats van een gebrugd. Het adres identificeert de node, OpenFabric kondigt het aan, en de twee fysieke links zijn slechts paden om hem te bereiken. Proxmox maakt een dummy-loopbackinterface om het adres te dragen.

De driehoek van drie nodes, en op welke NIC elke kabel landtswitch van 2,5 Gbitbeheer + clientmesh110.10.10.1/32mesh210.10.10.2/32mesh310.10.10.3/32DAC-01nic1 ↔ nic1DAC-03nic2 ↔ nic2DAC-02mesh2 nic2 ↔ mesh3 nic1nic0nic0nic0Elke node bereikt de andere twee direct, dus elke meshhop is één hop. De gestreepte nic0-links zijnhet aparte beheerpad van 2,5 Gbit — nooit deel van de fabric, en de reden dat je nog kuntinloggen als het mesh stuk is.
Drie kabels, zes poorten, en twee paden naar elke node. Trek een willekeurige kabel los en elke node is nog bereikbaar — de twee resterende links vormen een keten waar OpenFabric omheen routeert.

Het draadwerk

Actieve glasvezel-DAC-kabels, in een driehoek, met jumboframes aan op beide meshinterfaces op elke node.

KabelVanNaar
DAC-01mesh1 nic1mesh2 nic1
DAC-02mesh2 nic2mesh3 nic1
DAC-03mesh3 nic2mesh1 nic2

Actieve glasvezel in plaats van koperen DAC, om twee redenen die over het rack gaan en niet over het netwerk:

  • Kabelbeheer. Actieve glasvezel-DAC’s zijn dunner en veel flexibeler dan koper, dus ze lopen netjes en stapelen zich niet op achter de servers.
  • Luchtstroom. Minder kabelmassa achter de kast betekent minder verstoring van de luchtstroom van voor naar achter, en dat doet ertoe als er meerdere snelle links in dezelfde paar rackunits landen.

Twee netwerken, niet één

Het mesh is niet het enige netwerk, en het mag er ook geen worden.

Elke node heeft nic0 op een switch van 2,5 Gbit, aan Proxmox aangeboden als de brug vmbr0. Die draagt de webinterface, beheertoegang en clientverkeer. Het is ook het pad dat je gebruikt terwijl je de fabric bouwt, en daarom moet het onafhankelijk daarvan zijn.

nic0 blijft met opzet buiten de fabric. Alleen nic1 en nic2 worden geselecteerd bij het aanmaken van de fabricnodes.

Het mesh draagt drie dingen:

  • Ceph. Replicatie, herstel en backfill van node naar node voor de hyperconvergente opslag.
  • Virtueel netwerk voor clients. VNets op VXLAN rekken gastnetwerken over alle drie de nodes, met het gerouteerde mesh als onderlaag.
  • Corosync, als tweede pad. Verkeer voor clusterlidmaatschap loopt over het beheernetwerk en over het mesh, zodat quorum niet afhangt van het overleven van één van de twee.
Wat op het beheernetwerk rijdt, wat op het mesh rijdt, en het ene ding op beideBeheernetwerk van 2,5 Gbitnic0 → vmbr0 → switchWebinterface van ProxmoxBeheertoegangVerkeer naar clientsGerouteerd mesh van 100 Gbitnic1 + nic2 → directe DAC, geen switchCeph-replicatie, herstel, backfillVirtuele clientnetwerken op VXLANLive migratieCorosync — beide padenClusterlidmaatschap hangt niet af van het overleven van één van beide netwerken.De scheiding ís het ontwerp. Beheer blijft bereikbaar in welke toestand de interfaces van 100 Gbitook zijn, en dat maakt het veilig de fabric vanuit de webinterface te bouwen — en terug tedraaien.
Corosync is het enige dat op beide zit. Al het andere heeft precies één thuis — en beheertoegang is degene die moet blijven werken terwijl je aan de andere zit.

De regel die het waard is op het wijzigingsticket te schrijven: beheer- en clienttoegang blijven altijd beschikbaar via de switch van 2,5 Gbit, in welke toestand de interfaces van 100 Gbit ook zijn.

Alles via de webinterface

Deze bouw gebeurt volledig in de webinterface van Proxmox. Dat is een bewuste keuze, geen beperking van het gereedschap.

Met opzet niet gebruikt:

  • /etc/network/interfaces met de hand bewerken.
  • FRR-configuratiebestanden met de hand bewerken.
  • vtysh als bouwmethode.

Proxmox genereert de onderliggende netwerk- en routeringsconfiguratie uit de SDN-objecten die je definieert. Kan iets echt niet in de interface worden gezet, dan is dat het waard als voorwaarde te benoemen in plaats van stil op de opdrachtregel op te lossen. De volgende die de webinterface opent weet niet dat je dat hebt gedaan.

Uitvoer van de opdrachtregel staat hieronder alleen als bewijs, nooit als bouwstap.

De bouw

1. Open de webinterface van Proxmox en ga naar Datacentre → SDN → Fabrics.

Proxmox Datacenter SDN Fabrics-weergave met de knop Add Fabric

2. Voeg de fabric toe. Geef hem een naam, geef hem de meshprefix, en zet de timers.

Dialoog Create OpenFabric met Name op Mesh, IPv4 Prefix 10.10.10.0/24, Hello Interval 1 en CSNP Interval 1

Hello- en CSNP-intervallen van 1 werken de toestand zo snel mogelijk bij zodra er iets verandert, en dat is wat je op een fabric van deze omvang wilt. De kosten zijn meer gebabbel in het besturingsvlak. Onbelangrijk op drie nodes met elk twee links, een tweede gedachte waard als de fabric ooit groeit.

3. Voeg elke node toe met Add node. Geef hem een adres uit het meshbereik en vink de interfaces aan die meedoen.

Dialoog Create Node voor mesh1 met IPv4 10.10.10.1 en nic1 en nic2 geselecteerd

Merk op wat niet is aangevinkt: nic0 blijft eruit, en vmbr0 houdt het beheeradres. Gebruik Create another voor de eerste twee nodes en Create op de laatste.

4. Kijk het resultaat na voordat je het toepast.

Fabrics-lijst met de fabric Mesh die OpenFabric op 10.10.10.0/24 gebruikt, met mesh1, mesh2 en mesh3 op 10.10.10.1, .2 en .3, elk met nic1 en nic2

Drie nodes, drie adressen, nic1, nic2 op elk, allemaal gemarkeerd als new — er is nog niets weggeschreven.

5. Pas de SDN-configuratie toe.

SDN Status-weergave met de knoppen Apply en Dry-Run, met zonestatus ok op alle drie de nodes

Er staat een Dry-Run naast Apply als je liever eerst ziet wat het van plan is.

Weten dat het gelukt is

De statusweergave hoort zowel de zone- als de fabricregels ok te tonen op alle drie de nodes, en geen wachtende wijzigingen meer om toe te passen.

SDN Status met zowel de zone- als de fabricregels op status ok op mesh1, mesh2 en mesh3

Kijk de fabric dan na vanuit het gezichtspunt van een node zelf. Eerst de routes — elke node hoort een /32 naar elk van de andere te hebben, en de kolom Via vertelt je welke buur hij gebruikt.

Fabric Mesh op node mesh1, tabblad Routes met 10.10.10.2/32 via 10.10.10.2 en 10.10.10.3/32 via 10.10.10.3

Dan de buren. Twee, allebei Up, op een driehoek van drie nodes.

Fabric Mesh op node mesh1, tabblad Neighbors met mesh2 en mesh3 allebei Up

Dan de interfaces, en daar komt de vorm van het geheel naar boven: dummy_Mesh als de loopback die het routeradres draagt, en nic1 en nic2 als Point-To-Point in plaats van broadcastsegmenten.

Fabric Mesh op node mesh1, tabblad Interfaces met dummy_Mesh als Loopback en nic1 en nic2 als Point-To-Point, allemaal Up

Bewijs het ten slotte van begin tot eind.

Shell op node mesh1 die 10.10.10.2 en 10.10.10.3 pingt, vier pakketten elk, 0% pakketverlies, gemiddeld rondje 0,134 ms en 0,141 ms

Geen verlies, en gemiddelden van 0,134 ms en 0,141 ms. Beide buren zijn één directe hop weg, en dat is wat een driehoek je geeft.

De controle die het waard is en die geen schermafbeelding kan laten zien: trek één kabel los en bevestig dat alles nog bereikbaar is. Dat is de hele reden om voor een gerouteerd mesh te kiezen boven een paar punt-tot-puntlinks. Het is dan ook de enige test die uitmaakt.

Voorbij drie nodes: de ring

Een driehoek is een volledig mesh. Elke node heeft een directe kabel naar elke andere node, elke hop is één hop, en geen node draagt ooit verkeer dat niet van hemzelf is.

Die eigenschap is wat twee meshpoorten per node je bij drie nodes opleveren, en het is precies wat je bij vier verliest. Niet een deel ervan. Alles. Een volledig mesh van vier nodes heeft drie poorten per stuk nodig. Met twee is het meeste wat je kunt draden een ring.

Een ring verandert het verkeersmodel. Nodes die naast elkaar liggen hebben nog een directe kabel, maar nodes aan weerszijden van de ring niet — hun verkeer moet een tussenliggende node oversteken. En die node moet bereid zijn pakketten tussen zijn twee meshinterfaces door te sturen, en dat doet Linux standaard niet. De kernel documenteert ip_forward als “Forward Packets between interfaces” met een “Default: 0 (disabled)”.

Een ring van vier nodes: nodes tegenover elkaar hebben geen kabel, dus één node stuurt voor ze doormesh110.10.10.1mesh2stuurt doormesh310.10.10.3mesh410.10.10.4mesh1 → mesh3geen kabel ertussendus het steekt mesh2 overdoorvoernodestuurt door tussennic1 en nic2Volledig mesh bij 4 nodes6 kabels, 3 poorten per nodegeen doorvoer, geen doorsturenRing: 4 kabels, 2 poorten —en daarom ben je hierTwee van de zes nodeparen hebben geen directe kabel. Hun verkeer wordt door een buur gedragen, endus dragen de links van die buur ook de Ceph-replicatie van andere nodes naast die van hemzelf — deprijs die de driehoek niet heeft.
mesh1 naar mesh3 heeft geen kabel. Zijn verkeer steekt mesh2 of mesh4 over, en die node stuurt het alleen door omdat doorsturen aanstaat op de twee interfaces waarop het aankomt.

Zet het aan voor de meshinterfaces, en alleen die:

# /etc/sysctl.d/99-mesh-forwarding.conf
net.ipv4.conf.nic1.forwarding = 1
net.ipv4.conf.nic2.forwarding = 1
sysctl --system

Lees ze terug in plaats van het aan te nemen:

sysctl net.ipv4.conf.nic1.forwarding net.ipv4.conf.nic2.forwarding

De instelling per interface is hier de juiste omvang, en hij werkt op zichzelf. De globale net.ipv4.ip_forward is geen voorwaarde. De doorstuurbeslissing van de kernel leest de eigen waarde van de ontvangende interface:

#define IN_DEV_FORWARD(in_dev)   IN_DEV_CONF_GET((in_dev), FORWARDING)

IN_DEV_CONF_GET geeft de instelling van dat apparaat terug, niet een EN met de globale. Zo sturen nic1 en nic2 doorgaand verkeer voor de fabric door, terwijl nic0 en vmbr0 precies blijven wat ze horen te zijn: hostinterfaces die niet routeren. De globale schakelaar aanzetten zou elke interface op de bak tot router maken, ook die naar je kantoornetwerk. Dat is niets wat dit ontwerp nodig heeft.

Eén ding om te weten over de globale IPv4-schakelaar, ook al zet je hem niet: net.ipv4.ip_forward zet in bulk, en daarom waarschuwt de kerneldocumentatie dat hem wijzigen “resets all configuration parameters to their default state”. Schrijft iets anders op de host hem ooit, dan overschrijft dat deze waarden per interface. Goed om te weten voordat je een middag besteedt aan waarom doorgaand verkeer is gestopt.

IPv6 is de uitzondering, en het is de enige plek waar de globale schakelaar thuishoort. De kerneldocumentatie zegt het rechtstreeks onder conf/all/forwarding:

Enable global IPv6 forwarding between all interfaces. IPv4 and IPv6 work differently here; the force_forwarding flag must be used to control which interfaces may forward packets.

Er is dus geen IPv6-equivalent van de nette aanpak per interface hierboven. Draagt de fabric IPv6, dan zet je doorsturen globaal aan en begrens je het daarna met force_forwarding, gedocumenteerd als “Enable forwarding on this interface only — regardless of the setting on conf/all/forwarding”. Merk op dat hetzelfde overschrijven omgekeerd geldt: conf.all.forwarding op 0 zetten reset force_forwarding op elke interface.

De bouw hierboven laat de IPv6-prefix van de fabric leeg, dus niets daarvan geldt hier — het doet alleen ter zake als je er een toevoegt.

Merk op wat doorsturen niet verandert: OpenFabric kondigde de /32 van elke node al aan en rekende het pad over de ring al uit. Doorsturen is de ontbrekende toestemming, niet het ontbrekende verstand. De routeringstabel had de hele tijd al gelijk. De kernel weigerde simpelweg als router op te treden.

Wat de ring kost, vergeleken met de driehoek:

  • Doorgaand verkeer. Op een ring van vier nodes steken de twee diagonale paren een tussenliggende node over, dus hun verkeer verbruikt ook de linkbandbreedte van die node. Ceph merkt dit als eerste, want replicatie is van allen naar allen in plaats van van buur naar buur.
  • Een extra hop latency op die paden, boven op de gebruikelijke cijfers onder de milliseconde van het ontwerp zonder switch.
  • Minder ruimte voor uitval. Eén gebroken link maakt van een ring een keten: nog volledig verbonden, maar met langere paden en meer doorgaand verkeer. Een tweede breuk splitst het cluster. Een driehoek verdraagt één breuk zonder enig doorgaand verkeer.

En het wordt slechter op een manier die makkelijker te tekenen dan te beschrijven is. Voeg een vijfde node toe en de helft van elk nodepaar in het cluster hangt af van iemand anders die doorstuurt:

Een ring van vijf nodes: de helft van de nodeparen hangt nu af van iemand anders die doorstuurtmesh1mesh2mesh3mesh4mesh5kabel — direct, één hopgeen kabel — een buur moet doorsturenVijf nodes, elk twee poorten10 nodeparen in totaal5 hebben een directe kabel5 niet, en gaan via een buurElke node stuurt nu verkeer doordat niet van hemzelf is.In plaats daarvan een volledig mesh?10 kabels, en 4 poorten per node— twee NIC's extra in elke server,en daar houdt het ontwerp op.Bij drie nodes gaat er niets via een ander. Bij vier twee paren. Bij vijf de helft — en éénbreuk maakt elk pad langer.
Tien nodeparen, vijf kabels. De gestreepte lijnen zijn paren zonder kabel ertussen — elk daarvan is Ceph-verkeer dat door de links van een derde node rijdt. Het volledige mesh dat dat zou vermijden wil vier poorten per server.

Dat is het echte plafond van dit ontwerp, en het is niet het routeringsprotocol. OpenFabric gaat er prima mee om. Het is dat het aantal poorten per node vast is, dus voorbij drie nodes maakt elke nieuwe bak meer van jouw verkeer tot iemand anders zijn doorgaand verkeer.

En de eerlijke aantekening, want die doet ter zake bij een bouw die tot hier alleen de webinterface heeft gebruikt: een sysctl is geen actie in de webinterface. Volgens de regel die eerder is gesteld maakt dat het een voorwaarde om te benoemen in plaats van iets om stil op de opdrachtregel op te lossen — schrijf het in het draaiboek, want de volgende die het SDN-paneel opent ziet een gezonde fabric en geen enkele hint dat een ring van een bestand in /etc/sysctl.d afhangt.

Terugdraaien

Verwijderen is de bouw in omgekeerde volgorde, in dezelfde interface: verwijder de SDN-objecten die voor het mesh zijn gemaakt, pas de configuratie toe, en bevestig dat de beheertoegang onaangeroerd is.

Die laatste stap is waarom nic0 en de switch van 2,5 Gbit bestaan. Als het terugdraaien van het mesh je de webinterface zou kunnen kosten, was het ontwerp al verkeerd voordat je begon.

Voordat je begint

  • Beheertoegang is echt onafhankelijk van het mesh. Kijk het na, neem het niet aan.
  • Alle drie de nodes zijn gezond voordat er een SDN-wijziging komt.
  • Nodenamen, interfacenamen en het draadwerk staan opgeschreven, want nic1 op de ene host die nic2 op de andere is, is een slechte middag.
  • Jumboframes staan op beide meshinterfaces, en de MTU houdt rekening met de overhead van VXLAN op de onderlaag.
  • Het meshbereik is gereserveerd en nergens anders in gebruik.

Bronnen

  • Proxmox VE — Software-Defined Network — de documentatie over SDN Fabrics. Fabrics “provide automated routing between nodes in a cluster”, OpenFabric is “based on IS-IS and optimized for the spine-leaf topology common in data centers”, elke node heeft een uniek Router-ID nodig, en “a dummy ’loopback’ interface with the router-id is automatically created”
  • Proxmox VE — Cluster Manager — het netwerk van Corosync en redundante links, achter het ontwerp met lidmaatschap over twee paden
  • Proxmox VE — Deploy Hyper-Converged Ceph Cluster — de netwerkverwachtingen voor een hyperconvergent cluster
  • Linux kernel — IP sysctl documentation — ip_forward en de standaard van 0, de doorstuurbesturing per interface, en de waarschuwing dat het wijzigen van de globale schakelaar de configuratie per interface reset