
Nyligen stötte jag pÄ en ganska ovanlig uppgift att stÀlla in routing för MetalLB. Det skulle inte vara nÄgot problem, eftersom det vanligtvis inte krÀvs nÄgra extra ÄtgÀrder för MetalLB, men i vÄrt fall har vi en ganska stor kluster med en ganska enkel nÀtverkskonfiguration.
I denna artikel kommer jag att berÀtta hur man stÀller in source-based och policy-based routing för det externa nÀtverket i din kluster.
Jag kommer inte att gÄ in pÄ installation och konfiguration av MetalLB i detalj, eftersom jag utgÄr frÄn att du redan har viss erfarenhet. LÄt oss gÄ direkt till saken, nÀmligen konfigurationen av routingen. SÄ vi har fyra fall:
Fall 1: NÀr ingen konfigurering krÀvs
LÄt oss gÄ igenom ett enkelt fall.

Ytterligare routing konfiguration krÀvs inte nÀr de adresser som MetalLB tillhandahÄller ligger i samma subnet som adresserna för dina noder.
Till exempel har du ett subnet 192.168.1.0/24, det finns en router 192.168.1.1, och dina noder fÄr adresser: 192.168.1.10-30, dÄ kan du för MetalLB konfigurera intervallet 192.168.1.100-120 och vara sÀker pÄ att de kommer att fungera utan nÄgon ytterligare konfiguration.
Varför sÄ? För att dina noder redan har konfigurerade rutter:
# 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.10Och adresser frÄn samma intervall kommer att ÄteranvÀnda dem utan nÄgra ytterligare ÄtgÀrder.
Fall 2: NÀr ytterligare konfiguration krÀvs

Du bör stÀlla in ytterligare rutter varje gÄng dina noder inte har en konfigurerad IP-adresser eller rutt till subnÀtet för vilket MetalLB tillhandahÄller adresser.
LÄt mig förklara lite mer ingÄende. Varje gÄng MetalLB tillhandahÄller en adress kan det liknas vid en enkel tilldelning som:
ip addr add 10.9.8.7/32 dev loObservera att:
- a) Adressen tilldelas med prefix
/32vilket betyder att rutt till subnÀtet för den automatiskt inte kommer att lÀggas till (det Àr bara en adress) - b) Adressen kopplas till vilken nodens grÀnssnitt som helst (till exempel loopback). HÀr Àr det vÀrt att nÀmna hur Linux-nÀtverksstacks funktioner. Det spelar ingen roll vilket grÀnssnitt du lÀgger till adressen, kÀrnan kommer alltid att hantera arp-förfrÄgningar och skicka arp-svar pÄ vilket som helst av dem, detta beteende anses vara korrekt och dessutom anvÀnds det ganska ofta i en dynamisk miljö som Kubernetes.
Detta beteende kan konfigureras, 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_announceI det hÀr fallet kommer arp-svar endast att skickas om grÀnssnittet uttryckligen innehÄller en specifik IP-adress. Denna instÀllning Àr obligatorisk om du planerar att anvÀnda MetalLB och din kube-proxy fungerar 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ÀndarlÀget, sÄ denna alternativ kommer inte att pÄverka MetalLB:s funktion.
LÄt oss ÄtervÀnda till vÄr uppgift. Om det inte finns nÄgon rutt för de tilldelade adresserna pÄ dina noder, lÀgg till den i förvÀg pÄ alla noder:
ip route add 10.9.8.0/24 dev eth1Fall 3: NÀr du behöver source-based routing
Source-based routing behöver du konfigurera nÀr du tar emot paket genom en separat gateway, inte den som Àr instÀlld som standard, sÄ att svarspaketen ocksÄ mÄste gÄ genom denna gateway.
Till exempel har du samma subnet 192.168.1.0/24 tilldelat för dina noder, men du vill tilldela externa adresser med hjÀlp av MetalLB. Anta att du har flera adresser frÄn subnettet 1.2.3.0/24 som ligger i VLAN 100, och du vill anvÀnda dem för att fÄ Ätkomst till Kubernetes-tjÀnster utifrÄn.

NÀr du gör en förfrÄgan till 1.2.3.4 gör du förfrÄgningar frÄn ett annat subnet Àn 1.2.3.0/24 och vÀntar pÄ svar. Den nod som för tillfÀllet Àr master för den tilldelade MetalLB-adressen 1.2.3.4, kommer att ta emot paket frÄn routern 1.2.3.1, men svaret mÄste nödvÀndigtvis skickas tillbaka samma vÀg, genom 1.2.3.1.
Eftersom vÄr nod redan har en instÀlld default gateway 192.168.1.1, sÄ kommer svaret som standard att gÄ dit, och inte till 1.2.3.1, genom vilken vi tog emot paketet.
Hur hanterar vi denna situation?
I det hÀr fallet mÄste du förbereda alla dina noder sÄ att de Àr redo att hantera externa adresser utan ytterligare konfiguration. Det vill sÀga för det ovanstÄende exemplet mÄste du i förvÀg skapa ett VLAN-grÀnssnitt pÄ noden:
ip link add link eth0 name eth0.100 type vlan id 100
ip link set eth0.100 upOch sedan lÀgga 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 100Observera att rutter vi lÀgger till i en separat routingtabell 100 den kommer endast att innehÄlla tvÄ rutter som Àr nödvÀndiga för att skicka svarspaketet genom gateway 1.2.3.1, som ligger bakom grÀnssnittet eth0.100.
Nu behöver vi lÀgga till en enkel regel:
ip rule add from 1.2.3.0/24 lookup 100som tydligt sÀger: om kÀlladressen för paketet ligger i 1.2.3.0/24, dÄ ska routingtabellen anvÀndas 100. I den har vi redan beskrivit en vÀg som skickar den genom 1.2.3.1
Fall 4: NÀr policy-baserad routing behövs
NÀtverks Topologi som i det föregÄende exemplet, men lÄt oss sÀga att du ocksÄ vill ha möjligheten att komma Ät externa adresser i poolen 1.2.3.0/24 frÄn dina pods:

Det unika Àr att nÀr man kontaktar en adress i 1.2.3.0/24, kommer svaret att nÄ noden och ha kÀllaadressen inom omrÄdet 1.2.3.0/24 och kommer lydigt att skickas till eth0.100, men vi vill att Kubernetes ska omdirigera det till vÄr första podd som initialt genererade förfrÄgan.
Att lösa detta problem visade sig vara utmanande, men det blev möjligt tack vare policy-baserad routing:
För att bÀttre förstÄ processen, lÄt mig ge dig ett flödesschema för netfilter:

Först, som i det föregÄende exemplet, lÄt oss 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 100Nu lÀgger vi till nÄgra regler i 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-markDessa regler kommer att mÀrka inkommande anslutningar pÄ grÀnssnittet eth0.100, mÀrkning av alla paket med taggen 0x100, samma tagg kommer ocksÄ att anvÀndas för svaren inom en och samma anslutning.
Nu kan vi lÀgga till en routingregel:
ip rule add from 1.2.3.0/24 fwmark 0x100 lookup 100Det vill sÀga alla paket med kÀllaadressen 1.2.3.0/24 och taggen 0x100 ska routas med hjÀlp av tabellen 100.
SÄledes kommer andra paket som tas emot pÄ ett annat grÀnssnitt inte att omfattas av denna regel, vilket tillÄter dem att routas med standardmetoderna i Kubernetes.
Det finns en annan aspekt, i Linux finns det sÄ kallad reverse path filter som stÀller till det genom att utföra en enkel kontroll: för alla inkommande paket Àndrar den kÀllaadressen i paketet med avsÀndarens adress och kontrollerar om paketet kan skickas ut genom samma grÀnssnitt som det mottogs pÄ, om inte, filtreras det.
Problemet Àr att det i vÄrt fall kommer att fungera inkorrekt, men vi kan stÀnga av det:
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth0.100/rp_filterObservera att det första kommandot kontrollerar det globala beteendet hos rp_filter, om det inte stĂ€ngs av, kommer det andra kommandot inte att ha nĂ„gon effekt. ĂndĂ„ kommer de andra grĂ€nssnitten att förbli med rp_filter aktiverat.
För att inte helt begrÀnsa fungerar filtret kan vi anvÀnda implementeringen rp_filter för netfilter. Genom att anvÀnda rpfilter som en iptables-modul kan man stÀlla in 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 DROPaktivera rp_filter pÄ grÀnssnittet eth0.100 för alla adresser utom 1.2.3.0/24.
KĂ€lla: habr.com
