Ajuste de enrutamiento para MetalLB en modo L2

Ajuste de enrutamiento para MetalLB en modo L2
No hace mucho me enfrenté a una tarea muy inusual: configurar el enrutamiento para MetalLB. Todo estaría bien, porque... Normalmente MetalLB no requiere ninguna acción adicional, pero en nuestro caso tenemos un cluster bastante grande con una configuración de red muy sencilla.

En este artículo, le diré cómo configurar el enrutamiento basado en fuentes y políticas para la red externa de su clúster.

No entraré en detalles sobre la instalación y configuración de MetalLB, ya que supongo que ya tienes algo de experiencia. Sugiero ir directo al grano, es decir, configurar el enrutamiento. Entonces tenemos cuatro casos:

Caso 1: cuando no se requiere configuración

Veamos un caso sencillo.

Ajuste de enrutamiento para MetalLB en modo L2

No se requiere configuración de enrutamiento adicional cuando las direcciones emitidas por MetalLB están en la misma subred que las direcciones de sus nodos.

Por ejemplo, tienes una subred 192.168.1.0/24, tiene un enrutador 192.168.1.1y sus nodos reciben direcciones: 192.168.1.10-30, luego para MetalLB puedes ajustar el rango 192.168.1.100-120 y asegúrese de que funcionarán sin ninguna configuración adicional.

¿Porqué es eso? Porque tus nodos ya tienen 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

Y las direcciones del mismo rango las reutilizarán sin ninguna acción adicional.

Caso 2: Cuando se requiere personalización adicional

Ajuste de enrutamiento para MetalLB en modo L2

Debe configurar rutas adicionales siempre que sus nodos no tengan una dirección IP configurada o una ruta a la subred para la cual MetalLB emite direcciones.

Te lo explicaré con un poco más de detalle. Siempre que MetalLB genera una dirección, se puede comparar con una asignación simple como:

ip addr add 10.9.8.7/32 dev lo

Presta atención a:

  • a) La dirección se asigna con un prefijo. /32 es decir, no se agregará automáticamente una ruta a la subred (es solo una dirección)
  • b) La dirección se adjunta a cualquier interfaz de nodo (por ejemplo, loopback). Vale la pena mencionar aquí las características de la pila de red de Linux. No importa a qué interfaz agregue la dirección, el kernel siempre procesará las solicitudes arp y enviará respuestas arp a cualquiera de ellas, este comportamiento se considera correcto y, además, se usa bastante en un entorno tan dinámico como Kubernetes.

Este comportamiento se puede personalizar, por ejemplo habilitando arp estricto:

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

En este caso, las respuestas arp solo se enviarán si la interfaz contiene explícitamente una dirección IP específica. Esta configuración es necesaria si planea utilizar MetalLB y su kube-proxy se ejecuta en modo IPVS.

Sin embargo, MetalLB no utiliza el kernel para procesar solicitudes arp, sino que lo hace él mismo en el espacio de usuario, por lo que esta opción no afectará el funcionamiento de MetalLB.

Volvamos a nuestra tarea. Si la ruta para las direcciones emitidas no existe en sus nodos, agréguela por adelantado a todos los nodos:

ip route add 10.9.8.0/24 dev eth1

Caso 3: cuando necesita enrutamiento basado en origen

Deberá configurar el enrutamiento basado en origen cuando reciba paquetes a través de una puerta de enlace independiente, no la configurada de forma predeterminada; por lo tanto, los paquetes de respuesta también deben pasar por la misma puerta de enlace.

Por ejemplo, tienes la misma subred 192.168.1.0/24 dedicado a sus nodos, pero desea emitir direcciones externas utilizando MetalLB. Supongamos que tiene varias direcciones de una subred 1.2.3.0/24 ubicado en la VLAN 100 y desea usarlos para acceder a los servicios de Kubernetes externamente.

Ajuste de enrutamiento para MetalLB en modo L2

Al contactar 1.2.3.4 realizará solicitudes desde una subred diferente a la 1.2.3.0/24 y espera una respuesta. El nodo que actualmente es el maestro de la dirección emitida por MetalLB. 1.2.3.4, recibirá el paquete del enrutador 1.2.3.1, pero la respuesta para él necesariamente debe ir por el mismo camino, a través de 1.2.3.1.

Dado que nuestro nodo ya tiene una puerta de enlace predeterminada configurada 192.168.1.1, entonces, de forma predeterminada, la respuesta irá a él y no a 1.2.3.1, a través del cual recibimos el paquete.

¿Cómo afrontar esta situación?

En este caso, debe preparar todos sus nodos de tal manera que estén listos para atender direcciones externas sin configuración adicional. Es decir, para el ejemplo anterior, debe crear una interfaz VLAN en el nodo de antemano:

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

Y luego agregue 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

Tenga en cuenta que agregamos rutas a una tabla de enrutamiento separada 100 contendrá sólo dos rutas necesarias para enviar un paquete de respuesta a través de la puerta de enlace 1.2.3.1, ubicado detrás de la interfaz eth0.100.

Ahora necesitamos agregar una regla simple:

ip rule add from 1.2.3.0/24 lookup 100

que dice explícitamente: si la dirección de origen del paquete está en 1.2.3.0/24, entonces necesitas usar la tabla de enrutamiento 100. En él ya hemos descrito la ruta que lo llevará a través 1.2.3.1

Caso 4: cuando necesita enrutamiento basado en políticas

La topología de la red es la misma que en el ejemplo anterior, pero digamos que también desea poder acceder a direcciones de grupos externos. 1.2.3.0/24 de tus vainas:

Ajuste de enrutamiento para MetalLB en modo L2

La peculiaridad es que al acceder a cualquier dirección en 1.2.3.0/24, el paquete de respuesta llega al nodo y tiene una dirección de origen en el rango 1.2.3.0/24 será enviado obedientemente a eth0.100, pero queremos que Kubernetes lo redirija a nuestro primer pod, que generó la solicitud original.

Resolver este problema resultó difícil, pero fue posible gracias al enrutamiento basado en políticas:

Para una mejor comprensión del proceso, aquí hay un diagrama de bloques de netfilter:
Ajuste de enrutamiento para MetalLB en modo L2

Primero, como en el ejemplo anterior, creemos una tabla de enrutamiento 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

Ahora agreguemos algunas reglas 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 reglas marcarán las conexiones entrantes a la interfaz. eth0.100, marcando todos los paquetes con la etiqueta 0x100, las respuestas dentro de la misma conexión también se marcarán con la misma etiqueta.

Ahora podemos agregar una regla de enrutamiento:

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

Es decir, todos los paquetes con una dirección de origen. 1.2.3.0/24 y etiquetar 0x100 debe enrutarse utilizando una tabla 100.

Así, otros paquetes recibidos en otra interfaz no están sujetos a esta regla, lo que permitirá enrutarlos utilizando herramientas estándar de Kubernetes.

Hay una cosa más, en Linux existe el llamado filtro de ruta inversa, que lo estropea todo; realiza una verificación simple: para todos los paquetes entrantes, cambia la dirección de origen del paquete con la dirección del remitente y verifica si el paquete puede salir por la misma interfaz en la que fue recibido, de lo contrario lo filtrará.

El problema es que en nuestro caso no funcionará correctamente, pero podemos desactivarlo:

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

Tenga en cuenta que el primer comando controla el comportamiento global de rp_filter; si no está deshabilitado, el segundo comando no tendrá ningún efecto. Sin embargo, las interfaces restantes permanecerán con rp_filter habilitado.

Para no limitar completamente el funcionamiento del filtro, podemos utilizar la implementación rp_filter para netfilter. Usando rpfilter como módulo de iptables, puedes configurar reglas bastante flexibles, por ejemplo:

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

habilitar rp_filter en la interfaz eth0.100 para todas las direcciones excepto 1.2.3.0/24.

Fuente: habr.com

Añadir un comentario