Тонкая настройка маршрутызацыі для MetalLB у рэжыме L2

Тонкая настройка маршрутызацыі для MetalLB у рэжыме L2
Не так даўно я сутыкнуўся з вельмі нестандартнай задачай налады маршрутышчацыі для MetalLB. Усё б нічога, т.я. звычайна для MetalLB не патрабуецца ніякіх дадатковых дзеянняў, але ў нашым выпадку маецца дастаткова вялікі кластар з вельмі няхітрай канфігурацыяй сеткі.

У дадзеным артыкуле я распавяду як наладзіць source-based і policy-based routing для вонкавай сеткі вашага кластара.

Я не буду падрабязна спыняцца на ўсталёўцы і наладзе MetalLB, бо мяркую вы ўжо маеце некаторы досвед. Прапаную адразу перайсці да справы, а менавіта да наладкі маршрутызацыі. Дык вось, мы маем чатыры кейсы:

Выпадак 1: Калі настройка не патрабуецца

Разбяром просты кейс.

Тонкая настройка маршрутызацыі для MetalLB у рэжыме L2

Дадатковая настройка маршрутызацыі не патрабуецца, калі выдаваныя 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: Калі патрабуецца дадатковая настройка

Тонкая настройка маршрутызацыі для MetalLB у рэжыме L2

Вам варта наладзіць дадатковыя маршруты кожны раз тады, калі вашы ноды не маюць настроенага IP-адрасу або маршруту ў падсетку для якой MetalLB выдае адрасы.

Растлумачу крыху падрабязней. Кожны раз, калі MetalLB выйдзе адрас, гэта можна параўнаць з простым прызначэннем выгляду:

ip addr add 10.9.8.7/32 dev lo

Звярніце ўвагу, на:

  • a) Адрас прызначаецца з прэфіксам /32 гэта значыць маршрут у падсетку для яго аўтаматычна не дадасца (гэта проста адрас)
  • b) Адрас вешаецца на любы інтэрфейс ноды (напрыклад loopback). Тут варта згадаць, аб асаблівасці сеткавага стэка Linux. Не важна на які інтэрфейс вы дадасце адрас, ядро ​​заўсёды будзе апрацоўваць arp-запыты і адпраўляць arp-адказы на любы з іх, гэтыя паводзіны лічыцца карэктным і, акрамя таго, досыць шырока выкарыстоўваецца ў такім дынамічным асяроддзі як Kubernetes.

Дадзеныя паводзіны можна наладжваць, напрыклад улучыўшы strict 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-proxy працуе ў рэжыме IPVS.

Тым не менш MetalLB не выкарыстоўвае ядро ​​для апрацоўкі arp-запытаў, а робіць гэта самастойна ў user-space, такім чынам дадзеная опцыя не паўплывае на працу MetalLB.

Вернемся да нашай задачы. Калі маршруту для выдаваных адрасоў на вашых нодах не існуе, дадайце яго загадзя на ўсе ноды:

ip route add 10.9.8.0/24 dev eth1

Выпадак 3: Калі спатрэбіцца source-based routing

Source-based routing вам запатрабуецца наладзіць тады, калі вы атрымліваеце пакеты праз асобны gateway, не той што наладжаны ў вас па змаўчанні, адпаведна зваротныя пакеты таксама павінны сыходзіць праз гэты ж gateway.

Напрыклад, у вас ёсць усё таксама падсетку 192.168.1.0/24 выдзеленая для вашых нод, але вы хочаце выдаваць знешнія адрасы з дапамогай MetalLB. Дапусцім, у вас ёсць некалькі адрасоў з падсеткі 1.2.3.0/24 якія знаходзяцца ва VLAN 100, і вы хочаце выкарыстоўваць іх для доступу Kubernetes-службаў звонку.

Тонкая настройка маршрутызацыі для MetalLB у рэжыме L2

Пры звароце на 1.2.3.4 вы будзеце здзяйсняць запыты з іншай падсеткі, чым 1.2.3.0/24 і чакаць адказ. Нода, якая ў дадзены момант з'яўляецца майстрам для выдадзенага MetalLB адраса 1.2.3.4, атрымае пакет ад маршрутызатара 1.2.3.1, але адказ для яго абавязкова павінен сысці тым жа маршрутам, праз 1.2.3.1.

Бо наша нода ўжо мае наладжаны default gateway 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: Калі спатрэбіцца policy-based routing

Тапалогія сеткі як і ў папярэднім прыкладзе, але дапусцім вы хочаце таксама мець магчымасць звяртацца да знешніх адрасоў пула 1.2.3.0/24 з вашых подаў:

Тонкая настройка маршрутызацыі для MetalLB у рэжыме L2

Асаблівасць заключаецца ў тым, што пры звароце да любога адрасу ў 1.2.3.0/24, пакет у адказ трапляючы на ​​ноду і маючы адрас крыніцы ў дыяпазоне 1.2.3.0/24 будзе паслухмяна адпраўлены ў eth0.100, Але мы вось хочам каб Kubernetes перанакіраваў яго ў наш першы пад, які і згенераваў першапачатковы запыт.

Вырашыць дадзеную праблему аказалася няпроста, але гэта стала магчымым дзякуючы policy-based routing:

Для большага разумення працэсу прывяду блок схему netfilter:
Тонкая настройка маршрутызацыі для MetalLB у рэжыме L2

Для пачатку, як і ў папярэднім прыкладзе, створым дадатковую табліцу маршрутызацыі:

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 існуе так званы reverse path filter, які псуе ўсю маліну ажыццяўляе простую праверку: для ўсіх уваходных пакетаў ён змяняе адрас крыніцы пакета з адрасам адпраўніка і правярае ці можа пакет сысці праз той жа інтэрфейс на які быў атрыманы , калі не, то адфільтроўваевет яго.

Праблема ў тым, што ў нашым выпадку ён будзе працаваць некарэктна, але мы можам адключыць яго:

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.

Крыніца: habr.com

Дадаць каментар