Finjustera routing för MetalLB i L2-läge

Finjustera routing för MetalLB i L2-läge
För inte så länge sedan stod jag inför en mycket ovanlig uppgift att sätta upp routing för MetalLB. Allt skulle vara bra, för... Vanligtvis kräver MetalLB inga ytterligare åtgärder, men i vårt fall har vi ett ganska stort kluster med en väldigt enkel nätverkskonfiguration.

I den här artikeln kommer jag att berätta hur du konfigurerar källbaserad och policybaserad routing för ditt klusters externa nätverk.

Jag kommer inte att gå in på detaljer om installation och konfigurering av MetalLB, eftersom jag antar att du redan har viss erfarenhet. Jag föreslår att du går rakt på sak, nämligen att ställa in routing. Så vi har fyra fall:

Fall 1: När ingen konfiguration krävs

Låt oss titta på ett enkelt fall.

Finjustera routing för MetalLB i L2-läge

Ytterligare routingkonfiguration krävs inte när adresserna utfärdade av MetalLB finns i samma subnät som adresserna till dina noder.

Du har till exempel ett subnät 192.168.1.0/24, den har en router 192.168.1.1, och dina noder får adresser: 192.168.1.10-30, sedan för MetalLB kan du justera intervallet 192.168.1.100-120 och var säker på att de kommer att fungera utan ytterligare konfiguration.

Varför är det så? Eftersom dina noder redan har rutter konfigurerade:

# 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

Och adresser från samma intervall kommer att återanvända dem utan ytterligare åtgärder.

Fall 2: När ytterligare anpassning krävs

Finjustera routing för MetalLB i L2-läge

Du bör konfigurera ytterligare rutter närhelst dina noder inte har en konfigurerad IP-adress eller rutt till subnätet som MetalLB utfärdar adresser för.

Jag ska förklara lite mer detaljerat. Närhelst MetalLB matar ut en adress kan den jämföras med en enkel uppgift som:

ip addr add 10.9.8.7/32 dev lo

Uppmärksamma:

  • a) Adressen tilldelas med ett prefix /32 det vill säga, en rutt kommer inte automatiskt att läggas till undernätet för den (det är bara en adress)
  • b) Adressen är kopplad till valfritt nodgränssnitt (till exempel loopback). Det är värt att nämna här funktionerna i Linux-nätverksstacken. Oavsett vilket gränssnitt du lägger till adressen till, kommer kärnan alltid att bearbeta arp-förfrågningar och skicka arp-svar till någon av dem, detta beteende anses vara korrekt och är dessutom ganska flitigt använt i en så dynamisk miljö som Kubernetes.

Detta beteende kan anpassas, till exempel genom att aktivera strikt arp:

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

I det här fallet kommer arp-svar endast att skickas om gränssnittet uttryckligen innehåller en specifik IP-adress. Den här inställningen krävs om du planerar att använda MetalLB och din kube-proxy körs i IPVS-läge.

MetalLB använder dock inte kärnan för att bearbeta arp-förfrågningar, utan gör det själv i användarutrymmet, så det här alternativet kommer inte att påverka driften av MetalLB.

Låt oss återgå till vår uppgift. Om rutten för de utfärdade adresserna inte finns på dina noder, lägg till den i förväg till alla noder:

ip route add 10.9.8.0/24 dev eth1

Fall 3: När du behöver källbaserad routing

Du måste konfigurera källbaserad routing när du tar emot paket genom en separat gateway, inte den som är konfigurerad som standard, därför bör svarspaket också gå genom samma gateway.

Du har till exempel samma subnät 192.168.1.0/24 dedikerad till dina noder, men du vill utfärda externa adresser med MetalLB. Låt oss anta att du har flera adresser från ett subnät 1.2.3.0/24 finns i VLAN 100 och du vill använda dem för att komma åt Kubernetes tjänster externt.

Finjustera routing för MetalLB i L2-läge

Vid kontakt 1.2.3.4 du kommer att göra förfrågningar från ett annat subnät än 1.2.3.0/24 och vänta på svar. Noden som för närvarande är master för den MetalLB-utfärdade adressen 1.2.3.4, kommer att ta emot paketet från routern 1.2.3.1, men svaret för honom måste nödvändigtvis gå samma väg, igenom 1.2.3.1.

Eftersom vår nod redan har en konfigurerad standardgateway 192.168.1.1, då kommer svaret som standard att gå till honom och inte till 1.2.3.1, genom vilken vi fick paketet.

Hur ska man hantera denna situation?

I det här fallet måste du förbereda alla dina noder på ett sådant sätt att de är redo att betjäna externa adresser utan ytterligare konfiguration. Det vill säga, för exemplet ovan måste du skapa ett VLAN-gränssnitt på noden i förväg:

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

Och lägg sedan till rutter:

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

Observera att vi lägger till rutter i en separat rutttabell 100 den kommer att innehålla endast två vägar som är nödvändiga för att skicka ett svarspaket genom gatewayen 1.2.3.1, som finns bakom gränssnittet eth0.100.

Nu måste vi lägga till en enkel regel:

ip rule add from 1.2.3.0/24 lookup 100

som uttryckligen säger: om paketets källadress finns i 1.2.3.0/24, då måste du använda routingtabellen 100. I den har vi redan beskrivit rutten som kommer att skicka honom igenom 1.2.3.1

Fall 4: När du behöver policybaserad routing

Nätverkstopologin är densamma som i föregående exempel, men låt oss säga att du också vill ha tillgång till externa pooladresser 1.2.3.0/24 från dina poddar:

Finjustera routing för MetalLB i L2-läge

Det speciella är att när man kommer åt vilken adress som helst i 1.2.3.0/24, träffar svarspaketet noden och har en källadress i intervallet 1.2.3.0/24 kommer lydigt att skickas till eth0.100, men vi vill att Kubernetes ska omdirigera den till vår första pod, som genererade den ursprungliga begäran.

Att lösa detta problem visade sig vara svårt, men det blev möjligt tack vare policybaserad routing:

För en bättre förståelse av processen, här är ett blockschema för nätfilter:
Finjustera routing för MetalLB i L2-läge

Låt oss först, som i det föregående exemplet, skapa en extra routingtabell:

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

Låt oss nu lägga till några regler för 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

Dessa regler kommer att markera inkommande anslutningar till gränssnittet eth0.100, markerar alla paket med taggen 0x100, kommer svar inom samma anslutning också att markeras med samma tagg.

Nu kan vi lägga till en routingregel:

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

Det vill säga alla paket med en källadress 1.2.3.0/24 och tagga 0x100 måste dirigeras med hjälp av en tabell 100.

Sålunda omfattas inte andra paket som tas emot på ett annat gränssnitt av denna regel, vilket gör att de kan dirigeras med hjälp av vanliga Kubernetes-verktyg.

Det finns en sak till, i Linux finns det ett så kallat omvänd sökvägsfilter, som förstör det hela, det utför en enkel kontroll: för alla inkommande paket ändrar den källadressen för paketet med avsändaradressen och kontrollerar om paketet kan lämna genom samma gränssnitt som det togs emot, om inte, kommer det att filtrera bort det.

Problemet är att i vårt fall kommer det inte att fungera korrekt, men vi kan inaktivera det:

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

Observera att det första kommandot styr det globala beteendet för rp_filter; om det inte är inaktiverat kommer det andra kommandot inte att ha någon effekt. De återstående gränssnitten kommer dock att förbli med rp_filter aktiverat.

För att inte helt begränsa driften av filtret kan vi använda implementeringen rp_filter för netfilter. Genom att använda rpfilter som en iptables-modul kan du konfigurera ganska flexibla regler, till exempel:

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

aktivera rp_filter på gränssnittet eth0.100 för alla adresser utom 1.2.3.0/24.

Källa: will.com

Lägg en kommentar