Files
kubernetes/redes_internet.md
2025-08-11 00:49:24 +02:00

7.9 KiB

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:

kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset.yml

Verifica:

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í.

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:

# 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:

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:

kubectl apply -f multus/nad-br-servicios.yaml

1.5 Despliega pods multi-homed de prueba

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

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

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 Instalar MetalLB

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 Habilitar strictARP en kube-proxy (obligatorio en L2)

Para evitar problemas de ARP flapping y garantizar que solo el nodo que anuncia la IP responda a las peticiones ARP, es necesario activar strictARP en kube-proxy.

kubectl -n kube-system edit configmap kube-proxy

En la sección config.conf busca la línea strictARP y cámbiala a:

strictARP: true

Guarda y reinicia kube-proxy:

kubectl -n kube-system rollout restart daemonset kube-proxy

2.3 Eliminar la etiqueta que excluye los nodos de anunciar LoadBalancer

Por defecto, Kubernetes etiqueta los nodos control-plane con:

node.kubernetes.io/exclude-from-external-load-balancers

Esto impide que MetalLB anuncie servicios desde esos nodos.

Para eliminarla de todos los nodos:

kubectl label node --all node.kubernetes.io/exclude-from-external-load-balancers-

Verifica que ya no aparece:

kubectl get nodes -L node.kubernetes.io/exclude-from-external-load-balancers

2.4 Definir 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.

Ejemplo: metallb/ipaddresspool.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

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: advert-general
  namespace: metallb-system
spec: {}

Kustomization:

resources:
  - ipaddresspool.yaml
  - l2advertisement.yaml

Para aplicar:

kubectl apply -k metallb/

2.5 Asignar una IP concreta al Service (loadBalancerIP)

Puedes indicar directamente la IP deseada usando el campo loadBalancerIP.

Ejemplo 1: Asignación explícita con loadBalancerIP

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

Ejemplo 2: Sin IP explícita (MetalLB elige una disponible)

apiVersion: v1
kind: Service
metadata:
  name: nginx-lab
spec:
  selector:
    app: nginx
  ports:
    - port: 8080
      targetPort: 80
  type: LoadBalancer

2.6 Verificar el funcionamiento

Prueba con el manifiesto test-lb.yaml:

kubectl apply -f test-lb.yaml
kubectl -n lb-test get svc test-lb -w

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 termines:

kubectl delete -f test-lb.yaml

📜 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.