Hacer overcommit de memoria (sobreasignación) significa asignar a las máquinas virtuales más RAM en total de la que tiene el host. Funciona porque la mayoría de VMs no usan toda su memoria a la vez, pero si todas la reclaman al mismo tiempo el host se queda sin memoria y el OOM killer del kernel termina alguna VM. En este tutorial medirás el ratio de overcommit de un host KVM con Ubuntu 24.04, configurarás virtio-balloon para recuperar memoria de las VMs, activarás KSM para deduplicar páginas idénticas y dejarás el host protegido frente a picos.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, KVM y libvirt instalados (
qemu-kvm,libvirt-daemon-system,libvirt-clients). - Un usuario no root con privilegios
sudoy miembro del grupolibvirt. - Al menos una VM Linux gestionada por libvirt. En los ejemplos se llama
web01y tiene 4 GB de RAM.
Paso 1: Medir la memoria del host y la asignada a las VMs
Empieza por ver cuánta memoria tiene el host y cuánta está realmente disponible:
free -h
total used free shared buff/cache available
Mem: 62Gi 41Gi 2.1Gi 1.0Gi 19Gi 20Gi
Swap: 8.0Gi 0B 8.0Gi
La columna que importa es available: memoria que el kernel puede entregar sin recurrir a swap, incluida la caché que puede liberar.
Suma ahora la memoria máxima asignada a todas las VMs en ejecución. virsh dominfo la muestra en KiB:
for vm in $(virsh list --name); do
virsh dominfo "$vm" | awk '/Max memory/ {print $3}'
done | awk '{sum += $1} END {printf "Asignado a VMs: %.1f GiB\n", sum / 1048576}'
Asignado a VMs: 88.0 GiB
Con 62 GiB físicos y 88 GiB asignados, el ratio de overcommit es de 88 / 62 = 1,4. Como referencia práctica:
| Ratio | Situación |
|---|---|
| Hasta 1,0 | Sin overcommit. Cada VM tiene su memoria garantizada. |
| 1,0 a 1,5 | Razonable con VMs de carga variada, ballooning y KSM activos. |
| Más de 1,5 | Arriesgado. Solo con VMs muy parecidas (mismo sistema, poca carga) y vigilancia constante. |
Deja siempre fuera del cálculo la memoria que necesita el propio host: unos 2-4 GB para el sistema y un 5-10 % adicional para la sobrecarga de QEMU.
Paso 2: Comprobar el dispositivo virtio-balloon
El balloon es un controlador dentro de la VM que puede "inflarse" para reservar memoria del invitado y devolverla al host, o "desinflarse" para devolvérsela a la VM. libvirt añade un dispositivo virtio de este tipo por defecto a las VMs nuevas. Compruébalo:
virsh dumpxml web01 | grep -A3 '<memballoon'
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
</memballoon>
Si aparece model='none' o no aparece nada, el ballooning no está disponible para esa VM. Dentro de la VM, comprueba que el controlador está cargado (en los kernels de Ubuntu, Debian y RHEL viene incluido):
lsmod | grep virtio_balloon
virtio_balloon 28672 0
Paso 3: Activar estadísticas y free page reporting
Por defecto el balloon no informa al host de cuánta memoria usa el invitado. Apaga la VM y edita su XML para activar las estadísticas cada 10 segundos, el desinflado automático y el free page reporting:
virsh shutdown web01
virsh edit web01
Sustituye la línea de apertura del bloque <memballoon> (conserva la línea <address> que ya tuviera) para que quede así:
<memballoon model='virtio' autodeflate='on' freePageReporting='on'>
<stats period='10'/>
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
</memballoon>
stats period='10': el invitado envía estadísticas de memoria al host cada 10 segundos.autodeflate='on': si el invitado está a punto de quedarse sin memoria, el balloon se desinfla solo antes de que actúe su OOM killer.freePageReporting='on': el invitado devuelve al host las páginas que libera, sin que tengas que ajustar el balloon a mano. Requiere un kernel de invitado 5.7 o posterior (Ubuntu 22.04 y 24.04 lo cumplen).
Arranca la VM y consulta sus estadísticas de memoria:
virsh start web01
virsh dommemstat web01
actual 4194304
swap_in 0
swap_out 0
major_fault 312
minor_fault 184022
unused 2871320
available 4020428
usable 3310244
rss 1650428
Los valores están en KiB. actual es la memoria asignada actualmente, usable la que el invitado podría usar sin swap y rss la que la VM ocupa de verdad en el host (unos 1,6 GB de los 4 GB asignados, en este ejemplo).
Paso 4: Recuperar memoria de una VM con el balloon
Con el balloon puedes reducir la memoria de una VM en caliente. Baja web01 a 2 GB:
virsh setmem web01 2G --live
virsh dommemstat web01 | grep actual
actual 2097152
Dentro de la VM, free -h mostrará ahora un total de unos 2 GB. Para devolverle la memoria:
virsh setmem web01 4G --live
No puedes superar la memoria máxima (Max memory) de la VM con setmem. Para dejar margen de crecimiento, define un máximo mayor que la memoria de arranque. Con la VM apagada:
virsh setmaxmem web01 8G --config
virsh setmem web01 4G --config
La VM arrancará con 4 GB y podrás subirla en caliente hasta 8 GB con virsh setmem web01 8G --live.
Importantesi reduces la memoria de una VM por debajo de lo que está usando, el invitado empezará a usar swap o su OOM killer matará procesos. Consulta antes
usableenvirsh dommemstaty deja siempre margen.
Paso 5: Activar KSM para deduplicar memoria
KSM (Kernel Samepage Merging) busca páginas de memoria idénticas entre VMs y las fusiona en una sola copia. Ahorra mucho cuando ejecutas muchas VMs con el mismo sistema operativo. QEMU marca la memoria de las VMs como fusionable por defecto, así que solo hay que activar KSM en el host.
Instala ksmtuned, un servicio que activa KSM cuando la memoria libre baja y ajusta su intensidad automáticamente:
sudo apt install ksmtuned
sudo systemctl enable --now ksmtuned
Verifica que está activo:
systemctl status ksmtuned --no-pager
Active: active (running) since Thu 2026-09-25 10:20:13 UTC; 8s ago
ksmtuned solo pone KSM en marcha cuando la memoria libre cae por debajo de un umbral (por defecto, el 20 % de la RAM). Para comprobar si KSM está trabajando y cuánto ahorra, consulta sus contadores:
cat /sys/kernel/mm/ksm/run
cat /sys/kernel/mm/ksm/pages_sharing
1
524288
run vale 1 cuando KSM está activo. pages_sharing es el número de páginas de 4 KiB que se están ahorrando: 524288 páginas equivalen a 2 GiB. Tras activarlo, KSM tarda varios minutos en recorrer la memoria, así que el contador crece de forma gradual.
AdvertenciaKSM consume CPU al escanear la memoria y, en teoría, permite ataques de canal lateral entre VMs que comparten páginas. En hosts con VMs de clientes distintos o con requisitos de aislamiento estrictos, valora dejarlo desactivado.
Paso 6: Proteger el host frente a picos de memoria
Aunque configures balloon y KSM, un pico simultáneo en varias VMs puede agotar la RAM. Tres medidas reducen el impacto.
Primero, ten swap en el host. No es para uso habitual, sino para absorber picos sin que el OOM killer mate una VM. Comprueba que existe con swapon --show y, si no hay, crea un archivo de swap de 8 GB:
sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Segundo, reduce la tendencia del kernel a usar swap para que solo lo haga bajo presión real:
echo 'vm.swappiness = 10' | sudo tee /etc/sysctl.d/99-kvm-memory.conf
sudo sysctl --system
Tercero, vigila la presión de memoria. El archivo PSI del kernel indica el porcentaje de tiempo en que los procesos esperaron por memoria en los últimos 10, 60 y 300 segundos:
cat /proc/pressure/memory
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0
Valores de some sostenidos por encima de 5-10 indican que el host ya sufre por falta de memoria: es el momento de reducir el balloon de alguna VM o migrarla a otro host. Integra esta métrica en tu sistema de monitorización.
Solución de problemas
virsh setmem no cambia la memoria de la VM: el invitado no tiene cargado virtio_balloon o la VM tiene <memballoon model='none'>. Revisa el paso 2.
virsh dommemstat solo muestra actual y rss: falta <stats period='10'/> en el XML o el invitado aún no ha enviado estadísticas. Espera unos segundos tras arrancar.
Una VM se apaga sola y en el host aparece Out of memory: Killed process ... (qemu-system-x86): el host se quedó sin memoria. Búscalo con sudo journalctl -k | grep -i "out of memory", reduce el ratio de overcommit, añade swap o mueve VMs a otro host.
Conclusión
Has medido el ratio de overcommit de tu host, configurado virtio-balloon con estadísticas, autodeflate y free page reporting, activado KSM con ksmtuned y preparado el host con swap y vigilancia de presión de memoria. Como siguientes pasos, añade rss de virsh dommemstat y /proc/pressure/memory a tus gráficas de monitorización, reserva memoria sin overcommit para las VMs críticas (por ejemplo, con hugepages) y define un procedimiento para migrar VMs a otro host cuando la presión se mantenga alta.
