Virtualización en Linux: KVM, QEMU y libvirt
Domina la virtualización en Linux con KVM, QEMU y libvirt: creación de VM con virt-install, virsh, discos qcow2, redes bridge y cloud-init.
InSkillCoach
Virtualización en Linux: KVM, QEMU y libvirt
KVM es el hipervisor integrado en el kernel de Linux: es el que hace funcionar gran parte de la nube mundial, desde OpenStack hasta numerosas ofertas de alojamiento. Combinado con QEMU para la emulación del hardware y con libvirt para la gestión, convierte cualquier máquina Linux en una plataforma de virtualización completa, sin licencias ni productos de terceros. En esta guía partimos de la comprobación del soporte de hardware para llegar a máquinas virtuales aprovisionadas automáticamente con cloud-init, pasando por virt-install, virsh, los discos qcow2 y la configuración de red.
Aclaremos primero el papel de cada componente: KVM es el módulo del kernel que da acceso a las instrucciones de virtualización del procesador; QEMU emula el hardware (discos, tarjetas de red, BIOS/UEFI) y se apoya en KVM para ejecutar el código invitado a una velocidad casi nativa; libvirt es la capa de gestión (API, demonio, CLI virsh) que unifica el control del conjunto.
1. Comprobar el soporte de hardware
La virtualización por hardware requiere las extensiones Intel VT-x o AMD-V, activadas en la BIOS/UEFI.
# Contar los indicadores de virtualización en /proc/cpuinfo
# vmx = Intel VT-x, svm = AMD-V ; un resultado > 0 es buena señal
grep -Ec '(vmx|svm)' /proc/cpuinfo
# En Ubuntu/Debian, la herramienta específica da un veredicto claro
sudo apt install cpu-checker
kvm-ok
# Resultado esperado:
# INFO: /dev/kvm exists
# KVM acceleration can be used
# Comprobar que los módulos del kernel están cargados
lsmod | grep kvm
# kvm_intel (o kvm_amd) y kvm deben aparecer
# Comprobar el dispositivo KVM
ls -l /dev/kvm
Si kvm-ok indica que la virtualización está desactivada, reinicia y activa VT-x/AMD-V en el firmware. Para la virtualización anidada (una VM dentro de una VM, útil para laboratorios):
# Comprobar el soporte de virtualización anidada (Intel)
cat /sys/module/kvm_intel/parameters/nested
# Y o 1 = activado
2. Instalar KVM, QEMU y libvirt
Debian/Ubuntu
# Instalar el hipervisor, la capa de gestión y las herramientas
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients \
virtinst bridge-utils qemu-utils
# Iniciar y habilitar el demonio libvirt
sudo systemctl enable --now libvirtd
# Añadir tu usuario a los grupos necesarios
# (hay que cerrar sesión y volver a iniciarla para que surta efecto)
sudo usermod -aG libvirt,kvm "$USER"
Rocky Linux/Fedora
# El grupo de paquetes virtualization instala todo lo necesario
sudo dnf install @virtualization
sudo systemctl enable --now libvirtd
sudo usermod -aG libvirt "$USER"
Validar la instalación
# Diagnóstico completo del host de virtualización
virt-host-validate
# Todas las líneas QEMU deben estar en PASS (los WARN de IOMMU son
# aceptables si no haces passthrough PCI)
# Comprobar la conexión con libvirt
virsh -c qemu:///system list --all
Coexisten dos URI de conexión: qemu:///system (VM gestionadas por el demonio del sistema, recomendado para servidores) y qemu:///session (VM del usuario, sin privilegios). Para evitar cualquier ambigüedad:
# Forzar a virsh a usar la conexión del sistema por defecto
echo 'export LIBVIRT_DEFAULT_URI=qemu:///system' >> ~/.bashrc
3. Crear una VM con virt-install
Preparar la imagen y el almacenamiento
# El directorio estándar de las imágenes de libvirt
ls /var/lib/libvirt/images/
# Descargar una ISO de Debian (ejemplo)
sudo wget -P /var/lib/libvirt/images/ \
https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-13.1.0-amd64-netinst.iso
Instalación interactiva desde una ISO
# Crear una VM: 2 vCPU, 4 GB de RAM, disco qcow2 de 20 GB
sudo virt-install \
--name debian-test \
--memory 4096 \
--vcpus 2 \
--disk path=/var/lib/libvirt/images/debian-test.qcow2,size=20,format=qcow2 \
--cdrom /var/lib/libvirt/images/debian-13.1.0-amd64-netinst.iso \
--os-variant debian12 \
--network network=default \
--graphics vnc,listen=127.0.0.1
# Listar los identificadores de SO reconocidos (optimiza los controladores virtio)
virt-install --osinfo list | grep -i debian
El instalador se muestra por VNC (usa virt-viewer debian-test o un túnel SSH). Para un servidor sin interfaz gráfica, el enfoque con cloud-init de la sección 8 es mucho más eficaz.
4. Gestionar las VM con virsh
Ciclo de vida
# Listar las VM (activas y detenidas)
virsh list --all
# Iniciar una VM
virsh start debian-test
# Apagado limpio (envía una señal ACPI, el invitado debe gestionarla)
virsh shutdown debian-test
# Apagado brusco (equivale a desenchufar el cable)
virsh destroy debian-test
# Reinicio
virsh reboot debian-test
# Arranque automático con el host
virsh autostart debian-test
# Consola serie de texto (si está configurada en el invitado)
virsh console debian-test
# Eliminar una VM y sus discos de forma definitiva
virsh undefine debian-test --remove-all-storage
Inspección y recursos
# Información detallada
virsh dominfo debian-test
# Direcciones IP obtenidas por la VM
virsh domifaddr debian-test
# Modificar la memoria en caliente (dentro del máximo definido)
virsh setmem debian-test 2048M --live
# Editar la definición XML de la VM
virsh edit debian-test
Snapshots
# Crear un snapshot antes de una operación arriesgada
virsh snapshot-create-as debian-test avant-migration \
--description "Avant montée de version PostgreSQL"
# Listar los snapshots
virsh snapshot-list debian-test
# Volver a un snapshot
virsh snapshot-revert debian-test avant-migration
# Eliminar un snapshot que ya no sirve
virsh snapshot-delete debian-test avant-migration
Los snapshots internos requieren el formato qcow2. Ojo: un snapshot no es una copia de seguridad, vive en el mismo disco que la VM y degrada ligeramente el rendimiento si se acumulan.
5. Discos qcow2 con qemu-img
El formato qcow2 (QEMU Copy-On-Write) admite aprovisionamiento ligero (el archivo solo crece con los datos reales), snapshots internos e imágenes base.
# Crear un disco de 50 GB (al principio ocupa solo unos pocos KB)
qemu-img create -f qcow2 /var/lib/libvirt/images/data.qcow2 50G
# Inspeccionar una imagen: tamaño virtual frente a tamaño real en disco
qemu-img info /var/lib/libvirt/images/debian-test.qcow2
# Ampliar un disco (después habrá que extender la partición en el invitado)
qemu-img resize /var/lib/libvirt/images/debian-test.qcow2 +20G
# Convertir una imagen de VMware/VirtualBox a qcow2
qemu-img convert -f vmdk -O qcow2 machine.vmdk machine.qcow2
# Compactar una imagen (la VM debe estar obligatoriamente apagada)
qemu-img convert -O qcow2 ancienne.qcow2 compactee.qcow2
Imágenes base y clones ligeros
# Crear un clon que solo almacena las diferencias con la imagen base
qemu-img create -f qcow2 -F qcow2 \
-b /var/lib/libvirt/images/base-debian.qcow2 \
/var/lib/libvirt/images/clone-01.qcow2
# Comprobar la cadena de dependencias
qemu-img info --backing-chain /var/lib/libvirt/images/clone-01.qcow2
No modifiques ni muevas nunca una imagen base mientras haya clones que dependan de ella: todos los clones quedarían corruptos.
6. Redes de libvirt: NAT y bridge
La red NAT por defecto
Durante la instalación, libvirt crea la red default: un puente interno virbr0 en 192.168.122.0/24 con DHCP integrado (dnsmasq). Las VM salen a Internet mediante NAT, pero no son accesibles desde la red física.
# Listar las redes de libvirt
virsh net-list --all
# Iniciar y hacer persistente la red por defecto
virsh net-start default
virsh net-autostart default
# Ver las concesiones DHCP asignadas a las VM
virsh net-dhcp-leases default
Bridge: VM como ciudadanas de la red local
Para que las VM obtengan una dirección IP de la red física (como máquinas de pleno derecho), crea un puente en el host. Ejemplo con Netplan (Ubuntu Server), en /etc/netplan/01-bridge.yaml:
network:
version: 2
ethernets:
enp3s0:
dhcp4: false
bridges:
br0:
interfaces: [enp3s0]
dhcp4: true
# Aplicar con una ventana de reversión automática en caso de corte
sudo netplan try
# Comprobar el puente
ip addr show br0
A continuación, conecta las VM al puente:
# Al crearla
virt-install ... --network bridge=br0 ...
# O modifica una VM existente: en virsh edit, sustituye
# <source network='default'/> por <source bridge='br0'/>
| Modo | Dirección IP de la VM | Accesible desde la LAN | Caso de uso |
|---|---|---|---|
| NAT (default) | 192.168.122.x privada | No | Equipos de desarrollo, laboratorios aislados |
| Bridge (br0) | Dirección de la LAN | Sí | Servidores de producción |
| Isolated | Privada, sin salida | No | Pruebas de seguridad, entornos sandbox |
7. ¿Contenedores LXC o máquinas virtuales?
LXC ejecuta contenedores de sistema: espacios aislados que comparten el kernel del host, mientras que KVM arranca un kernel completo por máquina. Ambos enfoques suelen coexistir en el mismo host (Proxmox es un buen ejemplo).
| Criterio | LXC (contenedor de sistema) | KVM (máquina virtual) |
|---|---|---|
| Kernel | Compartido con el host | Propio de cada VM |
| Aislamiento | Namespaces y cgroups | Por hardware (VT-x/AMD-V) |
| Densidad | Muy alta (cientos por host) | Limitada por la RAM dedicada |
| Arranque | Alrededor de 1 segundo | De 10 a 60 segundos |
| Sobrecoste de memoria | Casi nulo | RAM reservada por VM |
| SO invitado | Solo Linux | Linux, Windows, BSD |
| Kernel o módulos personalizados | Imposible | Sí |
| Seguridad multiinquilino | Correcta, superficie más amplia | Fuerte, referencia de la nube pública |
# Vistazo rápido a LXC en Ubuntu
sudo apt install lxc
sudo lxc-create -n conteneur-test -t download -- -d debian -r bookworm -a amd64
sudo lxc-start -n conteneur-test
sudo lxc-attach -n conteneur-test
Regla de decisión: LXC para muchos entornos Linux ligeros en una misma máquina; KVM en cuanto se necesite otro SO, un kernel específico o un aislamiento fuerte entre inquilinos.
8. cloud-init: automatizar el aprovisionamiento
cloud-init es el estándar de inicialización de las imágenes cloud: en su primer arranque, la VM lee una configuración (usuarios, claves SSH, paquetes, comandos) y se autoconfigura. Combinado con las imágenes cloud oficiales, elimina por completo la instalación manual.
Obtener una imagen cloud
# Imagen cloud de Ubuntu 24.04 (qcow2 listo para usar, unos 600 MB)
sudo wget -P /var/lib/libvirt/images/ \
https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
Escribir la configuración user-data
# /tmp/user-data.yaml
#cloud-config
hostname: vm-web-01
users:
- name: admin
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... admin@poste-travail
package_update: true
packages:
- nginx
- htop
runcmd:
- systemctl enable --now nginx
Crear la VM aprovisionada
# Crear el disco de la VM a partir de la imagen cloud (clon ligero ampliado)
sudo qemu-img create -f qcow2 -F qcow2 \
-b /var/lib/libvirt/images/noble-server-cloudimg-amd64.img \
/var/lib/libvirt/images/vm-web-01.qcow2 20G
# virt-install genera la ISO de cloud-init automáticamente con --cloud-init
sudo virt-install \
--name vm-web-01 \
--memory 2048 \
--vcpus 2 \
--disk path=/var/lib/libvirt/images/vm-web-01.qcow2,format=qcow2 \
--import \
--os-variant ubuntu24.04 \
--network network=default \
--cloud-init user-data=/tmp/user-data.yaml \
--noautoconsole
# Dos minutos después: obtener la dirección IP y conectarse
virsh domifaddr vm-web-01
ssh admin@192.168.122.53
La VM arranca, crea el usuario, instala nginx y activa el servicio sin ninguna intervención. Este proceso se puede automatizar con scripts y después industrializar con Terraform (provider libvirt) o Ansible.
Buenas prácticas
- Ejecuta
virt-host-validatetras cualquier instalación o actualización del host. - Trabaja siempre sobre
qemu:///systemen los servidores y fijaLIBVIRT_DEFAULT_URIpara evitar VM «desaparecidas» creadas en la conexión equivocada. - Indica siempre
--os-varianten virt-install: los controladores virtio seleccionados marcan una gran diferencia de rendimiento. - Prefiere
virsh shutdownavirsh destroy: un apagado brusco puede corromper los sistemas de archivos del invitado. - Trata los snapshots como puntos de retorno temporales, nunca como copias de seguridad: haz copia de los archivos qcow2 (con la VM apagada o mediante un snapshot externo consistente).
- No toques nunca una imagen base referenciada por clones.
- Reserva el NAT para los entornos de prueba; usa un bridge para cualquier servicio que deba ser accesible.
- Estandariza el aprovisionamiento con cloud-init desde la segunda VM: la configuración manual no escala.
- Vigila el espacio en disco de
/var/lib/libvirt/images: los qcow2 con aprovisionamiento ligero crecen en silencio hasta llenar el volumen.
Conclusión
La pila KVM, QEMU y libvirt ofrece una virtualización de nivel de producción con herramientas exclusivamente del software libre: KVM aporta un rendimiento casi nativo, QEMU la emulación del hardware y libvirt una interfaz de gestión coherente, del equipo de desarrollo al clúster. Ahora sabes comprobar el soporte de hardware, instalar la pila, crear VM con virt-install, controlarlas con virsh, gestionar discos qcow2, elegir entre NAT y bridge, decidir entre contenedores LXC y máquinas virtuales, y automatizar el aprovisionamiento con cloud-init.
El siguiente paso es industrializar: describe tus VM en Terraform con el provider libvirt, configúralas con Ansible y tu infraestructura de virtualización será reproducible, versionada y auditable como código.
Acerca de InSkillCoach
Experto en formación y tecnologías
Coach especializado en tecnologías avanzadas e IA, impulsado por GNeurone Inc.
Certificaciones:
- AWS Certified Solutions Architect – Professional
- Certificaciones de Google Cloud
- Microsoft Certified: DevOps Engineer Expert
- Certified Kubernetes Administrator (CKA)
- CompTIA Security+
Comentarios
Los comentarios funcionan con GitHub Discussions
Inicia sesión con GitHub para participar en la discusión