hotplug

QEMU-KVM: Aumentar la memoria RAM “en vivo”. Método 2

QEMU, al fin y al cabo, no es más que un emulador muy similar a veces a lo que sería…tu portátil. En el funcionamiento normal de QEMU existen métodos para insertar y extraer periféricos USB, discos, “devices” en general.

De manera que, si tu linux lo soporta, ¿porqué no simular que conectamos o desconectamos DIMMs completos de RAM en vivo?

Eso es lo que implementaron los desarrolladores de QEMU hace un tiempo, la capacidad para insertar y desconectar DIMMs de RAM sin tener que reiniciar el servidor. Ahora bien, tiene su truco. Al igual que en la placa base de tu portátil, existe una especificación que asocia ciertos módulos de RAM a un procesador. Es como cuando conectáis un servidor con dos procesadores, y tenéis que colocar RAM en un lado de la placa asociada a un procesador, y la otra parte en el otro lado, asociada al otro procesador.

Eso mismo, se puede  hacer en QEMU. Y es un poco engorroso porque a la hora de colocar un DIMM de RAM tienes que ver los “huecos” que tienes libres en la “placa base” simulada, para poder enganchar el DIMM de RAM en el sitio adecuado.

 

Antes de nada, recordad que en QEMU, con libvirtd,  si queremos ser capaces de modificar la RAM en vivo, hay que especificarle un “máximo” de RAM y un valor con el que arranca. En el caso de libvirt, tenemos que definir ese máximo, y , de paso, definir un nodo NUMA (aunque esté mal dicho, vamos a decir que es una serie de huecos disponibles)

En este caso, definimos un máximo de 16 GB y un valor actual de RAM de 1 GB. Y le especificamos, que el nodo NUMA de ID 0, puede estar asociado a las CPUs (virtuales) de ID 0 al 2.

Como casi todo en libvirt, se puede definir un DIMM de memoria RAM en formato XML.

En este caso, un DIMM de 256 MB de RAM.

Ahora, para conectarlo:

Si todo ha ido bien, el vuestro servidor virtual aparecerán esos 256 MB de RAM extra.

Para quitarlo, se puede usar el comando detach-device. Podréis quitar la RAM que hayáis añadido.

 

¿Dónde funciona esto?

En servidores Centos 6, Debian 7, y versiones similares.

Con un libvirt más o menos moderno, a partir de la 1.2.14.

Con un kernel 4 de linux en el hypervisor. Yo no lo probaría con el kernel por defecto de RedHat. Otra cosa es el kernel UEK de Oracle Linux.

 

¿Dónde está la documentación?

Esta es una pregunta recurrente en el universo de QEMU 😉

Está aquí: https://github.com/qemu/qemu/blob/master/docs/memory-hotplug.txt

Te explica cómo insertar DIMMs de RAM a través del interfaz de QEMU.

Y respecto a la documentación de libvirt: https://libvirt.org/formatdomain.html#elementsMemory

 

QEMU-kVM aumentar la memoria “en vivo”, método 1

Existen dos métodos principales para aumentar (o disminuir) la memoria “en vivo” del servidor. Ambas requieren un poco de previsión.

El primer paso, al arrancar el servidor tener en cuenta que “memory” identifica la memoria máxima que queremos que pueda ocupar ese servidor, y “currentmemory” es la que le dejamos ocupar al arrancar.

En el XML de libvirt:

En línea de comandos con QEMU:

 

Si queremos modificar la RAM que utiliza nuestro servidor:

 

En libvirt,

 

Y en libvirt, pero pasando el comando directamente al “monitor” de QEMU con “virsh qemu-monitor-command –hmp SERVIDOR –cmd ”

 

 

Veremos como se ajusta la RAM dentro del servidor, siempre que este tenga activado el soporte para “Memory Ballooning”.

 

Hay varias cosas a tener en cuenta:

 

  • En Windows, necesitas tener activo el device de ballooning y con el driver adecuado, que viene en la ISO de drivers para windows de QEMU , https://fedoraproject.org/wiki/Windows_Virtio_Drivers
  • Al arrancar, el servidor te intentará reservar lo que esté especificado como MÁXIMO. Es decir, si tu creas un servidor con 1024 de Memory y 512 de “current”, al arrancar, intentará reservar 1024. Si no cabe, porque deja sin memoria el servidor, el proceso de QEMU morirá.
  • No es bueno bajar la RAM por debajo de 128MB en los linux. Dará kernel panic. Hay que tener cuidado al especificar las unidades de medida de la RAM.

 

 

Hotplug de CPU en QEMU+KVM

Desde la versión 2.7 rc1 de QEMU (publicada el 1 de Agosto 2016) es posible realizar, al fin, una modificación en el número de CPUs sin reiniciar el servidor. A esta función se le denomina “hotplug” de CPU.

Hasta ahora tan solo se podía aumentar el número de cores, ahora es posible también disminuirlos sin tener que apagar del todo el servidor, pero eso si, con ciertas restricciones.

  • No es posible quitar el último core (el primero de todos según se inicia el servidor).
  • Ciertos sistemas operativos no lo soportan porque no son capaces de “activar” las CPUs cuando se les engancha. En los Redhat’s y variantes (CentOS, p.ej) funciona bien. En los sistemas operativos Windows, también funciona adecuadamente. Los sistemas operativos Debian en cambio requieren de ciertas modificaciones en el “udev” para que el sistema operativo active los nuevos cores.
  • Solo lo he probado a partir de kernels 4.4, que es lo que suelo utilizar. En cualquier caso, necesitaría un kernel moderno. Yo no probaría aun a utilizar kernel 4.6.

Esta funcionalidad no está integrada en libvirt 2.0 aun, por lo que se ha de hacer a mano desde qemu, via “monitor”. Por simplificar, y como casi todos arrancamos los procesos con qemu+libvirt pongo el comando para libvirt exacto.

Primero vemos a ver el ID de nuestro servidor virtual. Se puede hacer igual con el nombre, para el argumento de –domain.

 

Seguidamente vamos a obtener las posiciones disponibles en las que enganchar las CPUs nuevas.

 

Hay que fijarse en la parte del “qom_path” de cada CPU. Para el siguiente comando “device_add” necesitamos pasarle el tipo de objeto, “qemu64-x86_64-cpu”, y donde lo vamos a colocar.

Según el comando anterior, y mirando el qom_path, tenemos dos CPUs ocupadas y nos quedan dos huecos libres.

 

Ahora para enganchar una nueva CPU tecleamos.

Explico todos los argumentos del comando virsh.

  • qemu-monitor-command: sirve para comunicarse con el proceso de qemu via un socket llamado “monitor”. Si tecleamos, por ejemplo, qemu-monitor-command –domain 13 –hmp help, enviaría al proceso de qemu el –help para que sacase las diferentes opciones disponibles. Este socket “monitor” está bloqueado por libvirt para poder gestionar el proceso de QEMU.
  • hmp: hay dos maneras de enviar comandos al proceso de qemu, una es via JSON, y otra, que es esta, via comandos.
  • device_add: el comando para añadir nuevos devices, ya sean tarjetas de red, CPUs, etc..
  • qemu64-x86_64-cpu: el tipo de objeto que estamos añadiendo. En este caso una CPU x86. Obviamente, no se pueden añadir diferentes tipos de CPU, y para cada sistema emulado hay que añadir el tipo adecuado. Hay ciertos tipos de emulaciones que aun no admiten este tipo de cambios en las CPUs.
  • socket-id=3, code-id=0, thread-id=0: Cuando creamos el servidor le especificamos la “estructura” de las CPUs, como si fuera la placa base de nuestro PC casero. P.ej:

-smp 2,sockets=2,cores=1,threads=1 (2 sockets de 1 core cada 1, y 1 thread por si queremos emular hyperthreading)

  • id: le ponemos un nombre. Es importante para simplificar el comando de eliminar. En este caso, cpu2.

En este caso, nosotros sabemos que tenemos el socket 3 y 4 libres, por el comando “info hotpluggable-cpus”, y le especificamos que se inserte en el socket 3.

Si en el servidor virtual miramos el fichero /var/log/messages, veremos un mensaje de ACPI indicando una nueva CPU. Aparecerá también en el comando “top” como una nueva CPU si pulsamos “1” para desplegar las CPUs.

Si no aparece en el “top” o en /proc/cpuinfo es probable que haya que activarla

 

Antes de añadir una nueva CPU

Antes y después de añadir una nueva CPU

Después de añadir una nueva CPU

 

 

Para quitar una CPU, ejecutamos:

Y la CPU desaparece del sistema, salvo error.