Reglare fină a rutare pentru MetalLB în modul L2

Reglare fină a rutare pentru MetalLB în modul L2
Nu cu mult timp în urmă m-am confruntat cu o sarcină foarte neobișnuită de a configura rutarea pentru MetalLB. Totul ar fi bine, pentru că... De obicei MetalLB nu necesită acțiuni suplimentare, dar în cazul nostru avem un cluster destul de mare cu o configurație de rețea foarte simplă.

În acest articol, vă voi spune cum să configurați rutarea bazată pe sursă și bazată pe politici pentru rețeaua externă a clusterului dvs.

Nu voi intra în detalii despre instalarea și configurarea MetalLB, deoarece presupun că aveți deja ceva experiență. Vă sugerez să mergeți direct la obiect, și anume să configurați rutarea. Deci avem patru cazuri:

Cazul 1: Când nu este necesară nicio configurație

Să ne uităm la un caz simplu.

Reglare fină a rutare pentru MetalLB în modul L2

Configurația suplimentară de rutare nu este necesară atunci când adresele emise de MetalLB sunt în aceeași subrețea cu adresele nodurilor dvs.

De exemplu, aveți o subrețea 192.168.1.0/24, are un router 192.168.1.1, iar nodurile dvs. primesc adrese: 192.168.1.10-30, apoi pentru MetalLB puteți regla intervalul 192.168.1.100-120 și asigurați-vă că vor funcționa fără nicio configurație suplimentară.

De ce este asta? Deoarece nodurile dvs. au deja rute configurate:

# 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

Și adresele din aceeași gamă le vor reutiliza fără acțiuni suplimentare.

Cazul 2: Când este necesară personalizarea suplimentară

Reglare fină a rutare pentru MetalLB în modul L2

Ar trebui să configurați rute suplimentare ori de câte ori nodurile dumneavoastră nu au o adresă IP configurată sau o rută către subrețeaua pentru care MetalLB emite adrese.

O să explic puțin mai detaliat. Ori de câte ori MetalLB scoate o adresă, aceasta poate fi comparată cu o atribuire simplă precum:

ip addr add 10.9.8.7/32 dev lo

Fi atent la:

  • a) Adresa este atribuită cu un prefix /32 adică o rută nu va fi adăugată automat la subrețea pentru aceasta (este doar o adresă)
  • b) Adresa este atașată la orice interfață nod (de exemplu loopback). Merită menționat aici caracteristicile stivei de rețea Linux. Indiferent de interfața la care adăugați adresa, nucleul va procesa întotdeauna cererile arp și va trimite răspunsuri arp la oricare dintre ele, acest comportament este considerat corect și, în plus, este destul de utilizat într-un mediu atât de dinamic precum Kubernetes.

Acest comportament poate fi personalizat, de exemplu, activând arp strict:

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

În acest caz, răspunsurile arp vor fi trimise numai dacă interfața conține în mod explicit o anumită adresă IP. Această setare este necesară dacă intenționați să utilizați MetalLB și kube-proxy-ul rulează în modul IPVS.

Cu toate acestea, MetalLB nu folosește nucleul pentru a procesa cererile arp, ci o face singur în spațiul utilizatorului, așa că această opțiune nu va afecta funcționarea MetalLB.

Să revenim la sarcina noastră. Dacă ruta pentru adresele emise nu există pe nodurile dvs., adăugați-o în avans la toate nodurile:

ip route add 10.9.8.0/24 dev eth1

Cazul 3: Când aveți nevoie de rutare bazată pe sursă

Va trebui să configurați rutarea bazată pe sursă atunci când primiți pachete printr-un gateway separat, nu cel configurat implicit, prin urmare pachetele de răspuns ar trebui să treacă și prin aceeași poartă.

De exemplu, aveți aceeași subrețea 192.168.1.0/24 dedicat nodurilor dvs., dar doriți să emiteți adrese externe folosind MetalLB. Să presupunem că aveți mai multe adrese dintr-o subrețea 1.2.3.0/24 situat în VLAN 100 și doriți să le utilizați pentru a accesa serviciile Kubernetes extern.

Reglare fină a rutare pentru MetalLB în modul L2

La contact 1.2.3.4 veți face solicitări dintr-o subrețea diferită de 1.2.3.0/24 și așteptați un răspuns. Nodul care este în prezent master pentru adresa emisă de MetalLB 1.2.3.4, va primi pachetul de la router 1.2.3.1, dar răspunsul pentru el trebuie să meargă neapărat pe același drum, prin 1.2.3.1.

Deoarece nodul nostru are deja un gateway implicit configurat 192.168.1.1, apoi implicit răspunsul va merge către el și nu către 1.2.3.1, prin care am primit coletul.

Cum să faci față acestei situații?

În acest caz, trebuie să vă pregătiți toate nodurile astfel încât acestea să fie gata să servească adrese externe fără configurare suplimentară. Adică, pentru exemplul de mai sus, trebuie să creați în avans o interfață VLAN pe nod:

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

Și apoi adăugați 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

Vă rugăm să rețineți că adăugăm rute la un tabel de rutare separat 100 va conține doar două rute necesare pentru a trimite un pachet de răspuns prin gateway 1.2.3.1, situat în spatele interfeței eth0.100.

Acum trebuie să adăugăm o regulă simplă:

ip rule add from 1.2.3.0/24 lookup 100

care spune în mod explicit: dacă adresa sursă a pachetului este în 1.2.3.0/24, atunci trebuie să utilizați tabelul de rutare 100. În ea am descris deja traseul prin care îl va trimite 1.2.3.1

Cazul 4: Când aveți nevoie de rutare bazată pe politici

Topologia rețelei este aceeași ca în exemplul anterior, dar să presupunem că doriți și să puteți accesa adresele de pool externe 1.2.3.0/24 din păstăile tale:

Reglare fină a rutare pentru MetalLB în modul L2

Particularitatea este că atunci când accesați orice adresă în 1.2.3.0/24, pachetul de răspuns lovește nodul și are o adresă sursă în interval 1.2.3.0/24 va fi trimis cu ascultare la eth0.100, dar dorim ca Kubernetes să-l redirecționeze către primul nostru pod, care a generat solicitarea inițială.

Rezolvarea acestei probleme s-a dovedit a fi dificilă, dar a devenit posibilă datorită rutării bazate pe politici:

Pentru o mai bună înțelegere a procesului, iată o diagramă bloc netfilter:
Reglare fină a rutare pentru MetalLB în modul L2

Mai întâi, ca în exemplul anterior, să creăm un tabel de rutare suplimentar:

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

Acum să adăugăm câteva reguli la 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

Aceste reguli vor marca conexiunile de intrare la interfață eth0.100, marcând toate pachetele cu eticheta 0x100, răspunsurile din cadrul aceleiași conexiuni vor fi, de asemenea, marcate cu aceeași etichetă.

Acum putem adăuga o regulă de rutare:

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

Adică toate pachetele cu o adresă sursă 1.2.3.0/24 și etichetați 0x100 trebuie dirijate folosind un tabel 100.

Astfel, alte pachete primite pe o altă interfață nu sunt supuse acestei reguli, ceea ce le va permite să fie rutate folosind instrumente standard Kubernetes.

Mai este ceva, în Linux există un așa-numit filtru de cale inversă, care strică totul; efectuează o verificare simplă: pentru toate pachetele primite, schimbă adresa sursă a pachetului cu adresa expeditorului și verifică dacă pachetul poate pleca prin aceeași interfață pe care a fost primit, dacă nu, îl va filtra.

Problema este că în cazul nostru nu va funcționa corect, dar îl putem dezactiva:

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

Vă rugăm să rețineți că prima comandă controlează comportamentul global al rp_filter; dacă nu este dezactivată, a doua comandă nu va avea efect. Cu toate acestea, interfețele rămase vor rămâne cu rp_filter activat.

Pentru a nu limita complet funcționarea filtrului, putem folosi implementarea rp_filter pentru netfilter. Folosind rpfilter ca modul iptables, puteți configura reguli destul de flexibile, de exemplu:

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

activați rp_filter pe interfață eth0.100 pentru toate adresele cu excepția 1.2.3.0/24.

Sursa: www.habr.com

Adauga un comentariu