Finjustere ruting for MetalLB i L2-modus

Finjustere ruting for MetalLB i L2-modus
For ikke lenge siden ble jeg møtt med en veldig uvanlig oppgave med å sette opp ruting for MetalLB. Alt ville vært bra, fordi... Vanligvis krever MetalLB ingen ekstra handlinger, men i vårt tilfelle har vi en ganske stor klynge med en veldig enkel nettverkskonfigurasjon.

I denne artikkelen vil jeg fortelle deg hvordan du konfigurerer kildebasert og policybasert ruting for det eksterne nettverket til klyngen din.

Jeg vil ikke gå i detalj om installasjon og konfigurering av MetalLB, siden jeg antar at du allerede har litt erfaring. Jeg foreslår at du går rett på sak, nemlig å sette opp ruting. Så vi har fire tilfeller:

Tilfelle 1: Når ingen konfigurasjon er nødvendig

La oss se på en enkel sak.

Finjustere ruting for MetalLB i L2-modus

Ytterligere rutingkonfigurasjon er ikke nødvendig når adressene utstedt av MetalLB er i samme undernett som adressene til nodene dine.

For eksempel har du et subnett 192.168.1.0/24, den har en ruter 192.168.1.1, og nodene dine mottar adresser: 192.168.1.10-30, så for MetalLB kan du justere rekkevidden 192.168.1.100-120 og vær sikker på at de vil fungere uten ytterligere konfigurasjon.

Hvorfor det? Fordi nodene dine allerede har konfigurert ruter:

# 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

Og adresser fra samme område vil gjenbruke dem uten ytterligere handlinger.

Tilfelle 2: Når ytterligere tilpasning er nødvendig

Finjustere ruting for MetalLB i L2-modus

Du bør konfigurere flere ruter når nodene dine ikke har en konfigurert IP-adresse eller rute til subnettet som MetalLB utsteder adresser for.

Jeg skal forklare litt mer detaljert. Når MetalLB sender ut en adresse, kan den sammenlignes med en enkel oppgave som:

ip addr add 10.9.8.7/32 dev lo

Følg med på:

  • a) Adressen tildeles med et prefiks /32 det vil si at en rute ikke automatisk legges til undernettet for den (det er bare en adresse)
  • b) Adressen er knyttet til et hvilket som helst nodegrensesnitt (for eksempel loopback). Det er verdt å nevne her funksjonene til Linux-nettverksstabelen. Uansett hvilket grensesnitt du legger til adressen til, vil kjernen alltid behandle arp-forespørsler og sende arp-svar til noen av dem, denne oppførselen anses som korrekt og er dessuten ganske mye brukt i et så dynamisk miljø som Kubernetes.

Denne oppførselen kan tilpasses, for eksempel ved å aktivere streng arp:

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

I dette tilfellet vil arp-svar bare sendes hvis grensesnittet eksplisitt inneholder en spesifikk IP-adresse. Denne innstillingen er nødvendig hvis du planlegger å bruke MetalLB og kube-proxyen din kjører i IPVS-modus.

MetalLB bruker imidlertid ikke kjernen til å behandle arp-forespørsler, men gjør det selv i brukerområdet, så dette alternativet vil ikke påvirke driften av MetalLB.

La oss gå tilbake til oppgaven vår. Hvis ruten for de utstedte adressene ikke finnes på nodene dine, legg den til på forhånd til alle noder:

ip route add 10.9.8.0/24 dev eth1

Tilfelle 3: Når du trenger kildebasert ruting

Du må konfigurere kildebasert ruting når du mottar pakker gjennom en separat gateway, ikke den som er konfigurert som standard, derfor bør svarpakker også gå gjennom samme gateway.

For eksempel har du samme subnett 192.168.1.0/24 dedikert til nodene dine, men du vil utstede eksterne adresser ved hjelp av MetalLB. La oss anta at du har flere adresser fra et undernett 1.2.3.0/24 ligger i VLAN 100 og du vil bruke dem til å få tilgang til Kubernetes-tjenester eksternt.

Finjustere ruting for MetalLB i L2-modus

Ved kontakt 1.2.3.4 du vil komme med forespørsler fra et annet undernett enn 1.2.3.0/24 og venter på svar. Noden som for øyeblikket er master for den MetalLB-utstedte adressen 1.2.3.4, vil motta pakken fra ruteren 1.2.3.1, men svaret for ham må nødvendigvis gå samme vei, gjennom 1.2.3.1.

Siden noden vår allerede har en konfigurert standard gateway 192.168.1.1, da vil svaret som standard gå til ham, og ikke til 1.2.3.1, som vi mottok pakken gjennom.

Hvordan takle denne situasjonen?

I dette tilfellet må du forberede alle nodene dine på en slik måte at de er klare til å betjene eksterne adresser uten ekstra konfigurasjon. Det vil si at for eksempelet ovenfor må du lage et VLAN-grensesnitt på noden på forhånd:

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

Og legg deretter til ruter:

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ær oppmerksom på at vi legger til ruter i en egen rutetabell 100 den vil inneholde bare to ruter som er nødvendige for å sende en svarpakke gjennom gatewayen 1.2.3.1, plassert bak grensesnittet eth0.100.

Nå må vi legge til en enkel regel:

ip rule add from 1.2.3.0/24 lookup 100

som eksplisitt sier: hvis pakkens kildeadresse er i 1.2.3.0/24, så må du bruke rutetabellen 100. I den har vi allerede beskrevet ruten som vil sende ham gjennom 1.2.3.1

Tilfelle 4: Når du trenger policy-basert ruting

Nettverkstopologien er den samme som i forrige eksempel, men la oss si at du også vil ha tilgang til eksterne bassengadresser 1.2.3.0/24 fra podene dine:

Finjustere ruting for MetalLB i L2-modus

Det særegne er at når du får tilgang til en hvilken som helst adresse i 1.2.3.0/24, treffer svarpakken noden og har en kildeadresse i området 1.2.3.0/24 vil lydig bli sendt til eth0.100, men vi vil at Kubernetes skal omdirigere den til vår første pod, som genererte den opprinnelige forespørselen.

Å løse dette problemet viste seg å være vanskelig, men det ble mulig takket være policybasert ruting:

For en bedre forståelse av prosessen, her er et netfilter blokkdiagram:
Finjustere ruting for MetalLB i L2-modus

La oss først, som i forrige eksempel, lage en ekstra rutetabell:

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

La oss nå legge til noen regler for 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

Disse reglene vil merke innkommende tilkoblinger til grensesnittet eth0.100, merker alle pakker med taggen 0x100, vil svar innenfor samme tilkobling også merkes med samme tag.

Nå kan vi legge til en rutingregel:

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

Det vil si alle pakker med en kildeadresse 1.2.3.0/24 og tag 0x100 må rutes ved hjelp av en tabell 100.

Dermed er andre pakker mottatt på et annet grensesnitt ikke underlagt denne regelen, som vil tillate dem å bli rutet ved hjelp av standard Kubernetes-verktøy.

Det er en ting til, i Linux er det et såkalt omvendt banefilter, som ødelegger det hele; det utfører en enkel sjekk: for alle innkommende pakker endrer den kildeadressen til pakken med avsenderadressen og sjekker om pakken kan gå gjennom det samme grensesnittet som den ble mottatt på, hvis ikke, vil den filtrere den ut.

Problemet er at i vårt tilfelle vil det ikke fungere riktig, men vi kan deaktivere det:

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

Vær oppmerksom på at den første kommandoen kontrollerer den globale oppførselen til rp_filter; hvis den ikke er deaktivert, vil den andre kommandoen ikke ha noen effekt. Imidlertid vil de gjenværende grensesnittene forbli med rp_filter aktivert.

For ikke å begrense driften av filteret fullstendig, kan vi bruke implementeringen rp_filter for netfilter. Ved å bruke rpfilter som en iptables-modul kan du konfigurere ganske fleksible regler, for eksempel:

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

aktiver rp_filter på grensesnittet eth0.100 for alle adresser unntatt 1.2.3.0/24.

Kilde: www.habr.com

Legg til en kommentar