Category Archives: KVM

Migrando una VM desde OpenVZ a KVM

Este post es muy interesante, relacionado con respaldos con rsync, manejo de máquinas virtuales, paquetes de Linux, manejo de la red.

En este post vemos una breve introducción a OpenVZ y KVM para entrar de lleno al proceso de migración de un sistema de virtualización al otro.

OpenVZ es un sistema de virtualización de Sistema Operativo muy popular, similar a LXC que permite a un sistema operativo Linux correr múltiples instancias a las cuales popularmente se les conoce como VPS.

Este tipo de virtualización basada en sistema operativo tiene la característica de que todas las máquinas virtuales que en ella corren, lo hacen usando el mismo único kernel que el hospedero tiene.

Tiene algunas desventajas, entre ellas que, ante un fallo en el kernel, todas las VPS se verían afectadas y que si un cliente necesita una versión diferente del kernel esto no será posible.

Ahora, tiene cosas buenas como el hecho de que es más rápido el funcionamiento del kernel ya que todas usan el mismo kernel y además que la memoria que no usa un VPS será aprovechada por otro VPS.

¿Por qué migrar desde OpenVZ?

Ocurren ocasiones en que es necesario migrar una VPS en OpenVZ hacia un sistema con full virtualización; por ejemplo porque se necesita utilizar las características de aislamiento típicas de un sistema full virtualizado como KVM, por ejemplo porque se requiere un kernel específico.

O porque nuestro proveedor de VPS va a dejar de ofrecernos el servicio,

Otra razón, la más común, es que necesitamos un manejo más certero de recursos como RAM, necesitamos que la RAM que adquirimos para nuestra VPS nos esté garantizada para nuestra máquina virtual, esto debido a que muchos proveedores de OpenVZ hacen lo que se llama “overselling” que es ofrecer a los clientes recursos que no se tienen realmente. Por ejemplo, tienen un servidor con 128GB de RAM y venden a sus clientes 10 máquinas virtuales de 24GB cada una. Si multiplicamos 10*24G=240G, que es mucho mayor que los 128GB que tienen. Esto es posible ya que OpenVZ permite utilizar la memoria que un cliente no usa, puede que un ciente de sus 24GB de RAM “comprados”, realmente use 8GB, y el resto lo tenga libre y solamente lo use en picos en ciertas horas del día. Esto permite al proveedor aprovechar esos 16GB para que en el mismo servidor corran otras máquinas de otros clientes.

Esto usualmente no causa problemas ya que usualmente no todas las máquinas usan toda la memoria todo el tiempo, es posible que una máquina use toda la memoria ahora, pero dentro de 5 minutos ya use solamente el 20% de esta, y entonces otra máquina comience a usar toda la RAM pero luego de 15 minutos ya use solamente el 15%. Como podemos ver, se tiene la esperanza de que la memoria se pueda ir compartiendo: una vez se usa para un grupo de clientes, pero luego para otro, etc.

El problema radica en que si en un determinado momento varios clientes, por diversas razones, comienzan a utilizar toda la memoria que reservaron, el servidor se quedará sin memoria. Existen técnicas como el uso de la SWAP, pero eventualmente se agota además de ser lenta.

Debe tenerse mucho cuidado con los proveedores de VPS ya que muchos, en el afán de ganar dinero, sobrevenden bastante agresivamente sus servidores. Siempre es saludable pensar que si un VPS es muy muy barato para las características que ofrecen, es síntoma de que se está sobrevendiendo agresivamente (mucho).

Lo contrario ocurre con proveedores que ofrecen virtualización completa (full virtualization) basada en KVM, Xen, VMWare. Los sistemas de full virtualización sí permiten la sobreventa de ciertos recursos (usando KSM para la RAM por ejemplo). Pero típicamente cuando vemos nombres como KVM, Xen o VMWare, esto significa que los recursos que vamos a contratar estarán disponibles para nuestra VM.

¿Qué problema tenemos al migrar desde OpenVZ?

El problema principal al migrar desde OpenVZ es que sus VPS no tienen el paquete “kernel” instalado entonces, aunque logremos convertir su disco duro (que está en formato ploop) hacia, digamos, qcow2, este no arrancará en nuestro KVM pues no existe un kernel para arrancar.

Esto no es un defecto, es una característica de OpenVZ, recordemos que las VPS no contienen un kernel propio sino que usan el kernel del hospedero. Pero las máquinas virtuales full virtualizadas sí necesitan tener su kernel cada una.

Procedimiento para migrar

El procedimiento en sentido general es bien sencillo, pero lleva una serie de pasos que debemos seguir con mucho cuidado.

Digamos que tenemos una VPS en OpenVZ que por comodidad llamaré “Servidor anterior” y tendremos una VM en KVM hacia la que queremos migrar el servidor anterior. A esta VM le llamaré “Servidor nuevo”. Anota esto en algún ugar.

Los siguientes pasos en algunos casos pueden ser realizados en diferente orden, o de forma paralela. Pero bueno, sigamos en esta orden:

Servidor anterior:

  • Ahorra espacio, borra todo lo que puedas borrar para agilitar la transferencia. Mientras más contenidos tengas, más tiempo demorará la transferencia.
  • Si es posible, disminuye el tamaño de los logs:
journalctl --vacuum-size=10M
  • Actualiza el sistema operativo y reinicia la máquina para validar que todo funcione luego de actualizar. Es importante actualizar ya que es muy útil que ambos servidores, el anterior y el nuevo, estén en la misma versión, y la forma de garantizar esto es que ambos estén actualizados.
  • Es importante reinciar ya que no queremos culpar a la migración por algo que falla desde antes. Ocurre que hay ocasiones en que luego de reiniciar no arranca algún servicio y es porque no estaba activado por defecto. En fin, es importante estar seguros que el servidor anterior funciona correctamente!
yum -y update && yum clean all && reboot
  • Anotemos la versión de Linux que corremos, pues esa misma versión debemos instalar en el nuevo servidor.
cat /etc/centos-release
AlmaLinux release 8.9 (Midnight Oncilla)

En este caso, es un AlmaLinux versión 8.

El release (.9) lo logramos en ambos servidores haciendo yum update. Es importante manteer la misma versión y release ya que ahorraremos tiempo al copiar archivos y a que algunos archivos que no existen en el servidor viejo (el kernel por ejemplo) los tendremos en el nuevo, todo con la misma misma versión.

Servidor nuevo:

  • Instalaremos la misma versión que en el server viejo. En mi ejemplo será AlmaLinux 8.
  • Instalo el paquete rsync. Este es el comando que usaremos para sincronizar por lo que debe existir en ambos servidores:
yum -y install rsync
  • Una vez instalado, le procedo a actualizar, con esto le llevaré al mismo release del servidor viejo que ya teníamos actualizado.
cat /etc/redhat-release; yum -y update &&  reboot
AlmaLinux release 8.9 (Midnight Oncilla)

Como podemos ver, tenemos la misma versión y release (8.9) que el servidor anterior. He reiniciado para estar seguro que el servidor arranca con el nuevo kernel, y que arranca correctamente.

Una vez más, reiniciamos para diferenciar si un futuro problema que tengamos con el reinicio, sea por la copia de los archivos y no de la actualización.

Copiamos los contenidos del archivo de configuración de red.

cat /etc/syscofig/network-scripts/ifcfg-eth0

En mi caso mi archivo se llama ifcfg-eth0, en tu caso puede variar. Es importante anotar los contenidos de la configuración de la red ya que al sincronizar los archivos en el siguiente paso, el rsync borrará los archivos que no existan en el servidor viejo, y este es uno de ellos.

Servidor viejo:

Regresamos ahora al servidor viejo, vamos a copiar los contenidos del viejo al nuevo. Vamos a instalar rsync, apagar mysqld; o mariadb, o postgresql, el que tengas.

Apagaremos el servidor de mysql para que no queden transacciones inconsistentes. Al finalizar la transferencia le volvemos a encender. Aquí ves la importancia de haber borrado cualquier archivo o contenido que ya no uses, como te mencioné al inicio, esto es para que la transferencia no demore mucho ya que la BD estará apagada durante todo este tiempo.

yum -y install rsync
systemctl stop mysqld (o mariadb, o postgresql)
rsync --exclude=/etc/fstab --exclude=/boot --exclude=/proc --exclude=/lib/modules/ --exclude=/etc/udev --exclude=/lib/udev --exclude=/sys -e ssh --delete --numeric-ids -avpogtStlHz / root@IPDELSERVERNUEVO:/
systemctl start mysqld

Este proceso tomará tanto tiempo como contenidos tengas que transferir del servidor viejo a la IP del servidor nuevo. Y de la velocidad de la red. Puede tomar algunos minutos, o algunas horas, toca esperar.

Tip!

Hay ocasiones en que no queremos tener la BD apagada tanto tiempo, esto es lo que yo hago!:

  • Sincronizo con rsync, sin apagar la BD
  • Cuando la sincronía acabe, luego de varios minutos, horas o días: apago la BD en ambos servidores, viejo y nuevo, y vuelvo a sincronizar.
  • Como ya los contenidos estaban previamente sincronizados, el rsync solamente sincronizará los archivos que hayan cambiado, que serán infinitamente menos que la sincronía inicia.

Servidor nuevo:

Ya estamos finalizando! Ahora vamos a hacer unas tareas finales, que son las más importantes:

Borramos la configuracion de red del openvz ya que no nos sirve en el servidor nuevo. Y copiemos la configuraciónde ifcfg-eth0 que guardamos en los pasos anteriores. Al hacer rsync, este archivo fue borrado ya que no existe en el origen:

cd /etc/sysconfig/networ-scripts
rm ifcfg-venet*
vi ifcfg-eth0  (aqui copio los contenidos que guardé antes)

Reiniciamos el servidor nuevo para ver que arranque correctamente:

reboot

A mi siempre me arranca correctamente. La red me funciona, todo ok.

Procedo como paso final a instalar el paquete kernel. Este último paso es confuso para algunas personas porque, cómo es posible que el sistema ya arranque si no tiene el paquete kernel?

Lo que sucede es que el archivo del kernel sí existe, está, existe gracias a que instalamos la máquina nueva virtual con la misma versión y release. Estos archivos no fueron borrados porque al hacer rsync hicimos dos exclude importantes: el exclude de /boot y el exclude en /lib/modules que es donde se guardan el kernel y sus módulos.

El problema radica en que la BD de rpm /var/lib/rpm sí fue sobreescrita cuando se hizo el rsync, y recuerden que el viejo sistema no contiene el paquete kernel ya que OpenVZ no necesita este paquete. Es por eso que tenemos el kernel instalado, pero no tenemos el paquete en la BD.

Si no hacemos este último paso, el sistema funcionará maravillosamente, pero a la hora de actualizar los paquetes, al no existir evidencia en la BD de paquetes del kernel, no lo actualizará posiblemente. Por esto hagamos:

yum install kernel

Y para validar que nada haya cambiado, reiniciamos:

reboot

Resumen

Como podemos ver, el proceso es bastante sencillo, he tomado mi tiempo en describirlo completamente para que se comprenda el por qué de cada paso, pero si nos fijamos bien, son pocos pasos, quizá unos 15.

Una forma de reducir el tamaño de un qcow2 para respaldar

El sistema de virtualización por excelencia en Linux es KVM (libvirt). Las máquinas virtuales en KVM usualmente almacenan su disco en formato QCOW2.

QCOW2 utiliza, en principio, solamente el espacio que requiere, digamos que tenemos un disco QCOW2 de 50GB de tamaño, sin embargo esto no significa que el archivo .QCOW2 utilizará 50GB en disco desde un inicio. Sino que utilizará lo que se va realmente almacenando, digamos que estamos utilizando 8GB de este disco, entonces QCOW2 utilizará aproximadamente 8GB de los 50GB del disco.

A medida que pasa el tiempo, el sistema operativo irá realizando escrituras en diversas partes del disco, creando archivos, actualizándolos, y también eliminándolos. Esto irá provocando que el espacio realmente utilizado vaya difiriendo del espacio utilizado por el archivo de disco de QCOW2. Pasado un tiempo, digamos que nuestro sistema operativo está ocupando 12GB, sin embargo el tamaño del disco del QCOW2 puede ser de, por ejemplo, 29GB.

A veces nos topamos conque queremos dar de baja ya a una máquina virtual, no le usaremos más (o al menos durante mucho tiempo) . Y queremos guardar un respaldo de ella. Tomemos el ejemplo anterior: definitivamente sería mejor almacenar solamente el espacio utilizado (12GB) que no los 29GB que actualmente tiene el QCOW2. Nos ahorramos 17GB de espacio.

Aunque existen muchas técnicas para reducir el tamaño del QCOW2, hoy experimenté con una de ellas que consiste en utilizar el comando virt-sparsify.

virt-sparsify es un binario parte del paquete guestfs-tools, por lo que debemos verificar que este paquete esté instalado. Para CentOS podemos ejecutar:

sudo yum install guestfs-tools

virt-sparsify en principio fue concebido como un comando que llena de 0 los espacios declarados como vacíos en un disco. Al llenarse de 0, puede aprovecharse esos 0 para comprimir todo ese espacio conteniendo la misma información. De esta forma logramos librarnos de contenidos escritos en disco que ya no nos son de valor (porque ya fueron declarados como borrados).

Para ellos utilizamos:

[root@backups respaldos]# virt-sparsify mivm.qcow2 --compress mivm-new.qcow2

Lo que hará será leer los contenidos de la VM ‘mivm.qcow2’ y los escribirá hacia la salida ‘mivm-new.qcow2’, comprimiendo sus contenidos.

En mi caso fallaba al iniciar indicándome que no había espacio en TMPDIR, pues TMPDIR por defecto es /tmp/, lo que hice fue, antes de volverlo a ejecutar cambié el contenido de la variable TMPDIR hacia /respaldos/tmp ya que en la partición donde está /respaldos/ yo sí tenía espacio suficiente:

mkdir /respaldos/tmp
export TMPDIR=/respaldos/tmp

y volví a repetir la operación. Ten en cuenta que tengo un disco duro con varios TB disponibles montado en /respaldos/, es por eso que opero con /respaldos/

El proceso puede tomar tiempo, incluso horas, depende del disco duro, y al finalizar podemos probar que mivm-new.qcow2 pueda ser leído

guestmount -a mivm-new.qcow2 -i /mnt
ls /mnt
umount /mnt

Si efectivamente podemos leer los contenidos, entonces ya con tranquilidad podemos borrar el qcow2 original (mivm.qcow2 en mi caso).

Por último: ¿qué hace guestmount? Es un comando muy interesante y que merece su propio post aparte. guestmount es un comando que te permite “abrir”, montar, un disco qcow2 y poder ver sus contenidos. En este caso lo utilicé para simplemente validar que el disco duro se podía acceder y ver sus contenidos (lo monté en /mnt), pero sirve para mucho más, por ejemplo un cliente al que no le arranca la red, puedes apagar la máquina (guestmount y virt-sparsify deben utilizarse con la VM apagada!), y puedes montar el disco y corregir cualquier falla en la configuración de la red que el usuario necesite, y entonces desmontar el disco montado con guestmount y volver a arrancar la VM.

¿Cómo activar consola serial en CentOS-7?

Esto puede no funcionar para CentOS-8

  • Edito /etc/sysconfig/grub
  • en GRUB_CMDLINE_LINUX agrego: console=ttyS0
  • En GRUB_TERMINAL_OUTPUT agrego: serial
  • En la línea de comando: stty -F /dev/ttyS0 speed 9600
  • Ejecuto: grub2-mkconfig -o /boot/grub2/grub.cfg
  • systemctl enable --now getty@ttyS0
  • Reinicio la VM: reboot
  • Desde el hospedero puedo ejecutar: virsh console vm
  • Para salir de la consola presiono: CTRL 5

¿Cómo redimensionar un qcow2?

Este howto funciona perfectamente para CentOS-8. En CentOS-7 no tenemos nbd por lo que no funcionará tal cual aquí se ve.

  • Apagas la vm: virsh shutdown vm
  • Verificas que ya se haya apagado: virsh list
  • Incrementas el qcow2: qemu-img resize /var/lib/libvirt/images/vm.qcow2 +40G
  • Cargas el módulo de nbd en el kernel: modprobe nbd
  • Asignas el disco duro a un dispositivo nbd: qemu-nbd -c /dev/nbd0 /var/lib/libvirt/images/vm.qcow2
  • instalas gparted: dnf install -y gparted
  • Ejecutas gparted en el dispositivo nbd: gparted /dev/nbd0
  • Cuando finalizas el proceso de redimensionar y cierras el gparted, procedes a eliminar el dispositivo nbd:
    • qemu-nbd -d /dev/nbd0 && rmmod nbd
  • Enciendes la vm: virsh start vm

Instalar KVM en CentOS-8 Básico

Este es el proceso a seguir para instalar KVM en una instalación básica de CentOS-8

Esta instalación vendrá con cockpit para poder manejar las máquinas virtuales más cómodo

dnf -y install  epel-release

dnf -y groupinstall "Host de virtualización"

dnf -y install screen virt-manager cockpit-pcp \
cockpit-storaged cockpit-dashboard \
cockpit-machines xorg-x11-xauth

systemctl enable --now libvirtd cockpit.socket

Si todo fue bien, procedemos a reiniciar y validar podemos ingresar al cockpit : https://TUIP:9090

Una vez dentro de cockpit, cambiamos en “Sistema” el “Perfil de Rendimiento” a “virtual-host”

En la sección “Networks” de “Virtual Machines” podremos validar que, efectivamente, el bridge está activo:

Si no estuviera activo, debemos seguir lo indicado en nuestro otro post aqui.

En “Storage Pools” de la sección “Virtual Machines” procedemos a agregar el pool por defecto. En nuestro caso estará en /var/lib/libvirt/images y le llamaré “default” pues en caso de tener varios pools, el pool llamado “default” es el que cockpit escogerá:

Cómo agregar un bridge para KVM en CENTOS-8

No es muy difícil, pero al momento es la forma que he hallado para agregar un bridge al CentOS-8 de forma tal que se pueda usar en KVM.

Quizá hayan otras formas, pero esta es la que me ha funcionado luego de tanta prueba y error.

Vamos a asumir que tenemos una interfaz de red llamada “enp2s0“. Por supuesto se debe verificar cuál es el nombre de su interfaz de red en su instalación y cambiar enp2s0 por el nombre correcto de su interfaz.

Edito el archivo /etc/sysconfig/network-scripts/ifcfg-br0 y le pongo estos contenidos (tener en cuenta cambiar la IP a la IP de su server):

DEVICE=br0
NAME=br0
TYPE=Bridge
DELAY=0
STP=off
ONBOOT=yes
IPADDR="192.168.1.120"
PREFIX="24"
GATEWAY="192.168.1.1"
DNS1=8.8.8.8
BOOTPROTO=none
DEFROUTE=yes
AUTOCONNECT_SLAVES=yes
IPV6INIT=no

Ahora edito el archivo de configuración de mi interfaz (/etc/sysconfig/network-scripts/ifcfg-enp2s0) y le dejo tal y como se ve aquí, ni una letra más, ni una menos (tener en cuenta poner el nombre correcto en NAME y en DEVICE:

TYPE="Ethernet"
NAME="enp2s0"
DEVICE="enp2s0"
ONBOOT="yes"
BRIDGE=br0

Ahora procedo a agregar el bridge a KVM:

Creo un xml : /root/br0.xml con estos contenidos exactamente:

network>
    <name>br0</name>
    <forward mode="bridge"/>
    <bridge name="br0" />
</network>

Y procedo a darle de alta al KVM:

virsh net-start br0
virsh net-autostart br0
virsh net-list --all

Si todo parece bien, reiniciamos el equipo y deberá regresar con la IP asignada a la interfaz br0.