Nem sokkal ezelőtt egy nagyon szokatlan feladattal kellett szembenéznem: útválasztást kell beállítani a MetalLB számára. Minden rendben lenne, mert... Általában a MetalLB nem igényel további műveleteket, de esetünkben egy meglehetősen nagy klaszterrel rendelkezünk, nagyon egyszerű hálózati konfigurációval.
Ebben a cikkben elmondom, hogyan konfigurálhat forrás- és házirend-alapú útválasztást a fürt külső hálózatához.
Nem részletezem a MetalLB telepítését és konfigurálását, mivel feltételezem, hogy már van némi tapasztalata. Azt javaslom, hogy menjen közvetlenül a lényegre, nevezetesen az útválasztás beállítására. Tehát négy esetünk van:
1. eset: Amikor nincs szükség konfigurációra
Nézzünk egy egyszerű esetet.
Nincs szükség további útválasztási konfigurációra, ha a MetalLB által kiadott címek ugyanabban az alhálózatban vannak, mint a csomópontok címei.
Például van egy alhálózata 192.168.1.0/24
, router van benne 192.168.1.1
, és a csomópontok címeket kapnak: 192.168.1.10-30
, akkor a MetalLB esetében beállíthatja a tartományt 192.168.1.100-120
és győződjön meg arról, hogy minden további konfiguráció nélkül működni fognak.
Miert van az? Mivel a csomópontokon már vannak konfigurálva az útvonalak:
# 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
Az azonos tartományba tartozó címek pedig további műveletek nélkül újra felhasználják őket.
2. eset: Ha további testreszabásra van szükség
További útvonalakat kell konfigurálnia, ha a csomópontok nem rendelkeznek konfigurált IP-címmel vagy útvonallal arra az alhálózatra, amelyhez a MetalLB címeket bocsát ki.
Kicsit részletesebben kifejtem. Amikor a MetalLB egy címet ad ki, az összehasonlítható egy egyszerű hozzárendeléssel, például:
ip addr add 10.9.8.7/32 dev lo
Figyelni:
- a) A címhez egy előtag tartozik
/32
vagyis egy útvonal nem kerül automatikusan hozzá az alhálózathoz (ez csak egy cím) - b) A cím bármely csomóponti interfészhez csatolva van (például loopback). Itt érdemes megemlíteni a Linux hálózati verem tulajdonságait. Függetlenül attól, hogy melyik interfészhez adja hozzá a címet, a kernel mindig feldolgozza az arp kéréseket, és bármelyikre küldi az arp válaszokat, ez a viselkedés helyesnek tekinthető, és ráadásul meglehetősen széles körben használják olyan dinamikus környezetben, mint a Kubernetes.
Ez a viselkedés testreszabható, például a szigorú arp engedélyezésével:
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
Ebben az esetben az arp válaszokat csak akkor küldi el, ha az interfész kifejezetten tartalmaz egy adott IP-címet. Ez a beállítás akkor szükséges, ha MetalLB-t kíván használni, és a kube-proxy IPVS módban fut.
A MetalLB azonban nem használja a kernelt az arp kérések feldolgozására, hanem saját maga végzi el a felhasználói térben, így ez az opció nem befolyásolja a MetalLB működését.
Térjünk vissza a feladatunkhoz. Ha a kiadott címekhez tartozó útvonal nem létezik a csomópontokon, előzetesen adja hozzá az összes csomóponthoz:
ip route add 10.9.8.0/24 dev eth1
3. eset: Ha forrásalapú útválasztásra van szüksége
Be kell állítania a forrás alapú útválasztást, ha külön átjárón keresztül kap csomagokat, nem az alapértelmezés szerint beállítotton, ezért a válaszcsomagoknak is ugyanazon az átjárón kell keresztülmenniük.
Például ugyanaz az alhálózata van 192.168.1.0/24
dedikált a csomópontjaihoz, de külső címeket szeretne kiadni a MetalLB használatával. Tegyük fel, hogy több címe van egy alhálózatból 1.2.3.0/24
a VLAN 100-ban található, és a Kubernetes-szolgáltatásokhoz külsőleg szeretne hozzáférni.
Kapcsolatfelvételkor 1.2.3.4
más alhálózatról fog kérni, mint 1.2.3.0/24
és várja a választ. Az a csomópont, amely jelenleg a MetalLB által kiadott cím mestere 1.2.3.4
, megkapja a csomagot a routertől 1.2.3.1
, de a válasznak feltétlenül ugyanazon az úton kell haladnia, keresztül 1.2.3.1
.
Mivel a csomópontunknak már van beállított alapértelmezett átjárója 192.168.1.1
, akkor alapértelmezés szerint a válasz neki fog menni, és nem 1.2.3.1
, amelyen keresztül megkaptuk a csomagot.
Hogyan lehet megbirkózni ezzel a helyzettel?
Ebben az esetben az összes csomópontot úgy kell előkészítenie, hogy készen álljanak a külső címek további konfiguráció nélküli kiszolgálására. Vagyis a fenti példában előzetesen létre kell hoznia egy VLAN interfészt a csomóponton:
ip link add link eth0 name eth0.100 type vlan id 100
ip link set eth0.100 up
Ezután adjon hozzá útvonalakat:
ip route add 1.2.3.0/24 dev eth0.100 table 100
ip route add default via 1.2.3.1 table 100
Felhívjuk figyelmét, hogy az útvonalakat külön útválasztási táblázatba adjuk 100
csak két olyan útvonalat fog tartalmazni, amelyek a válaszcsomag átjárón keresztül történő elküldéséhez szükségesek 1.2.3.1
, amely az interfész mögött található eth0.100
.
Most hozzá kell adnunk egy egyszerű szabályt:
ip rule add from 1.2.3.0/24 lookup 100
amely kifejezetten azt mondja: ha a csomag forráscíme benne van 1.2.3.0/24
, akkor az útválasztási táblát kell használnia 100
. Ebben már leírtuk az útvonalat, amelyen keresztül eljut 1.2.3.1
4. eset: Ha házirend-alapú útválasztásra van szüksége
A hálózati topológia ugyanaz, mint az előző példában, de tegyük fel, hogy külső készletcímeket is szeretne elérni 1.2.3.0/24
a hüvelyeidből:
A sajátosság az, hogy bármely cím elérésekor 1.2.3.0/24
, a válaszcsomag eléri a csomópontot, és a tartományban van egy forráscíme 1.2.3.0/24
engedelmesen elküldik majd eth0.100
, de azt szeretnénk, hogy a Kubernetes átirányítsa az első podba, amely az eredeti kérést generálta.
A probléma megoldása nehéznek bizonyult, de a házirend-alapú útválasztásnak köszönhetően lehetségessé vált:
A folyamat jobb megértése érdekében itt van egy netfilter blokkdiagram:
Először is, az előző példához hasonlóan, hozzunk létre egy további útválasztó táblát:
ip route add 1.2.3.0/24 dev eth0.100 table 100
ip route add default via 1.2.3.1 table 100
Most adjunk hozzá néhány szabályt az iptables-hoz:
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
Ezek a szabályok megjelölik az interfészhez bejövő kapcsolatokat eth0.100
, minden csomagot megjelölve a címkével 0x100
, az ugyanazon a kapcsolaton belüli válaszok is ugyanazzal a címkével lesznek megjelölve.
Most hozzáadhatunk egy útválasztási szabályt:
ip rule add from 1.2.3.0/24 fwmark 0x100 lookup 100
Vagyis minden csomag forráscímmel 1.2.3.0/24
és tag 0x100
táblázat segítségével kell irányítani 100
.
Így a másik interfészen kapott más csomagokra nem vonatkozik ez a szabály, amely lehetővé teszi, hogy szabványos Kubernetes-eszközökkel irányítsák őket.
Van még valami, a Linuxban van egy úgynevezett reverse path filter, ami elrontja az egészet, egy egyszerű ellenőrzést végez: minden bejövő csomagnál megváltoztatja a csomag forráscímét a küldő címével, és ellenőrzi, hogy a csomag ugyanazon az interfészen keresztül távozhat, amelyen érkezett, ha nem, akkor kiszűri.
A probléma az, hogy esetünkben nem fog megfelelően működni, de letilthatjuk:
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth0.100/rp_filter
Kérjük, vegye figyelembe, hogy az első parancs az rp_filter globális viselkedését szabályozza; ha nincs letiltva, a második parancsnak nincs hatása. A többi interfészen azonban az rp_filter engedélyezve marad.
Annak érdekében, hogy ne korlátozzuk teljesen a szűrő működését, használhatjuk az rp_filter implementációt a netfilterhez. Az rpfilter iptables modulként való használatával meglehetősen rugalmas szabályokat állíthat be, például:
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
engedélyezze az rp_filtert az interfészen eth0.100
minden címre, kivéve 1.2.3.0/24
.
Forrás: will.com