# 1. Guía avanzada de Multus en Kubernetes ## 1.1 Instala Multus (opcional, para múltiples redes) Multus permite que un pod tenga más de una interfaz de red (multi-homed), útil para appliances, firewalls, balanceadores, gateways, etc. Instálalo si necesitas conectar pods a varias redes físicas o VLANs (por ejemplo, mediante bridges y NADs). **Instalación:** ```bash kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset.yml ``` **Verifica:** ```bash kubectl get pods -n kube-system | grep multus ``` --- ## 1.2 (Opcional) Quita el taint del nodo master para poder programar pods en él Por defecto, Kubernetes no programa pods de usuario en el nodo principal (control-plane). Elimina este bloqueo para poder desplegar aplicaciones ahí. ```bash kubectl taint nodes --all node-role.kubernetes.io/control-plane- kubectl taint nodes --all node-role.kubernetes.io/master- ``` --- ## 1.3 Crea el bridge físico en todos los nodos Para que Multus pueda conectar pods a una red física o VLAN, debes crear un bridge Linux con el mismo nombre en **todos** los nodos del clúster. Ejemplo usando NetworkManager/nmcli: ```bash # 1. Crear el bridge (br-srv) y ponerle IP si quieres conectividad L3 nmcli con add type bridge ifname br-srv con-name br-srv nmcli con mod br-srv ipv4.addresses 192.168.200.1/22 nmcli con mod br-srv ipv4.method manual nmcli con up br-srv # 2. Crear la VLAN asociada (vlan20) sobre el bond nmcli con add type vlan ifname vlan20 dev bond0 id 20 con-name vlan20 nmcli con mod vlan20 ipv4.method disabled ipv6.method ignore nmcli con mod vlan20 master br-srv connection.slave-type bridge nmcli con up vlan20 ``` * **IMPORTANTE:** Repite en todos los nodos, y asigna una IP distinta del mismo rango a cada uno si es posible. * El bridge debe estar **UP y con IP activa** para funcionar correctamente a nivel L2/L3. --- ## 1.4 Crea la NetworkAttachmentDefinition (NAD) Ejemplo: ```yaml apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: name: br-srv namespace: default spec: config: '{ "cniVersion": "0.3.1", "type": "bridge", "bridge": "br-srv", "ipam": { "type": "host-local", "subnet": "192.168.200.0/22", "rangeStart": "192.168.200.100", "rangeEnd": "192.168.200.200" } }' ``` Despliega: ```bash kubectl apply -f multus/nad-br-servicios.yaml ``` --- ## 1.5 Despliega pods multi-homed de prueba ```yaml apiVersion: v1 kind: Pod metadata: name: multus-test annotations: k8s.v1.cni.cncf.io/networks: br-srv spec: containers: - name: alpine image: alpine command: ["sleep", "infinity"] securityContext: capabilities: add: ["NET_ADMIN"] ``` --- ## 1.6 Verifica la conectividad L2/L3 entre pods ```bash kubectl exec -it multus-test -- sh ip a ``` * Deberías ver dos interfaces: una de Flannel (eth0) y una de la red secundaria (net1). * **IMPORTANTE:** Si el bridge físico (`br-srv`) está up pero SIN IP, la conectividad entre pods en nodos diferentes **NO funcionará**. Los bridges deben tener una IP asignada y activa. ### **¿Por qué es necesario que el bridge tenga IP?** * El bridge sólo se comporta como una red L2 completa entre nodos cuando está “activo”, es decir, con una IP asociada en todos los hosts. * Si no tiene IP, sólo funcionará el tráfico entre pods del mismo nodo (unicast y broadcast entre nodos puede no funcionar). * Al asignar una IP al bridge, Linux activa la tabla ARP y gestiona correctamente los vecinos y el reenvío entre interfaces del bridge. --- ## 1.7 Limpieza de recursos ```bash kubectl delete pod multus-test kubectl delete pod multus-test2 kubectl delete -f multus/nad-br-servicios.yaml ``` --- ## 1.8 Ejemplo de estructura de archivos ``` multus/ ├── nad-br-servicios.yaml ├── test-multus-pod.yaml ├── test-multus-pod2.yaml └── readme.md ``` --- ## 1.9 Resumen rápido * Multus + bridge = pods multi-homed en redes físicas. * El bridge **debe estar vivo y con IP** en todos los nodos. * Sin IP en el bridge, no hay tráfico entre pods en nodos distintos. * Puedes crear tantas NAD como bridges/VLANs requieras. --- # 2. Instalación y configuración de MetalLB (LoadBalancer local) MetalLB permite asignar IPs flotantes de tu red LAN a servicios `LoadBalancer`, igual que hacen los clústeres en la nube. Es fundamental si quieres exponer servicios como ingress, dashboards, etc., accesibles desde tu red local. --- ## 2.1 Instala MetalLB ```bash kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml ``` Esto crea el namespace `metallb-system` y despliega los pods necesarios. --- ## 2.2 Define un pool con múltiples rangos En lugar de crear múltiples `IPAddressPool` por separado, puedes declarar varios rangos de IP en un **solo** `IPAddressPool`. Esto simplifica la gestión. **Ejemplo: `metallb/ipaddresspool.yaml`** ```yaml apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: pool-general namespace: metallb-system spec: addresses: - 192.168.1.100-192.168.1.110 # Rango 1: producción - 192.168.2.100-192.168.2.110 # Rango 2: laboratorio ``` **Ejemplo: `metallb/l2advertisement.yaml`** ```yaml apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: advert-general namespace: metallb-system spec: {} ``` **Kustomization:** ```yaml resources: - ipaddresspool.yaml - l2advertisement.yaml ``` Para aplicar: ```bash kubectl apply -k metallb/ ``` --- ## 2.3 Asignar una IP concreta al Service (`loadBalancerIP`) Puedes indicar directamente la IP deseada usando el campo `loadBalancerIP`, y MetalLB la asignará si pertenece a uno de los rangos definidos. ### ✅ Ejemplo 1: Asignación explícita con `loadBalancerIP` ```yaml apiVersion: v1 kind: Service metadata: name: nginx-prod spec: selector: app: nginx ports: - port: 80 targetPort: 80 type: LoadBalancer loadBalancerIP: 192.168.1.105 # IP concreta del pool ``` No es necesario usar anotaciones si la IP está incluida en el `IPAddressPool`. ### ✅ Ejemplo 2: Sin IP explícita (MetalLB elige una disponible) ```yaml apiVersion: v1 kind: Service metadata: name: nginx-lab spec: selector: app: nginx ports: - port: 8080 targetPort: 80 type: LoadBalancer ``` MetalLB seleccionará automáticamente una IP libre de **cualquier** rango declarado en el pool. --- ## 2.4 Verificar los resultados Para comprobar que **MetalLB** asigna direcciones IP correctamente, realiza la siguiente prueba utilizando el manifiesto `test-lb.yaml` que ya está en el repositorio: ```bash kubectl apply -f test-lb.yaml ``` Supervisa la asignación de IP externa: ```bash kubectl -n lb-test get svc test-lb -w ``` Deberías ver en la columna `EXTERNAL-IP` una de las direcciones configuradas en tu `IPAddressPool`. Ejemplo de salida esperada: ``` NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE test-lb LoadBalancer 10.104.58.240 192.168.1.100 80:30248/TCP 9s ``` Cuando quieras limpiar la prueba: ```bash kubectl delete -f test-lb.yaml ``` Esto eliminará el Namespace `lb-test` y todos los recursos creados para la prueba. --- ## 📜 Notas importantes - Puedes declarar varios rangos en un solo `IPAddressPool`. - No necesitas anotaciones para indicar qué pool usar si especificas directamente una IP con `loadBalancerIP`. - Es buena práctica versionar todos los manifiestos en una carpeta `metallb/` dentro de tu repo Git. - El uso de múltiples pools por separado sigue siendo válido, pero es innecesario si no quieres asignar pools por nombre con anotaciones.