Enrutamento de axuste fino para MetalLB no modo L2

Enrutamento de axuste fino para MetalLB no modo L2
Non hai moito enfrontarme a unha tarefa moi inusual de configurar o enrutamento para MetalLB. Todo estaría ben, porque... Normalmente MetalLB non require ningunha acción adicional, pero no noso caso temos un clúster bastante grande cunha configuración de rede moi sinxela.

Neste artigo vouche dicir como configurar o enrutamento baseado en fontes e en políticas para a rede externa do teu clúster.

Non vou entrar en detalles sobre a instalación e configuración de MetalLB, xa que supoño que xa tes algunha experiencia. Suxiro ir directamente ao grano, é dicir, configurar o enrutamento. Entón temos catro casos:

Caso 1: cando non se precisa ningunha configuración

Vexamos un caso sinxelo.

Enrutamento de axuste fino para MetalLB no modo L2

Non é necesaria unha configuración de enrutamento adicional cando os enderezos emitidos por MetalLB están na mesma subrede que os enderezos dos teus nodos.

Por exemplo, tes unha subrede 192.168.1.0/24, ten un enrutador 192.168.1.1, e os teus nodos reciben enderezos: 192.168.1.10-30, entón para MetalLB pode axustar o rango 192.168.1.100-120 e asegúrese de que funcionarán sen ningunha configuración adicional.

Por que é iso? Porque os teus nodos xa teñen rutas configuradas:

# 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

E os enderezos do mesmo rango reutilizaranos sen ningunha acción adicional.

Caso 2: cando se require personalización adicional

Enrutamento de axuste fino para MetalLB no modo L2

Debe configurar rutas adicionais sempre que os seus nodos non teñan un enderezo IP configurado ou unha ruta á subrede para a que MetalLB emite enderezos.

Vou explicar cun pouco máis de detalle. Sempre que MetalLB saca un enderezo, pódese comparar cunha asignación sinxela como:

ip addr add 10.9.8.7/32 dev lo

Preste atención a:

  • a) O enderezo está asignado cun prefixo /32 é dicir, unha ruta non se engadirá automaticamente á subrede para ela (só é un enderezo)
  • b) O enderezo está unido a calquera interface de nodo (por exemplo, loopback). Paga a pena mencionar aquí as características da pila de rede Linux. Independentemente da interface á que engadas o enderezo, o núcleo sempre procesará as solicitudes arp e enviará respostas arp a calquera delas, este comportamento considérase correcto e, ademais, úsase bastante nun ambiente tan dinámico como Kubernetes.

Este comportamento pódese personalizar, por exemplo, activando arp estrito:

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

Neste caso, as respostas arp só se enviarán se a interface contén explícitamente un enderezo IP específico. Esta configuración é necesaria se pensas usar MetalLB e o teu kube-proxy está a executarse en modo IPVS.

Non obstante, MetalLB non usa o núcleo para procesar solicitudes arp, senón que o fai por si mesmo no espazo de usuario, polo que esta opción non afectará o funcionamento de MetalLB.

Volvamos á nosa tarefa. Se a ruta para os enderezos emitidos non existe nos teus nodos, engádea con antelación a todos os nodos:

ip route add 10.9.8.0/24 dev eth1

Caso 3: cando necesites un enrutamento baseado na fonte

Deberá configurar o enrutamento baseado na orixe cando reciba paquetes a través dunha pasarela separada, non a configurada por defecto, polo que os paquetes de resposta tamén deberían pasar pola mesma pasarela.

Por exemplo, tes a mesma subrede 192.168.1.0/24 dedicado aos teus nodos, pero queres emitir enderezos externos usando MetalLB. Supoñamos que tes varios enderezos dunha subrede 1.2.3.0/24 situado na VLAN 100 e quere usalos para acceder aos servizos de Kubernetes externamente.

Enrutamento de axuste fino para MetalLB no modo L2

Ao contactar 1.2.3.4 realizará solicitudes desde unha subrede diferente á 1.2.3.0/24 e agardar unha resposta. O nodo que é actualmente o mestre para o enderezo emitido por MetalLB 1.2.3.4, recibirá o paquete do router 1.2.3.1, pero a resposta para el debe ir necesariamente polo mesmo camiño, a través 1.2.3.1.

Xa que o noso nodo xa ten unha pasarela predeterminada configurada 192.168.1.1, entón por defecto a resposta irá a el, e non a 1.2.3.1, a través do cal recibimos o paquete.

Como facer fronte a esta situación?

Neste caso, cómpre preparar todos os seus nós de forma que estean preparados para servir enderezos externos sen configuración adicional. É dicir, para o exemplo anterior, cómpre crear unha interface VLAN no nodo con antelación:

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

E despois engade rutas:

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

Teña en conta que engadimos rutas a unha táboa de rutas separada 100 só conterá dúas rutas necesarias para enviar un paquete de resposta a través da pasarela 1.2.3.1, situado detrás da interface eth0.100.

Agora necesitamos engadir unha regra sinxela:

ip rule add from 1.2.3.0/24 lookup 100

que di explícitamente: se o enderezo de orixe do paquete está en 1.2.3.0/24, entón cómpre utilizar a táboa de enrutamento 100. Nel xa describimos o percorrido que o enviará 1.2.3.1

Caso 4: cando necesites un enrutamento baseado en políticas

A topoloxía da rede é a mesma que no exemplo anterior, pero digamos que tamén queres acceder a enderezos de grupo externos 1.2.3.0/24 das túas vainas:

Enrutamento de axuste fino para MetalLB no modo L2

A peculiaridade é que ao acceder a calquera enderezo en 1.2.3.0/24, o paquete de resposta chega ao nodo e ten un enderezo de orixe no intervalo 1.2.3.0/24 será enviado obedientemente a eth0.100, pero queremos que Kubernetes o redirija ao noso primeiro pod, que xerou a solicitude orixinal.

Resolver este problema resultou difícil, pero fíxose posible grazas ao enrutamento baseado en políticas:

Para unha mellor comprensión do proceso, aquí tes un diagrama de bloques de netfilter:
Enrutamento de axuste fino para MetalLB no modo L2

En primeiro lugar, como no exemplo anterior, creemos unha táboa de enrutamento adicional:

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

Agora imos engadir algunhas regras a 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

Estas regras marcarán as conexións entrantes á interface eth0.100, marcando todos os paquetes coa etiqueta 0x100, as respostas dentro da mesma conexión tamén se marcarán coa mesma etiqueta.

Agora podemos engadir unha regra de enrutamento:

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

É dicir, todos os paquetes cun enderezo de orixe 1.2.3.0/24 e etiquetar 0x100 debe ser encamiñada mediante unha táboa 100.

Así, outros paquetes recibidos noutra interface non están suxeitos a esta regra, o que permitirá encamiñalos mediante ferramentas estándar de Kubernetes.

Hai unha cousa máis, en Linux hai un filtro de camiño inverso, que estraga todo; realiza unha comprobación sinxela: para todos os paquetes entrantes, cambia o enderezo de orixe do paquete co enderezo do remitente e verifica se o paquete pode saír pola mesma interface na que foi recibido, se non, filtrarao.

O problema é que no noso caso non funcionará correctamente, pero podemos desactivalo:

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

Teña en conta que o primeiro comando controla o comportamento global de rp_filter; se non está desactivado, o segundo comando non terá ningún efecto. Non obstante, as interfaces restantes permanecerán con rp_filter activado.

Para non limitar completamente o funcionamento do filtro, podemos usar a implementación rp_filter para netfilter. Usando rpfilter como módulo de iptables, pode configurar regras bastante flexibles, por exemplo:

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

habilite rp_filter na interface eth0.100 para todos os enderezos excepto 1.2.3.0/24.

Fonte: www.habr.com

Engadir un comentario