Introducción

Tenés un cluster de Kubernetes con KubeVirt corriendo VMs en producción. Las workloads andan bien, el equipo gana confianza, y surge la pregunta inevitable: «¿Podemos migrar una VM en vivo a otro cluster?». Los casos de uso son claros: recovery ante desastres, actualizaciones de clusters, balanceo de capacidad. KubeVirt desde la versión 1.6 (julio 2025) soporta decentralized live migration, que en teoría debería resolverlo. Pero el equipo de red respondió con un «no tan rápido»: la VM necesita mantener su IP y MAC en el cluster destino, lo que implica estirar un dominio de Layer 2 entre sites. En infraestructura tradicional, eso significa nuevos VLANs, cambios en switches, posiblemente hardware adicional, una ventana de cambio y un ticket que puede tardar semanas.

Qué ocurrió

El problema no está en la tecnología de migración de KubeVirt, sino en los requisitos de red que Kubernetes no resuelve por defecto. Para migrar una VM entre clusters sin cortar conexiones, se necesitan dos cosas:

  • Un dominio L2 estirado: La VM debe aterrizar en el cluster destino con la misma IP y MAC, en el mismo dominio de broadcast. Sin esto, cada migración implica reasignar IPs, actualizar DNS y romper conexiones existentes. Aplicaciones stateful como clusters de PostgreSQL con replicación síncrona o colas de mensajes con sesiones TCP persistentes no toleran cambios de IP sin intervención manual.
  • Una ruta de migración dedicada: La migración transfiere gigabytes de estado de memoria en tiempo real. Si este tráfico compite con el tráfico de aplicaciones, genera congestión, latencia impredecible y dificulta el monitoreo independiente de cada tipo de tráfico.
  • En plataformas de virtualización tradicionales (vmware NSX, OpenStack + Neutron), estos problemas se resuelven con VLANs dedicadas para migración y constructs de switches virtuales propietarios. Pero estas soluciones están acopladas al hardware, son específicas de vendor y a menudo requieren licencias por socket.

    Impacto para DevOps / Infraestructura / Cloud / Seguridad

    El principal impacto es operacional: la imposibilidad de migrar VMs entre clusters limita la flexibilidad de la infraestructura. Sin movilidad cross-cluster:

    • Recovery ante desastres requiere recrear VMs en el cluster de backup con nuevas IPs, lo que alarga el RTO y puede requerir cambios manuales en aplicaciones dependientes.
    • Actualizaciones de clusters obligan a apagar VMs o a mantener clusters viejos hasta que las aplicaciones puedan redirigirse, aumentando costos y riesgos de seguridad (ej.: clusters sin parches).
    • Balanceo de carga no puede redistribuir VMs según la capacidad disponible, llevando a sobreutilización en algunos clusters y subutilización en otros.

    Para el equipo de seguridad, esto también significa menor agilidad para aislar workloads problemáticas o moverlas a clusters con políticas de seguridad más estrictas. Además, si se implementan soluciones ad-hoc (como tunnels VPN punto a punto para migración), se introduce complejidad y riesgos de configuración inconsistente.

    En entornos cloud (ej.: EKS), el problema persiste: aunque la red subyacente sea manejada por AWS, los clusters de Kubernetes son dominios de red independientes y no comparten un dominio L2 por defecto.

    Detalles técnicos

    La solución open source para este problema combina EVPN/VXLAN como overlay de red y OpenPERouter para gestionarlo de manera nativa en Kubernetes.

    Cómo funciona EVPN/VXLAN

    EVPN (Ethernet VPN) es un estándar IETF (RFC 7432) que permite crear overlays de Layer 2 y Layer 3 sobre redes IP existentes. Usando VXLAN como encapsulamiento (puerto UDP 8472), los endpoints (VTEPs) establecen tunnels entre sí y distribuen información de MAC e IP via BGP. Esto permite:

    • Estirar un dominio L2 ( broadcast domain) entre sites sin depender de VLANs físicas.
    • Aislar tráfico con VRFs (Virtual Routing and Forwarding).
    • Crear overlays sobre cualquier infraestructura IP subyacente (puede atravesar routers, firewalls, incluso Internet).

    OpenPERouter: EVPN como CRD

    OpenPERouter es un proyecto open source que implementa EVPN/VXLAN para Kubernetes mediante Custom Resource Definitions (CRDs). Tres recursos clave:

  • Underlay: Define el peering BGP entre cada cluster de Kubernetes y su switch top-of-rack (ToR). Ejemplo:
  • apiVersion: metal3.io/v1alpha1
    kind: Underlay
    metadata:
    name: underlay-main
    spec:
    type: BGP
    bgp:
    myASN: 65001
    peerASN: 64500
    peerAddress: 192.168.1.1
    peerInterface: eth0
    ipPool: 192.168.2.0/24

  • L2VNI: Crea un overlay de Layer 2 (VXLAN) para un subnet. Ejemplo para la red de aplicaciones:
  • apiVersion: metal3.io/v1alpha1
    kind: L2VNI
    metadata:
    name: app-network
    spec:
    vni: 110
    vrf: red
    network: 192.170.1.0/24

  • L3VNI: Habilita routing entre subnets y conexión a redes externas.
  • Para la migración, se define un segundo L2VNI dedicado:

    apiVersion: metal3.io/v1alpha1
    kind: L2VNI
    metadata:
    name: migration-network
    spec:
    vni: 666
    vrf: rouge
    network: 192.170.2.0/24

    Este overlay usa el mismo patrón que la red de aplicaciones, pero con un VNI distinto (666), lo que aisla el tráfico de migración del tráfico de applications. El overlay se construye sobre la conectividad IP existente entre sites; los endpoints VXLAN no necesitan estar en el mismo segment de red.

    Migración de VMs

    Con la infraestructura de red en su lugar, la migración de una VM entre clusters requiere tres recursos:

  • VM de destino: Provisionada en el cluster B con la misma MAC e IP que la VM origen, y runStrategy: WaitAsReceiver:
  • apiVersion: kubevirt.io/v1
    kind: VirtualMachine
    metadata:
    name: my-vm
    spec:
    runStrategy: WaitAsReceiver
    template:
    spec:
    networkInterfaces:
    – name: default
    multus:
    networkName: app-network

  • Receiver: Declara la readiness para recibir la migración en el cluster B:
  • apiVersion: kubevirt.io/v1
    kind: VirtualMachineInstanceMigration
    metadata:
    name: migration-my-vm-to-b
    spec:
    vmName: my-vm
    targetNode: node-b-1
    liveMigrate: true

  • Sender: Inicia la migración desde el cluster A, apuntando al receiver:
  • apiVersion: kubevirt.io/v1
    kind: VirtualMachineInstanceMigration
    metadata:
    name: migration-my-vm-to-b
    spec:
    vmName: my-vm
    targetNode: node-b-1
    liveMigrate: true
    nodeSelector: {}
    tolerance:
    – key: node-role.kubernetes.io/master
    operator: Exists
    effect: NoSchedule

    El tráfico de migración fluye sobre el VNI 666, aislado del VNI 110 de aplicaciones. EVPN actualiza las advertencias MAC/IP en el fabric, y el tráfico hacia la VM comienza a llegar al nuevo cluster sin cambios en DNS o IPs.

    IPAM cross-cluster

    Para evitar conflictos de IPs entre clusters, se necesita una estrategia de IPAM que partione el subnet. El ejemplo usa Whereabouts (un CNI para asignación de IPs) con rangos excluyentes:

    • Cluster A: 192.170.1.0/25 (192.170.1.0-127)
    • Cluster B: 192.170.1.128/25 (192.170.1.128-255)

    Configuración en el NetworkAttachmentDefinition:

    apiVersion: «k8s.cni.cncf.io/v1»
    kind: NetworkAttachmentDefinition
    metadata:
    name: app-network
    spec:
    config: |-
    {
    «cniVersion»: «0.3.1»,
    «type»: «whereabouts»,
    «ipam»: {
    «type»: «host-local»,
    «range»: «192.170.1.0/25»,
    «excludeRanges»: [
    {«start»: «192.170.1.128», «end»: «192.170.1.255»}
    ]
    }
    }

    Qué deberían hacer los administradores y equipos técnicos

  • Evaluar la conectividad entre clusters: Asegurarse de que haya reachability IP entre los nodos de todos los clusters (para el overlay VXLAN). Si los clusters están en diferentes redes, puede ser necesario configurar routing o VPC peering (en cloud).
  • Desplegar OpenPERouter:
  • kubectl apply -f https://github.com/metal3-io/OpenPERouter/releases/download/v0.6.0/manifests.yaml

    Verificar que el daemon openperouter se ejecute en los nodos con la interfaz de red correcta (ej.: eth0).

  • Configurar el underlay:
  • – Definir un Underlay CR por cluster, con el ASN y peer BGP correspondientes al switch ToR.

    – Si los switches ToR no soporten BGP, usar un BGP speaker en cada nodo (ej.: FRR) y configurar peering entre nodos.

  • Crear los overlays:
  • – Un L2VNI para la red de aplicaciones (mismo VNI y VRF en todos los clusters).

    – Un L2VNI separado para migración (VNI y VRF distintos).

  • Configurar IPAM cross-cluster:
  • – Implementar Whereabouts o otro CNI con soporte para rangos excluyentes.

    – Asegurarse de que cada cluster tenga un rango único dentro del subnet estirado.

  • Probar la migración:
  • – Crear una VM en el cluster A.

    – Definir los recursos VirtualMachine (con WaitAsReceiver), VirtualMachineInstanceMigration (receiver) en el cluster B, y VirtualMachineInstanceMigration (sender) en el cluster A.

    – Verificar que la VM migre sin perder conectividad:

    kubectl get vmi -w # Monitorear el estado de la VM
    kubectl get virtualmachineinstancemigration -o wide # Ver progreso de la migración

  • Monitorear el overlay:
  • – Verificar el estado de los peers BGP:

    kubectl exec -n openperouter openperouter-cpxd — vrf show
    kubectl exec -n openperouter openperouter-cpxd — bgp neighbor

    – Monitorear tráfico VXLAN con herramientas como tcpdump (filtrando por puerto UDP 8472).

    Conclusión

    La migración cross-cluster de VMs en KubeVirt no es un problema técnico de la herramienta, sino un desafío de red. EVPN/VXLAN proporcionan el overlay necesario para estirar dominios L2 y aislar el tráfico de migración, mientras que OpenPERouter los expone como recursos nativos de Kubernetes. El cambio es operacional: la configuración de la red pasa de ser un ticket al equipo de networking (con ventanas de cambio y dependencias de hardware) a ser un CRD aplicado por el equipo de plataforma, versionado en Git y revisable via PR.

    Esta aproximación no solo habilita la movilidad de VMs, sino que también sienta las bases para otros casos de uso multi-cluster, como estirar redes de Pods entre clusters o implementar servicios distribuidos. KubeVirt (proyecto incubado en CNCF desde abril 2022) y OpenPERouter son open source, sin costos de licencia por socket, y funcionan sobre cualquier infraestructura IP.

    Fuentes

    • https://thenewstack.io/kubevirt-evpn-vm-migration/
    • https://kubernetes.io/blog/
    • https://labs.ripe.net/

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *