Routing nauwkeurig afstemmen voor MetalLB in L2-modus

Routing nauwkeurig afstemmen voor MetalLB in L2-modus
Nog niet zo lang geleden werd ik geconfronteerd met een zeer ongebruikelijke taak: het opzetten van routing voor MetalLB. Alles zou goed komen, want... Meestal vereist MetalLB geen extra acties, maar in ons geval hebben we een vrij groot cluster met een zeer eenvoudige netwerkconfiguratie.

In dit artikel vertel ik je hoe je source-based en policy-based routing configureert voor het externe netwerk van je cluster.

Ik zal niet in detail treden over het installeren en configureren van MetalLB, omdat ik ervan uitga dat je al enige ervaring hebt. Ik stel voor om meteen ter zake te gaan, namelijk het instellen van routing. We hebben dus vier gevallen:

Geval 1: Wanneer er geen configuratie vereist is

Laten we eens naar een eenvoudig geval kijken.

Routing nauwkeurig afstemmen voor MetalLB in L2-modus

Er is geen aanvullende routeringsconfiguratie vereist wanneer de door MetalLB uitgegeven adressen zich in hetzelfde subnet bevinden als de adressen van uw knooppunten.

U hebt bijvoorbeeld een subnet 192.168.1.0/24, het heeft een router 192.168.1.1, en uw knooppunten ontvangen adressen: 192.168.1.10-30, dan kunt u voor MetalLB het bereik aanpassen 192.168.1.100-120 en zorg ervoor dat ze zullen werken zonder enige aanvullende configuratie.

Waarom is dat? Omdat voor uw knooppunten al routes zijn geconfigureerd:

# ip route
default via 192.168.1.1 dev eth0 onlink 
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10

En adressen uit hetzelfde bereik zullen ze zonder extra handelingen hergebruiken.

Geval 2: Wanneer extra maatwerk nodig is

Routing nauwkeurig afstemmen voor MetalLB in L2-modus

U moet extra routes configureren wanneer uw knooppunten geen geconfigureerd IP-adres of route naar het subnet hebben waarvoor MetalLB adressen uitgeeft.

Ik zal het wat gedetailleerder uitleggen. Telkens wanneer MetalLB een adres uitvoert, kan dit worden vergeleken met een eenvoudige toewijzing, zoals:

ip addr add 10.9.8.7/32 dev lo

Let op:

  • a) Het adres wordt toegewezen met een voorvoegsel /32 dat wil zeggen dat er niet automatisch een route aan het subnet wordt toegevoegd (het is slechts een adres)
  • b) Het adres is gekoppeld aan elke knooppuntinterface (bijvoorbeeld loopback). Het is de moeite waard om hier de kenmerken van de Linux-netwerkstack te vermelden. Het maakt niet uit aan welke interface je het adres toevoegt, de kernel zal altijd arp-verzoeken verwerken en arp-antwoorden naar elk van hen sturen. Dit gedrag wordt als correct beschouwd en wordt bovendien vrij veel gebruikt in zo'n dynamische omgeving als Kubernetes.

Dit gedrag kan worden aangepast, bijvoorbeeld door strikte arp in te schakelen:

echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

In dit geval worden arp-antwoorden alleen verzonden als de interface expliciet een specifiek IP-adres bevat. Deze instelling is vereist als u MetalLB wilt gebruiken en uw kube-proxy in IPVS-modus draait.

MetalLB gebruikt de kernel echter niet om arp-verzoeken te verwerken, maar doet dit zelf in de gebruikersruimte, dus deze optie heeft geen invloed op de werking van MetalLB.

Laten we terugkeren naar onze taak. Als de route voor de uitgegeven adressen niet bestaat op uw knooppunten, voeg deze dan vooraf toe aan alle knooppunten:

ip route add 10.9.8.0/24 dev eth1

Geval 3: Wanneer u brongebaseerde routering nodig heeft

U moet brongebaseerde routering configureren als u pakketten ontvangt via een aparte gateway, niet de gateway die standaard is geconfigureerd. Daarom moeten responspakketten ook via dezelfde gateway gaan.

U hebt bijvoorbeeld hetzelfde subnet 192.168.1.0/24 toegewezen aan uw knooppunten, maar u wilt externe adressen uitgeven met MetalLB. Laten we aannemen dat u meerdere adressen van een subnet heeft 1.2.3.0/24 bevinden zich in VLAN 100 en u wilt deze gebruiken om extern toegang te krijgen tot Kubernetes-services.

Routing nauwkeurig afstemmen voor MetalLB in L2-modus

Bij contact 1.2.3.4 u zult verzoeken indienen vanuit een ander subnet dan 1.2.3.0/24 en wacht op een antwoord. Het knooppunt dat momenteel de master is voor het door MetalLB uitgegeven adres 1.2.3.4, ontvangt het pakket van de router 1.2.3.1, maar het antwoord voor hem moet noodzakelijkerwijs dezelfde route volgen, via 1.2.3.1.

Omdat ons knooppunt al een geconfigureerde standaardgateway heeft 192.168.1.1, dan gaat het antwoord standaard naar hem, en niet naar 1.2.3.1, via welke wij het pakket hebben ontvangen.

Hoe om te gaan met deze situatie?

In dit geval moet u al uw knooppunten zo voorbereiden dat ze klaar zijn om externe adressen te bedienen zonder aanvullende configuratie. Dat wil zeggen dat u voor het bovenstaande voorbeeld vooraf een VLAN-interface op het knooppunt moet maken:

ip link add link eth0 name eth0.100 type vlan id 100
ip link set eth0.100 up

En voeg vervolgens routes toe:

ip route add 1.2.3.0/24 dev eth0.100 table 100
ip route add default via 1.2.3.1 table 100

Houd er rekening mee dat we routes toevoegen aan een aparte routeringstabel 100 het bevat slechts twee routes die nodig zijn om een ​​antwoordpakket via de gateway te verzenden 1.2.3.1, gelegen achter de interface eth0.100.

Nu moeten we een eenvoudige regel toevoegen:

ip rule add from 1.2.3.0/24 lookup 100

waarin expliciet staat: als het bronadres van het pakket binnen is 1.2.3.0/24, dan moet je de routeringstabel gebruiken 100. Daarin hebben we al de route beschreven die hem zal doorsturen 1.2.3.1

Geval 4: Wanneer u op beleid gebaseerde routering nodig heeft

De netwerktopologie is hetzelfde als in het vorige voorbeeld, maar stel dat u ook toegang wilt hebben tot externe pooladressen 1.2.3.0/24 uit je peulen:

Routing nauwkeurig afstemmen voor MetalLB in L2-modus

De bijzonderheid is dat bij toegang tot een adres in 1.2.3.0/24, raakt het antwoordpakket het knooppunt en heeft het een bronadres in het bereik 1.2.3.0/24 zal gehoorzaam worden toegezonden eth0.100, maar we willen dat Kubernetes het omleidt naar onze eerste pod, die het oorspronkelijke verzoek heeft gegenereerd.

Het oplossen van dit probleem bleek lastig, maar werd mogelijk dankzij policy-based routing:

Voor een beter begrip van het proces is hier een netfilter-blokdiagram:
Routing nauwkeurig afstemmen voor MetalLB in L2-modus

Laten we eerst, net als in het vorige voorbeeld, een extra routeringstabel maken:

ip route add 1.2.3.0/24 dev eth0.100 table 100
ip route add default via 1.2.3.1 table 100

Laten we nu een paar regels toevoegen aan iptables:

iptables -t mangle -A PREROUTING -i eth0.100 -j CONNMARK --set-mark 0x100
iptables -t mangle -A PREROUTING  -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j RETURN
iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark

Deze regels markeren inkomende verbindingen met de interface eth0.100, waarbij alle pakketten met de tag worden gemarkeerd 0x100, worden reacties binnen dezelfde verbinding ook gemarkeerd met dezelfde tag.

Nu kunnen we een routeringsregel toevoegen:

ip rule add from 1.2.3.0/24 fwmark 0x100 lookup 100

Dat wil zeggen, alle pakketten met een bronadres 1.2.3.0/24 en labelen 0x100 moet worden gerouteerd met behulp van een tabel 100.

Andere pakketten die op een andere interface worden ontvangen, vallen dus niet onder deze regel, waardoor ze kunnen worden gerouteerd met behulp van standaard Kubernetes-tools.

Er is nog één ding: in Linux is er een zogenaamd reverse path-filter, dat de hele zaak verpest; het voert een eenvoudige controle uit: voor alle inkomende pakketten verandert het het bronadres van het pakket met het afzenderadres en controleert of het pakket kan via dezelfde interface vertrekken waarop het is ontvangen, zo niet, dan wordt het eruit gefilterd.

Het probleem is dat het in ons geval niet correct zal werken, maar we kunnen het uitschakelen:

echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth0.100/rp_filter

Houd er rekening mee dat het eerste commando het globale gedrag van rp_filter regelt; als het niet is uitgeschakeld, heeft het tweede commando geen effect. De overige interfaces blijven echter behouden met rp_filter ingeschakeld.

Om de werking van het filter niet volledig te beperken, kunnen we de rp_filter-implementatie voor netfilter gebruiken. Door rpfilter als iptables-module te gebruiken, kunt u vrij flexibele regels configureren, bijvoorbeeld:

iptables -t raw -A PREROUTING -i eth0.100 -d 1.2.3.0/24 -j RETURN
iptables -t raw -A PREROUTING -i eth0.100 -m rpfilter --invert -j DROP

schakel rp_filter in op de interface eth0.100 voor alle adressen behalve 1.2.3.0/24.

Bron: www.habr.com

Voeg een reactie