Не така одамна се соочив со многу необична задача да поставам рутирање за MetalLB. Сè би било добро, бидејќи ... Обично MetalLB не бара никакви дополнителни дејства, но во нашиот случај имаме прилично голем кластер со многу едноставна мрежна конфигурација.
Во оваа статија ќе ви кажам како да конфигурирате рутирање базирано на извор и политика за надворешната мрежа на вашиот кластер.
Нема да навлегувам во детали за инсталирање и конфигурирање на MetalLB, бидејќи претпоставувам дека веќе имате одредено искуство. Предлагам да одиме директно на поентата, имено поставување на рутирање. Значи, имаме четири случаи:
Случај 1: Кога не е потребна конфигурација
Ајде да погледнеме во едноставен случај.
Не е потребна дополнителна конфигурација за рутирање кога адресите издадени од MetalLB се во истата подмрежа како и адресите на вашите јазли.
На пример, имате подмрежа 192.168.1.0/24
, има рутер 192.168.1.1
, и вашите јазли добиваат адреси: 192.168.1.10-30
, потоа за MetalLB можете да го прилагодите опсегот 192.168.1.100-120
и бидете сигурни дека ќе работат без дополнителна конфигурација.
Зошто е тоа? Бидејќи вашите јазли веќе имаат конфигурирани правци:
# 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
И адресите од истиот опсег ќе ги користат повторно без никакви дополнителни дејства.
Случај 2: Кога е потребно дополнително прилагодување
Треба да конфигурирате дополнителни правци секогаш кога вашите јазли немаат конфигурирана IP адреса или маршрута до подмрежата за која адресира издавањето на MetalLB.
Ќе објаснам малку подетално. Секогаш кога MetalLB дава адреса, таа може да се спореди со едноставна задача како:
ip addr add 10.9.8.7/32 dev lo
Обрни внимание на:
- a) Адресата е доделена со префикс
/32
односно, рутата нема автоматски да се додаде во подмрежата за неа (тоа е само адреса) - b) Адресата е прикачена на кој било интерфејс на јазол (на пример, loopback). Овде вреди да се споменат карактеристиките на стекот на мрежата Линукс. Без разлика на кој интерфејс ќе ја додадете адресата, кернелот секогаш ќе обработува arp-барања и ќе испраќа одговори на arp на кое било од нив, ова однесување се смета за правилно и, згора на тоа, е доста широко користено во таква динамична средина како Kubernetes.
Ова однесување може да се приспособи, на пример, со овозможување строг arp:
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
Во овој случај, одговорите на arp ќе се испраќаат само ако интерфејсот експлицитно содржи одредена IP адреса. Оваа поставка е потребна ако планирате да користите MetalLB и вашиот kube-прокси работи во режим IPVS.
Меѓутоа, MetalLB не го користи кернелот за обработка на барањата arp, туку тоа го прави самиот во корисничкиот простор, така што оваа опција нема да влијае на работата на MetalLB.
Да се вратиме на нашата задача. Ако рутата за издадените адреси не постои на вашите јазли, додајте ја однапред на сите јазли:
ip route add 10.9.8.0/24 dev eth1
Случај 3: Кога ви треба рутирање базирано на извор
Ќе треба да конфигурирате рутирање базирано на извор кога примате пакети преку посебна порта, а не онаа што е стандардно конфигурирана, затоа пакетите за одговор исто така треба да поминуваат низ истата порта.
На пример, ја имате истата подмрежа 192.168.1.0/24
посветен на вашите јазли, но сакате да издавате надворешни адреси користејќи MetalLB. Да претпоставиме дека имате повеќе адреси од подмрежа 1.2.3.0/24
се наоѓа во VLAN 100 и сакате да ги користите за надворешно пристап до услугите на Кубернетес.
При контактирање 1.2.3.4
ќе поднесувате барања од друга подмрежа од 1.2.3.0/24
и чекај одговор. Јазолот кој моментално е главен за адресата издадена од MetalLB 1.2.3.4
, ќе го прими пакетот од рутерот 1.2.3.1
, но одговорот за него мора нужно да оди по истиот пат, низ 1.2.3.1
.
Бидејќи нашиот јазол веќе има конфигуриран стандарден портал 192.168.1.1
, тогаш стандардно одговорот ќе оди кај него, а не до 1.2.3.1
, преку кој го добивме пакетот.
Како да се справите со оваа ситуација?
Во овој случај, треба да ги подготвите сите ваши јазли на таков начин што тие се подготвени да опслужуваат надворешни адреси без дополнителна конфигурација. Тоа е, за горенаведениот пример, треба однапред да креирате VLAN интерфејс на јазолот:
ip link add link eth0 name eth0.100 type vlan id 100
ip link set eth0.100 up
И потоа додадете маршрути:
ip route add 1.2.3.0/24 dev eth0.100 table 100
ip route add default via 1.2.3.1 table 100
Ве молиме имајте предвид дека додаваме маршрути во посебна рутирачка табела 100
ќе содржи само две рути неопходни за испраќање на пакет одговор преку портата 1.2.3.1
, кој се наоѓа зад интерфејсот eth0.100
.
Сега треба да додадеме едноставно правило:
ip rule add from 1.2.3.0/24 lookup 100
кој експлицитно вели: ако изворната адреса на пакетот е внатре 1.2.3.0/24
, тогаш треба да ја користите рутирачката табела 100
. Во него веќе ја опишавме рутата по која ќе го испрати 1.2.3.1
Случај 4: Кога ви треба рутирање засновано на политики
Топологијата на мрежата е иста како и во претходниот пример, но да речеме дека сакате да имате пристап до адресите на надворешниот базен 1.2.3.0/24
од вашите мешунки:
Особеноста е во тоа што при пристапување кон која било адреса во 1.2.3.0/24
, пакетот одговор го погодува јазолот и има изворна адреса во опсегот 1.2.3.0/24
ќе биде послушно испратен до eth0.100
, но сакаме Kubernetes да го пренасочи кон нашиот прв pod, кој го генерира оригиналното барање.
Решавањето на овој проблем се покажа како тешко, но стана возможно благодарение на рутирањето засновано на политики:
За подобро разбирање на процесот, тука е блок дијаграм на нетфилтер:
Прво, како и во претходниот пример, ајде да создадеме дополнителна рутирачка табела:
ip route add 1.2.3.0/24 dev eth0.100 table 100
ip route add default via 1.2.3.1 table 100
Сега да додадеме неколку правила на 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
Овие правила ќе ги означат дојдовните врски со интерфејсот eth0.100
, означувајќи ги сите пакети со ознаката 0x100
, одговорите во рамките на истата врска исто така ќе бидат означени со истата ознака.
Сега можеме да додадеме правило за рутирање:
ip rule add from 1.2.3.0/24 fwmark 0x100 lookup 100
Тоа е, сите пакети со изворна адреса 1.2.3.0/24
и означете 0x100
мора да се насочи со помош на табела 100
.
Така, другите пакети добиени на друг интерфејс не подлежат на ова правило, што ќе им овозможи да се насочуваат со користење на стандардни алатки на Kubernetes.
Има уште една работа, во Linux постои таканаречен филтер за обратна патека, кој ја расипува целата работа, врши едноставна проверка: за сите дојдовни пакети, ја менува изворната адреса на пакетот со адресата на испраќачот и проверува дали пакетот може да замине преку истиот интерфејс на кој е примен, ако не, ќе го филтрира.
Проблемот е што во нашиот случај нема да работи правилно, но можеме да го оневозможиме:
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth0.100/rp_filter
Ве молиме имајте предвид дека првата команда го контролира глобалното однесување на rp_filter; ако не е оневозможено, втората команда нема да има ефект. Сепак, преостанатите интерфејси ќе останат со вклучен rp_filter.
За да не ја ограничиме целосно работата на филтерот, можеме да ја користиме имплементацијата rp_filter за netfilter. Користејќи rpfilter како модул iptables, можете да конфигурирате прилично флексибилни правила, на пример:
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
овозможете rp_filter на интерфејсот eth0.100
за сите адреси освен 1.2.3.0/24
.
Извор: www.habr.com