Fino podešavanje rutiranja za MetalLB u L2 modu

Fino podešavanje rutiranja za MetalLB u L2 modu
Nedavno sam se suočio sa vrlo neobičnim zadatkom postavljanja rutiranja za MetalLB. Sve bi bilo u redu, jer... Obično MetalLB ne zahtijeva nikakve dodatne radnje, ali u našem slučaju imamo prilično veliki klaster sa vrlo jednostavnom mrežnom konfiguracijom.

U ovom članku ću vam reći kako da konfigurirate rutiranje zasnovano na izvoru i politici za vanjsku mrežu vašeg klastera.

Neću ulaziti u detalje o instalaciji i konfiguraciji MetalLB-a, jer pretpostavljam da već imate iskustva. Predlažem da pređemo direktno na stvar, odnosno postavljanje rutiranja. Dakle, imamo četiri slučaja:

Slučaj 1: Kada nije potrebna konfiguracija

Pogledajmo jednostavan slučaj.

Fino podešavanje rutiranja za MetalLB u L2 modu

Dodatna konfiguracija rutiranja nije potrebna kada su adrese koje izdaje MetalLB u istoj podmreži kao i adrese vaših čvorova.

Na primjer, imate podmrežu 192.168.1.0/24, ima ruter 192.168.1.1, a vaši čvorovi primaju adrese: 192.168.1.10-30, zatim za MetalLB možete podesiti raspon 192.168.1.100-120 i budite sigurni da će raditi bez ikakvih dodatnih konfiguracija.

Žašto je to? Budući da vaši čvorovi već imaju konfigurirane rute:

# 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

A adrese iz istog raspona će ih ponovo koristiti bez ikakvih dodatnih radnji.

Slučaj 2: Kada je potrebno dodatno prilagođavanje

Fino podešavanje rutiranja za MetalLB u L2 modu

Trebali biste konfigurirati dodatne rute kad god vaši čvorovi nemaju konfiguriranu IP adresu ili rutu do podmreže za koju MetalLB izdaje adrese.

Objasniću malo detaljnije. Kad god MetalLB izbaci adresu, može se uporediti sa jednostavnim dodjelom kao što je:

ip addr add 10.9.8.7/32 dev lo

Obratite pažnju na:

  • a) Adresa se dodjeljuje prefiksom /32 to jest, ruta neće biti automatski dodana u podmrežu za nju (to je samo adresa)
  • b) Adresa je povezana sa bilo kojim sučeljem čvora (na primjer loopback). Ovdje je vrijedno spomenuti karakteristike Linux mrežnog steka. Bez obzira na koje sučelje dodate adresu, kernel će uvijek obraditi arp zahtjeve i poslati arp odgovore na bilo koji od njih, ovo ponašanje se smatra ispravnim i, štoviše, prilično se koristi u tako dinamičnom okruženju kao što je Kubernetes.

Ovo ponašanje se može prilagoditi, na primjer omogućavanjem strict arp:

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

U ovom slučaju, arp odgovori će biti poslani samo ako interfejs eksplicitno sadrži određenu IP adresu. Ova postavka je potrebna ako planirate da koristite MetalLB i vaš kube-proxy radi u IPVS modu.

Međutim, MetalLB ne koristi kernel za obradu arp zahtjeva, već to radi sam u korisničkom prostoru, tako da ova opcija neće utjecati na rad MetalLB-a.

Vratimo se našem zadatku. Ako ruta za izdate adrese ne postoji na vašim čvorovima, dodajte je unaprijed svim čvorovima:

ip route add 10.9.8.0/24 dev eth1

Slučaj 3: Kada vam je potrebno rutiranje zasnovano na izvoru

Moraćete da konfigurišete rutiranje zasnovano na izvoru kada primate pakete kroz poseban gateway, a ne onaj koji je podrazumevano konfigurisan, stoga paketi odgovora takođe treba da prolaze kroz isti gateway.

Na primjer, imate istu podmrežu 192.168.1.0/24 posvećen vašim čvorovima, ali želite da izdate eksterne adrese koristeći MetalLB. Pretpostavimo da imate više adresa iz podmreže 1.2.3.0/24 koji se nalaze u VLAN 100 i želite da ih koristite za eksterni pristup Kubernetes servisima.

Fino podešavanje rutiranja za MetalLB u L2 modu

Prilikom kontakta 1.2.3.4 postavljat ćete zahtjeve iz druge podmreže 1.2.3.0/24 i sačekajte odgovor. Čvor koji je trenutno glavni za adresu koju je izdao MetalLB 1.2.3.4, će primiti paket od rutera 1.2.3.1, ali odgovor za njega mora nužno ići istim putem, kroz 1.2.3.1.

Pošto naš čvor već ima konfiguriran default gateway 192.168.1.1, tada će po defaultu odgovor ići njemu, a ne njemu 1.2.3.1, preko koje smo primili paket.

Kako izaći na kraj sa ovom situacijom?

U ovom slučaju, morate pripremiti sve svoje čvorove na takav način da budu spremni za opsluživanje vanjskih adresa bez dodatne konfiguracije. To jest, za gornji primjer, morate unaprijed kreirati VLAN sučelje na čvoru:

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

Zatim dodajte rute:

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

Imajte na umu da rute dodajemo u zasebnu tabelu rutiranja 100 sadržat će samo dvije rute potrebne za slanje paketa odgovora kroz gateway 1.2.3.1, koji se nalazi iza interfejsa eth0.100.

Sada moramo dodati jednostavno pravilo:

ip rule add from 1.2.3.0/24 lookup 100

što eksplicitno kaže: ako je izvorna adresa paketa u 1.2.3.0/24, tada trebate koristiti tabelu rutiranja 100. U njemu smo već opisali rutu kojom će ga poslati 1.2.3.1

Slučaj 4: Kada vam je potrebno usmjeravanje zasnovano na politici

Mrežna topologija je ista kao u prethodnom primjeru, ali recimo da također želite imati pristup adresama vanjskog bazena 1.2.3.0/24 iz vaših mahuna:

Fino podešavanje rutiranja za MetalLB u L2 modu

Posebnost je u tome što prilikom pristupa bilo kojoj adresi u 1.2.3.0/24, paket odgovora pogađa čvor i ima izvornu adresu u rasponu 1.2.3.0/24 će biti poslušno poslat na eth0.100, ali želimo da ga Kubernetes preusmjeri na naš prvi pod, koji je generirao originalni zahtjev.

Rješavanje ovog problema pokazalo se teškim, ali je postalo moguće zahvaljujući usmjeravanju zasnovanom na politikama:

Za bolje razumijevanje procesa, evo blok dijagrama netfiltera:
Fino podešavanje rutiranja za MetalLB u L2 modu

Prvo, kao u prethodnom primjeru, napravimo dodatnu tablicu usmjeravanja:

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

Sada dodajmo nekoliko pravila za 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

Ova pravila će označiti dolazne veze na interfejs eth0.100, označavajući sve pakete oznakom 0x100, odgovori unutar iste veze će također biti označeni istom oznakom.

Sada možemo dodati pravilo rutiranja:

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

Odnosno, svi paketi sa izvornom adresom 1.2.3.0/24 i tag 0x100 moraju biti rutirani pomoću tabele 100.

Dakle, drugi paketi primljeni na drugom interfejsu ne podležu ovom pravilu, što će im omogućiti da budu rutirani pomoću standardnih Kubernetes alata.

Ima još nešto, u Linuxu postoji takozvani filter obrnutih putanja, koji kvari cijelu stvar; on vrši jednostavnu provjeru: za sve dolazne pakete mijenja izvornu adresu paketa sa adresom pošiljaoca i provjerava da li paket može otići kroz isti interfejs na kojem je primljen, ako nije, filtrirat će ga.

Problem je što u našem slučaju neće raditi kako treba, ali ga možemo onemogućiti:

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

Imajte na umu da prva komanda kontroliše globalno ponašanje rp_filter; ako nije onemogućena, druga komanda neće imati efekta. Međutim, preostala sučelja će ostati s uključenim rp_filterom.

Kako ne bismo u potpunosti ograničili rad filtera, možemo koristiti implementaciju rp_filter za netfilter. Koristeći rpfilter kao iptables modul, možete konfigurirati prilično fleksibilna pravila, na primjer:

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

omogućite rp_filter na interfejsu eth0.100 za sve adrese osim 1.2.3.0/24.

izvor: www.habr.com

Dodajte komentar