Migración en Vivo de VM: Guía Completa

Introducción

La migración en vivo es una de las características más poderosas de las plataformas modernas de virtualización, permitiendo que las máquinas virtuales se muevan entre hosts físicos con cero tiempo de inactividad. Esta capacidad es esencial para el equilibrio de carga, mantenimiento de hardware, recuperación ante desastres y optimización de la utilización de recursos en entornos de producción.

Esta guía completa explora la migración en vivo de KVM/QEMU usando libvirt, cubriendo todo desde la configuración básica hasta escenarios avanzados de migración. Ya sea que esté administrando un pequeño clúster u orquestando migraciones entre centros de datos, comprender los detalles técnicos, requisitos y mejores prácticas es crucial para una implementación exitosa.

La migración en vivo funciona transfiriendo la memoria, el estado de la CPU y el estado del dispositivo de una VM en ejecución desde un host a otro mientras la VM continúa ejecutándose. El proceso es transparente para las aplicaciones y los usuarios, con solo un breve impacto en el rendimiento durante la fase final de conmutación. Las implementaciones modernas pueden migrar VMs en segundos con un tiempo de inactividad imperceptible.

Al final de esta guía, dominará la configuración de migración en vivo, comprenderá diferentes tipos de migración, optimizará el rendimiento de la migración y solucionará problemas comunes que surgen en entornos de producción.

Comprensión de la Migración en Vivo

¿Qué es la Migración en Vivo?

La migración en vivo (también llamada migración en caliente) es el proceso de mover una máquina virtual en ejecución de un host físico a otro sin detener la VM ni interrumpir los servicios en ejecución. Todo el estado de la VM, incluido el contenido de la memoria, los registros de la CPU y los estados del dispositivo, se transfiere al host de destino.

Fases del Proceso de Migración

┌────────────────────────────────────────┐
│   Fase 1: Configuración Previa         │
│   - Verificar compatibilidad           │
│   - Verificar recursos                 │
│   - Establecer conexión                │
└──────────────┬─────────────────────────┘
               │
┌──────────────▼─────────────────────────┐
│   Fase 2: Pre-Copia Iterativa          │
│   - Copiar páginas de memoria          │
│   - Rastrear páginas sucias            │
│   - Re-copiar páginas modificadas      │
└──────────────┬─────────────────────────┘
               │
┌──────────────▼─────────────────────────┐
│   Fase 3: Detener y Copiar             │
│   - Pausar VM brevemente               │
│   - Transferir estado restante         │
│   - ~100-500ms tiempo de inactividad   │
└──────────────┬─────────────────────────┘
               │
┌──────────────▼─────────────────────────┐
│   Fase 4: Post-Migración               │
│   - Reanudar VM en destino             │
│   - Limpiar origen                     │
│   - Actualizar red/almacenamiento      │
└────────────────────────────────────────┘

Tipos de Migración

1. Migración en Vivo (Migración en Caliente)

  • La VM permanece en ejecución durante todo el proceso
  • La memoria y el estado se copian mientras la VM se ejecuta
  • Pausa breve durante la conmutación final
  • Cero tiempo de inactividad visible

2. Migración Fuera de Línea (Migración en Frío)

  • VM detenida antes de la migración
  • Transferencia más rápida (sin seguimiento de páginas sucias)
  • Tiempo de inactividad durante todo el proceso
  • Más simple, más confiable

3. Migración de Almacenamiento en Vivo

  • Mover imágenes de disco de VM mientras se ejecuta
  • Puede combinarse con migración en vivo
  • Útil para mantenimiento de almacenamiento

4. Migración Post-Copia

  • Iniciar VM en destino inmediatamente
  • Obtener páginas de memoria bajo demanda
  • Menor tiempo total de migración
  • Riesgo si falla la red

Prerrequisitos y Requisitos

Requisitos de Configuración del Host

Ambos hosts de origen y destino deben tener:

# 1. Misma arquitectura de CPU
lscpu | grep "Model name"
lscpu | grep "Architecture"

# 2. Características de CPU compatibles
virsh capabilities | grep -A 20 "<cpu>"

# 3. Misma versión de libvirt (o compatible)
virsh version

# 4. KVM/QEMU instalado
which qemu-system-x86_64
lsmod | grep kvm

# 5. Almacenamiento compartido o migración de almacenamiento configurada
# (para imágenes de disco)

# 6. Conectividad de red
ping destination-host

Requisitos de Red

# Red de baja latencia (preferiblemente dedicada)
ping -c 100 destination-host | tail -n 1
# RTT debe ser < 1ms para mejor rendimiento

# Alto ancho de banda (mínimo 1Gbps, recomendado 10Gbps)
iperf3 -s  # En destino
iperf3 -c destination-host -t 30  # En origen

# Abrir puertos requeridos
# libvirt por defecto: 16509 (TLS) o 16514 (TCP)
# qemu+ssh: 22 (SSH)

Requisitos de Almacenamiento

Opción 1: Almacenamiento Compartido (Recomendado)

# Almacenamiento compartido NFS
# Montar la misma compartición NFS en ambos hosts
mount -t nfs nfs-server:/exports/vms /var/lib/libvirt/images

# Verificar que ambos hosts vean el mismo almacenamiento
ls -la /var/lib/libvirt/images/

# Agregar a /etc/fstab para persistencia
echo "nfs-server:/exports/vms /var/lib/libvirt/images nfs defaults 0 0" >> /etc/fstab

Opción 2: Migración de Almacenamiento

# Copiar imágenes de disco durante la migración
# Requiere ancho de banda suficiente
# Toma más tiempo que la migración con almacenamiento compartido

Compatibilidad de CPU

# Verificar flags de CPU en ambos hosts
virsh capabilities | grep features

# Usar host-passthrough o host-model con cuidado
# Mejor: Usar modelo de CPU nombrado para compatibilidad

# Ver modelos de CPU disponibles
virsh domcapabilities | grep -A 50 cpu
qemu-system-x86_64 -cpu help

# Configurar VM con CPU compatible
virsh edit vm-name

<cpu mode='custom' match='exact'>
  <model>Broadwell</model>
</cpu>

# O usar host-model con verificación de características
<cpu mode='host-model'>
  <model fallback='forbid'/>
</cpu>

Configuración de Almacenamiento Compartido

Configuración de NFS

En el Servidor NFS:

# Instalar servidor NFS
apt install nfs-kernel-server  # Debian/Ubuntu
dnf install nfs-utils  # RHEL/CentOS

# Crear directorio de exportación
mkdir -p /exports/vms
chown -R qemu:qemu /exports/vms
chmod 755 /exports/vms

# Configurar exportaciones
cat >> /etc/exports << 'EOF'
/exports/vms 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)
EOF

# Aplicar cambios
exportfs -arv

# Iniciar NFS
systemctl enable nfs-server
systemctl start nfs-server

# Verificar exportaciones
showmount -e localhost

En los Hosts KVM (tanto origen como destino):

# Instalar cliente NFS
apt install nfs-common  # Debian/Ubuntu
dnf install nfs-utils  # RHEL/CentOS

# Crear punto de montaje
mkdir -p /var/lib/libvirt/images

# Montar compartición NFS
mount -t nfs nfs-server:/exports/vms /var/lib/libvirt/images

# Probar acceso de escritura
touch /var/lib/libvirt/images/test
rm /var/lib/libvirt/images/test

# Agregar a fstab
echo "nfs-server:/exports/vms /var/lib/libvirt/images nfs defaults 0 0" >> /etc/fstab

# Verificar montaje
df -h | grep vms

Configuración del Pool de Almacenamiento

# Crear pool de almacenamiento en almacenamiento compartido
cat > nfs-pool.xml << 'EOF'
<pool type='dir'>
  <name>nfs-pool</name>
  <target>
    <path>/var/lib/libvirt/images</path>
  </target>
</pool>
EOF

# Definir pool en ambos hosts
virsh pool-define nfs-pool.xml
virsh pool-start nfs-pool
virsh pool-autostart nfs-pool

# Verificar
virsh pool-list
virsh pool-info nfs-pool

Configuración de Hosts para Migración

Configuración de Red

Usando libvirtd TCP (Sin Cifrar - Solo Pruebas):

# Editar /etc/libvirt/libvirtd.conf en ambos hosts
sudo vim /etc/libvirt/libvirtd.conf

# Descomentar y modificar:
listen_tls = 0
listen_tcp = 1
tcp_port = "16509"
auth_tcp = "none"  # ¡Solo para pruebas!

# Editar /etc/default/libvirtd (Debian/Ubuntu)
sudo vim /etc/default/libvirtd
libvirtd_opts="--listen"

# O /etc/sysconfig/libvirtd (RHEL/CentOS)
LIBVIRTD_ARGS="--listen"

# Reiniciar libvirtd
sudo systemctl restart libvirtd

# Verificar que esté escuchando
ss -tulpn | grep 16509

Usando libvirtd TLS (Seguro - Producción):

# Generar certificados TLS (en autoridad de certificación)
mkdir -p /etc/pki/CA
cd /etc/pki/CA

# Crear CA
certtool --generate-privkey > cakey.pem
cat > ca.info << EOF
cn = CA
ca
cert_signing_key
EOF
certtool --generate-self-signed --load-privkey cakey.pem \
  --template ca.info --outfile cacert.pem

# Crear certificados de servidor para cada host
certtool --generate-privkey > serverkey.pem
cat > server.info << EOF
organization = MyOrg
cn = host1.example.com
tls_www_server
encryption_key
signing_key
EOF
certtool --generate-certificate --load-privkey serverkey.pem \
  --load-ca-certificate cacert.pem --load-ca-privkey cakey.pem \
  --template server.info --outfile servercert.pem

# Instalar certificados en ambos hosts
sudo mkdir -p /etc/pki/libvirt/private
sudo cp cacert.pem /etc/pki/CA/
sudo cp servercert.pem /etc/pki/libvirt/
sudo cp serverkey.pem /etc/pki/libvirt/private/

# Configurar libvirtd para TLS
sudo vim /etc/libvirt/libvirtd.conf
listen_tls = 1
listen_tcp = 0

# Reiniciar libvirtd
sudo systemctl restart libvirtd

Usando SSH (Más Simple - Recomendado):

# No se necesita configuración especial de libvirtd
# Solo configurar autenticación por clave SSH

# En el host de origen
ssh-keygen -t rsa -b 4096

# Copiar clave al destino
ssh-copy-id root@destination-host

# Probar conexión
ssh root@destination-host 'virsh version'

# ¡Este es el método recomendado!

Configuración del Firewall

# Permitir puertos de libvirt
# TCP: 16509 (no-TLS), 16514 (TLS)
# SSH: 22

# Debian/Ubuntu (UFW)
ufw allow 16509/tcp
ufw allow 16514/tcp
ufw allow 22/tcp

# RHEL/CentOS (firewalld)
firewall-cmd --permanent --add-port=16509/tcp
firewall-cmd --permanent --add-port=16514/tcp
firewall-cmd --permanent --add-service=ssh
firewall-cmd --reload

# iptables directamente
iptables -A INPUT -p tcp --dport 16509 -j ACCEPT
iptables -A INPUT -p tcp --dport 16514 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Realización de Migración en Vivo

Migración en Vivo Básica

Usando virsh (método SSH - recomendado):

# Sintaxis:
# virsh migrate [opciones] dominio desturi [migrateuri] [dname]

# Migración simple usando SSH
virsh migrate --live ubuntu-vm qemu+ssh://destination-host/system

# Con salida detallada
virsh migrate --live --verbose ubuntu-vm qemu+ssh://destination-host/system

# Migración persistente (mantener configuración)
virsh migrate --live --persistent ubuntu-vm qemu+ssh://destination-host/system

# Indefinir origen después de la migración
virsh migrate --live --persistent --undefinesource ubuntu-vm \
  qemu+ssh://destination-host/system

Usando conexión TCP:

# Migración TCP directa
virsh migrate --live ubuntu-vm qemu+tcp://destination-host/system

# Con puerto personalizado
virsh migrate --live ubuntu-vm qemu+tcp://destination-host:16509/system

Monitoreo del progreso de la migración:

# Monitorear en terminal separada
watch -n 1 'virsh domjobinfo ubuntu-vm'

# Muestra:
# - Tiempo transcurrido
# - Datos procesados
# - Datos restantes
# - Tasa de transferencia de memoria
# - Estado de migración

Migración Peer-to-Peer

# Migración P2P (iniciada por host de destino)
virsh migrate --live --p2p ubuntu-vm qemu+ssh://destination-host/system

# P2P con migración tunelizada (cifrada)
virsh migrate --live --p2p --tunnelled ubuntu-vm \
  qemu+ssh://destination-host/system

# Ventajas:
# - Topología de red más simple
# - Solo necesita conectividad origen->destino
# - Selección automática de URI de destino

Migración con Opciones Personalizadas

# Especificar URI de migración para transferencia de datos
virsh migrate --live --p2p --tunnelled \
  --migrateuri tcp://192.168.100.1:49152 \
  ubuntu-vm qemu+ssh://destination-host/system

# Establecer límite de ancho de banda (MB/s)
virsh migrate --live --verbose --bandwidth 100 \
  ubuntu-vm qemu+ssh://destination-host/system

# Suspender VM de destino después de la migración (para pruebas)
virsh migrate --live --suspend ubuntu-vm qemu+ssh://destination-host/system

# Cambiar nombre de VM en destino
virsh migrate --live ubuntu-vm qemu+ssh://destination-host/system \
  --dname ubuntu-vm-migrated

# Migración insegura (omitir verificaciones de seguridad - ¡usar con cuidado!)
virsh migrate --live --unsafe ubuntu-vm qemu+ssh://destination-host/system

Migración de Almacenamiento en Vivo

Migrar VM con almacenamiento no compartido:

# Copiar disco durante la migración
virsh migrate --live --copy-storage-all ubuntu-vm \
  qemu+ssh://destination-host/system

# Copiar solo cambios incrementales (si el disco existe parcialmente)
virsh migrate --live --copy-storage-inc ubuntu-vm \
  qemu+ssh://destination-host/system

# Especificar rutas de disco de destino
virsh migrate --live --copy-storage-all \
  --migrate-disks vda \
  ubuntu-vm qemu+ssh://destination-host/system

# ¡Esto es mucho más lento debido a la copia de disco!
# Monitorear con: virsh domjobinfo ubuntu-vm

Migración Fuera de Línea (En Frío)

# Apagar VM primero
virsh shutdown ubuntu-vm

# Esperar el apagado
while [ "$(virsh domstate ubuntu-vm)" != "shut off" ]; do
    sleep 1
done

# Migrar configuración y disco
virsh dumpxml ubuntu-vm > ubuntu-vm.xml
scp ubuntu-vm.xml root@destination-host:/tmp/
scp /var/lib/libvirt/images/ubuntu-vm.qcow2 \
    root@destination-host:/var/lib/libvirt/images/

# En el host de destino
virsh define /tmp/ubuntu-vm.xml
virsh start ubuntu-vm

# Eliminar del origen
virsh undefine ubuntu-vm

Escenarios Avanzados de Migración

Migración Comprimida

# Usar compresión para reducir ancho de banda (mayor uso de CPU)
virsh migrate --live --compressed ubuntu-vm \
  qemu+ssh://destination-host/system

# Ajustar nivel de compresión e hilos
virsh migrate --live --compressed \
  --comp-methods mt \
  --comp-mt-level 9 \
  --comp-mt-threads 4 \
  ubuntu-vm qemu+ssh://destination-host/system

Migración Auto-Converge

# Acelerar automáticamente VM si la migración no converge
virsh migrate --live --auto-converge ubuntu-vm \
  qemu+ssh://destination-host/system

# Establecer aceleración inicial e incremental
virsh migrate --live --auto-converge \
  --auto-converge-initial 20 \
  --auto-converge-increment 10 \
  ubuntu-vm qemu+ssh://destination-host/system

# Ayuda con cargas de trabajo intensivas en memoria

Migración Post-Copia

# Iniciar VM en destino antes de la transferencia completa de memoria
virsh migrate --live --postcopy ubuntu-vm \
  qemu+ssh://destination-host/system

# Cambiar a modo post-copia durante la migración
virsh migrate-setmaxdowntime ubuntu-vm 1000
virsh migrate-postcopy ubuntu-vm

# Ventajas:
# - Convergencia garantizada
# - Menor tiempo total de migración
# - Fase de pre-migración más corta

# Desventajas:
# - La falla de red puede perder VM
# - Posibles problemas de rendimiento hasta la transferencia completa

Migración con Configuración Persistente

# Persistir VM en destino, eliminar del origen
virsh migrate --live --persistent --undefinesource ubuntu-vm \
  qemu+ssh://destination-host/system

# Mantener VM definida en ambos hosts (no exclusivo)
virsh migrate --live --persistent ubuntu-vm \
  qemu+ssh://destination-host/system

# Verificar en destino
ssh root@destination-host 'virsh list --all'

Migración de Múltiples VMs

#!/bin/bash
# Migrar múltiples VMs secuencialmente

VMS=("web1" "web2" "web3")
DEST="qemu+ssh://destination-host/system"

for vm in "${VMS[@]}"; do
    echo "Migrando $vm..."
    virsh migrate --live --verbose --persistent --undefinesource \
        "$vm" "$DEST"

    if [ $? -eq 0 ]; then
        echo "$vm migrada exitosamente"
    else
        echo "ERROR: Fallo al migrar $vm"
        exit 1
    fi
done

echo "Todas las VMs migradas exitosamente"

Migración Paralela (Múltiples VMs)

#!/bin/bash
# Migrar VMs en paralelo (¡usar con cuidado!)

VMS=("web1" "web2" "web3")
DEST="qemu+ssh://destination-host/system"

for vm in "${VMS[@]}"; do
    (
        virsh migrate --live --verbose "$vm" "$DEST" &
    ) &
done

# Esperar a que todas las migraciones se completen
wait

echo "Todas las migraciones iniciadas"

Optimización del Rendimiento

Gestión de Ancho de Banda

# Establecer límite de ancho de banda de migración (MB/s)
virsh migrate-setspeed ubuntu-vm 100

# Verificar límite de ancho de banda actual
virsh migrate-getspeed ubuntu-vm

# Establecer durante la migración
virsh migrate --live --bandwidth 200 ubuntu-vm \
  qemu+ssh://destination-host/system

# Ajuste dinámico durante la migración
virsh migrate-setspeed ubuntu-vm 150

Gestión de Tiempo de Inactividad

# Establecer tiempo máximo de inactividad tolerable (milisegundos)
virsh migrate-setmaxdowntime ubuntu-vm 500

# El valor predeterminado suele ser 300ms
# Los valores más bajos pueden causar que falle la migración
# Los valores más altos reducen el tiempo total de migración

# Verificar si se puede cumplir el umbral de tiempo de inactividad
virsh domjobinfo ubuntu-vm | grep downtime

Ajuste de Red

# Usar red de migración dedicada
virsh migrate --live --migrateuri tcp://10.0.1.1:49152 \
  ubuntu-vm qemu+ssh://destination-host/system

# Configurar virtio-net multi-cola para mejor rendimiento
virsh edit ubuntu-vm

<interface type='network'>
  <source network='default'/>
  <model type='virtio'/>
  <driver name='vhost' queues='4'/>
</interface>

# Habilitar MTU grande (tramas jumbo) en red de migración
ip link set dev eth1 mtu 9000

Optimización de Memoria

# Habilitar globo de memoria para mejor migración
virsh edit ubuntu-vm

<memballoon model='virtio'>
  <stats period='10'/>
</memballoon>

# Reducir memoria de VM antes de la migración
virsh setmem ubuntu-vm 2G

# Habilitar páginas enormes para migración más rápida
virsh edit ubuntu-vm

<memoryBacking>
  <hugepages/>
</memoryBacking>

# Verificar páginas enormes en el host
cat /proc/meminfo | grep Huge

Configuración de CPU

# Usar fijación de CPU para rendimiento consistente
virsh vcpupin ubuntu-vm 0 0
virsh vcpupin ubuntu-vm 1 1

# Asegurar modelo de CPU compatible
virsh edit ubuntu-vm

<cpu mode='custom' match='exact'>
  <model>Broadwell</model>
  <feature policy='require' name='pdpe1gb'/>
</cpu>

# Verificar compatibilidad de CPU
virsh cpu-compare cpu.xml

Monitoreo y Solución de Problemas

Monitoreo del Progreso de Migración

# Estadísticas de migración en tiempo real
virsh domjobinfo ubuntu-vm

# La salida incluye:
# Job type:         Unbounded
# Time elapsed:     42123 ms
# Data processed:   2.5 GiB
# Data remaining:   512 MiB
# Memory processed: 2.3 GiB
# Memory remaining: 256 MiB
# Memory bandwidth: 128 MiB/s

# Monitoreo continuo
watch -n 1 'virsh domjobinfo ubuntu-vm'

# Script para monitoreo detallado
#!/bin/bash
while true; do
    clear
    virsh domjobinfo ubuntu-vm
    sleep 1
done

Registros de Migración

# Verificar registros de libvirt
tail -f /var/log/libvirt/libvirtd.log

# Registros de QEMU para VM específica
tail -f /var/log/libvirt/qemu/ubuntu-vm.log

# Registros del sistema
journalctl -u libvirtd -f

# Filtrar eventos de migración
journalctl -u libvirtd | grep -i migrate

Problemas Comunes y Soluciones

Problema: La migración se detiene o nunca se completa

# Verificar si la VM tiene alta rotación de memoria
virsh domjobinfo ubuntu-vm | grep "Memory bandwidth"

# Soluciones:
# 1. Habilitar auto-converge
virsh migrate --live --auto-converge ubuntu-vm qemu+ssh://dest/system

# 2. Aumentar ancho de banda
virsh migrate-setspeed ubuntu-vm 500

# 3. Usar compresión
virsh migrate --live --compressed ubuntu-vm qemu+ssh://dest/system

# 4. Cambiar a post-copia
virsh migrate-postcopy ubuntu-vm

# 5. Reducir carga de trabajo de VM temporalmente

Problema: Error de compatibilidad de CPU

# Error: "migration of domain failed: Unsafe migration..."

# Verificar compatibilidad de CPU
virsh capabilities | grep features

# Solución: Usar modo de CPU compatible
virsh edit ubuntu-vm

# Cambiar de:
<cpu mode='host-passthrough'/>

# A:
<cpu mode='host-model'>
  <model fallback='allow'/>
</cpu>

# O usar modelo específico:
<cpu mode='custom' match='exact'>
  <model>Westmere</model>
</cpu>

# Forzar migración insegura (solo pruebas)
virsh migrate --live --unsafe ubuntu-vm qemu+ssh://dest/system

Problema: Red inaccesible después de la migración

# Verificar que la configuración de red coincida
virsh net-list --all  # En ambos hosts

# Verificar configuración de puente
brctl show  # En ambos hosts

# Verificar interfaz de red de VM
virsh domiflist ubuntu-vm

# Soluciones:
# 1. Asegurar mismos nombres de red en ambos hosts
# 2. Usar modo puente para consistencia
# 3. Configurar enrutamiento adecuado entre hosts

Problema: Almacenamiento no accesible

# Verificar almacenamiento compartido montado en ambos hosts
df -h | grep libvirt

# Verificar conectividad NFS
showmount -e nfs-server

# Verificar permisos de archivo
ls -la /var/lib/libvirt/images/

# Soluciones:
# 1. Montar almacenamiento compartido en destino
# 2. Usar --copy-storage-all si no hay almacenamiento compartido
# 3. Verificar conectividad NFS/almacenamiento

Problema: Permiso denegado

# Verificar permisos de libvirt
ls -la /var/run/libvirt/

# Verificar membresía de grupo
groups $USER

# Verificar SELinux/AppArmor
getenforce  # SELinux
aa-status   # AppArmor

# Soluciones:
# 1. Agregar usuario al grupo libvirt
usermod -aG libvirt $USER

# 2. Configurar SELinux
setsebool -P virt_use_nfs 1

# 3. Usar root para pruebas

Problema: Rendimiento de migración lento

# Verificar ancho de banda de red
iperf3 -c destination-host

# Verificar uso de CPU
top
htop

# Monitorear E/S de disco
iotop

# Soluciones:
# 1. Aumentar ancho de banda de migración
virsh migrate-setspeed ubuntu-vm 1000

# 2. Usar compresión si CPU disponible
virsh migrate --live --compressed ubuntu-vm qemu+ssh://dest/system

# 3. Usar red de migración dedicada con tramas jumbo
# 4. Reducir memoria de VM o pausar carga de trabajo
# 5. Habilitar auto-converge

Scripts de Migración y Automatización

Script de Verificación Pre-Migración

#!/bin/bash
# pre-migration-check.sh

VM=$1
DEST_HOST=$2

if [ -z "$VM" ] || [ -z "$DEST_HOST" ]; then
    echo "Uso: $0 <nombre-vm> <host-destino>"
    exit 1
fi

echo "Verificaciones pre-migración para $VM a $DEST_HOST"
echo "============================================"

# Verificar que VM exista y esté en ejecución
if ! virsh domstate "$VM" | grep -q "running"; then
    echo "ERROR: VM $VM no está en ejecución"
    exit 1
fi
echo "✓ VM está en ejecución"

# Verificar host de destino alcanzable
if ! ping -c 1 "$DEST_HOST" &>/dev/null; then
    echo "ERROR: No se puede alcanzar host de destino"
    exit 1
fi
echo "✓ Host de destino alcanzable"

# Verificar conectividad SSH
if ! ssh root@"$DEST_HOST" 'exit' &>/dev/null; then
    echo "ERROR: No se puede conectar por SSH al destino"
    exit 1
fi
echo "✓ Conectividad SSH OK"

# Verificar que destino tenga KVM
if ! ssh root@"$DEST_HOST" 'virsh version' &>/dev/null; then
    echo "ERROR: KVM no disponible en destino"
    exit 1
fi
echo "✓ KVM disponible en destino"

# Verificar compatibilidad de CPU
echo "✓ Compatibilidad de CPU (verificación manual recomendada)"

# Verificar disponibilidad de memoria
VM_MEM=$(virsh dominfo "$VM" | grep "Max memory" | awk '{print $3}')
DEST_FREE=$(ssh root@"$DEST_HOST" "free | grep Mem | awk '{print \$4}'")

if [ "$DEST_FREE" -lt "$VM_MEM" ]; then
    echo "ADVERTENCIA: Memoria baja en destino"
fi
echo "✓ Verificación de memoria completa"

# Verificar almacenamiento compartido
VM_DISK=$(virsh domblklist "$VM" | awk 'NR>2 {print $2}' | head -n 1)
if ! ssh root@"$DEST_HOST" "ls $VM_DISK" &>/dev/null; then
    echo "ERROR: Disco no accesible en destino"
    echo "  Considerar usar --copy-storage-all"
    exit 1
fi
echo "✓ Almacenamiento compartido accesible"

echo ""
echo "¡Todas las verificaciones pasadas! Listo para migrar."
echo ""
echo "Comando sugerido:"
echo "virsh migrate --live --verbose --persistent --undefinesource \\"
echo "  $VM qemu+ssh://$DEST_HOST/system"

Script de Migración Automatizada

#!/bin/bash
# migrate-vm.sh

VM=$1
DEST=$2
BANDWIDTH=500  # MB/s

if [ -z "$VM" ] || [ -z "$DEST" ]; then
    echo "Uso: $0 <nombre-vm> <host-destino>"
    exit 1
fi

DEST_URI="qemu+ssh://${DEST}/system"

echo "Iniciando migración de $VM a $DEST"
echo "===================================="

# Verificaciones pre-migración
echo "Ejecutando verificaciones pre-migración..."
if ! bash pre-migration-check.sh "$VM" "$DEST"; then
    echo "¡Verificaciones pre-migración fallidas!"
    exit 1
fi

# Crear instantánea antes de la migración (seguridad)
echo "Creando instantánea de seguridad..."
SNAPSHOT="pre-migrate-$(date +%Y%m%d-%H%M%S)"
virsh snapshot-create-as "$VM" "$SNAPSHOT" "Instantánea pre-migración"

# Realizar migración
echo "Iniciando migración..."
virsh migrate --live --verbose --persistent --undefinesource \
    --bandwidth "$BANDWIDTH" \
    --auto-converge \
    "$VM" "$DEST_URI" 2>&1 | tee migration-${VM}.log

if [ ${PIPESTATUS[0]} -eq 0 ]; then
    echo "¡Migración completada exitosamente!"

    # Verificar que VM esté en ejecución en destino
    if ssh root@"$DEST" "virsh domstate $VM" | grep -q "running"; then
        echo "VM verificada en ejecución en destino"
        # Eliminar instantánea de seguridad
        virsh snapshot-delete "$VM" "$SNAPSHOT" 2>/dev/null || true
    else
        echo "ADVERTENCIA: VM puede no estar en ejecución en destino"
    fi
else
    echo "¡Migración fallida!"
    echo "Verificar migration-${VM}.log para detalles"
    exit 1
fi

Script de Migración de Balanceo de Carga

#!/bin/bash
# load-balance.sh
# Migrar VMs para balancear carga entre hosts

HOSTS=("host1" "host2" "host3")
THRESHOLD=70  # Umbral de uso de CPU

for host in "${HOSTS[@]}"; do
    CPU_USAGE=$(ssh root@"$host" "top -bn1 | grep 'Cpu(s)' | awk '{print \$2}' | cut -d'%' -f1")

    if (( $(echo "$CPU_USAGE > $THRESHOLD" | bc -l) )); then
        echo "Host $host sobrecargado (${CPU_USAGE}%)"

        # Encontrar host menos cargado
        MIN_HOST=""
        MIN_LOAD=100

        for target in "${HOSTS[@]}"; do
            if [ "$target" != "$host" ]; then
                LOAD=$(ssh root@"$target" "top -bn1 | grep 'Cpu(s)' | awk '{print \$2}' | cut -d'%' -f1")
                if (( $(echo "$LOAD < $MIN_LOAD" | bc -l) )); then
                    MIN_LOAD=$LOAD
                    MIN_HOST=$target
                fi
            fi
        done

        # Migrar VM menos crítica
        VM=$(ssh root@"$host" "virsh list --name | head -n 1")
        echo "Migrando $VM de $host a $MIN_HOST"
        ssh root@"$host" "virsh migrate --live $VM qemu+ssh://${MIN_HOST}/system"
    fi
done

Mejores Prácticas

Planificación y Preparación

  1. Siempre probar migraciones en dev/staging primero
  2. Verificar compatibilidad de CPU antes de migraciones de producción
  3. Usar almacenamiento compartido cuando sea posible
  4. Configurar red de migración dedicada para producción
  5. Documentar procedimientos de migración y runbooks

Consideraciones de Rendimiento

# 1. Usar compresión para migraciones WAN
virsh migrate --live --compressed

# 2. Establecer límites de ancho de banda apropiados
virsh migrate --bandwidth 500

# 3. Habilitar auto-converge para VMs intensivas en memoria
virsh migrate --auto-converge

# 4. Usar post-copia para convergencia garantizada
virsh migrate --postcopy

# 5. Programar migraciones durante períodos de bajo uso

Mejores Prácticas de Seguridad

# 1. Siempre usar SSH o TLS para producción
virsh migrate --live ubuntu-vm qemu+ssh://dest/system

# 2. Nunca usar auth_tcp = "none" en producción
# 3. Implementar gestión adecuada de certificados para TLS
# 4. Usar red de migración dedicada y aislada
# 5. Habilitar reglas de firewall para puertos de migración solo entre hosts confiables

Monitoreo y Validación

# 1. Siempre monitorear migraciones
watch -n 1 'virsh domjobinfo vm-name'

# 2. Validar VM después de la migración
ssh dest-host 'virsh domstate vm-name'
ssh dest-host 'virsh dominfo vm-name'

# 3. Probar conectividad de aplicación
curl http://vm-ip/health

# 4. Verificar registros para errores
journalctl -u libvirtd | grep -i error

# 5. Mantener registros detallados de migración

Conclusión

La migración en vivo es una capacidad crítica para la infraestructura virtualizada moderna, permitiendo mantenimiento sin tiempo de inactividad, optimización dinámica de recursos y estrategias mejoradas de recuperación ante desastres. Dominar la migración en vivo de KVM/QEMU con libvirt proporciona la base para construir plataformas de virtualización altamente disponibles y flexibles.

Conclusiones clave:

  • El almacenamiento compartido simplifica significativamente la migración en vivo
  • La migración basada en SSH es el método más simple y seguro
  • La compatibilidad de CPU es crucial para migraciones exitosas
  • Auto-converge y compresión ayudan con cargas de trabajo desafiantes
  • Siempre monitorear el progreso de la migración y validar resultados
  • La migración post-copia garantiza convergencia pero tiene riesgos

A medida que gane experiencia con la migración en vivo, explore escenarios avanzados como migraciones entre centros de datos, estrategias de migración de almacenamiento e integración con plataformas de orquestación como OpenStack u oVirt. La flexibilidad y el poder de la migración en vivo de KVM la convierten en una tecnología fundamental para infraestructura en la nube e implementaciones de virtualización empresarial.

Recuerde que las migraciones exitosas requieren planificación cuidadosa, pruebas exhaustivas y monitoreo adecuado. Con el conocimiento y las técnicas cubiertas en esta guía, está equipado para implementar flujos de trabajo de migración en vivo confiables y eficientes en entornos de producción.