Guía rápida de KVM

De la Wikipedia:

Kernel-based Virtual Machine o KVM, (en español, Máquina virtual basada en el núcleo) es una solución para implementar virtualización completa con Linux. Está formada por un módulo del núcleo (con el nombre kvm.ko) y herramientas en el espacio de usuario, siendo en su totalidad software libre. El componente KVM para el núcleo está incluido en Linux desde la versión 2.6.20.

KVM permite ejecutar máquinas virtuales utilizando imágenes de disco que contienen sistemas operativos sin modificar. Cada máquina virtual tiene su propio hardware virtualizado: una tarjeta de red, discos duros, tarjeta gráfica, etc.

En primer lugar, debemos comprobar si nuestro equipo es compatible con KVM:

egrep --color '(svm|vmx)' /proc/cpuinfo

Si la salida anterior muestra algo, podremos seguir adelante. Si no muestra nada, también podremos seguir, pero no se aprovecharán las capacidades de virtualización del equipo (se hará un fallback a emulación en lugar de virtualización).

Instalación en Debian/Ubuntu

Para Debian/Ubuntu, deberemos instalar los siguientes paquetes:

sudo apt-get install cpu-checker qemu-kvm libvirt-bin bridge-utils virt-manager virt-viewer libguestfs-tools

También tendremos que añadir nuestro usuario al grupo libvirtd para poder gestionar máquinas virtuales en el sistema con nuestro propio usuario (sin ser root):

sudo adduser ${USER} libvirtd

Por último, deberemos reiniciar la sesión para que se recarguen nuestros permisos de usuario.

Instalación en Red Hat/CentOS

Para Red Hat/CentOS, deberemos instalar los siguientes paquetes:

sudo yum install kvm libvirt virt-viewer virt-manager virt-sysprep

Para poder gestionar máquinas virtuales sin necesidad de ser root, deberemos crear un grupo, agregar nuestro usuario a ese grupo, y configurar ese grupo en KVM para permitirle la gestión (básicamente, estamos simulando el comportamiento que Ubuntu ya hace por sí solo, referencia 1 y referencia 2):

sudo groupadd libvirtd
sudo usermod -a -G libvirtd ${USER}
sudo sed -r -i -e 's/^#?unix_sock_group = .*/unix_sock_group = "libvirtd"/' \
               -e 's/^#?unix_sock_rw_perms = .*/unix_sock_rw_perms = "0770"/' \
               -e 's/^#?auth_unix_rw = .*/auth_unix_rw = "none"/' \
               /etc/libvirt/libvirtd.conf
sudo service libvirtd restart

Por último, deberemos reiniciar la sesión para que se recarguen nuestros permisos de usuario.

Herramientas principales de gestión

Con KVM disponemos de varias herramientas para gestionar tanto el sistema como las propias máquinas virtuales:

  • virsh: nos permite gestionar el sistema y las máquinas virtuales a un nivel medio-bajo.
  • virt-install: nos permite crear máquinas virtuales de una forma sencilla.

Tipos de conexión

En la instalación por defecto, tenemos dos tipos de conexión:

  • qemu:///system: nos conectamos al servicio de virtualización del sistema. Las máquinas creadas aquí se pueden configurar para que arranquen automáticamente cuando se inicie el host.
  • quemu:///session: nos conectamos a nuestra propia sesión. Estas máquinas sólo las podrá ver y gestionar el propio usuario, y además, los archivos de imagen (discos duros, etc.), deberán estar en una ubicación donde el usuario pueda leer y escribir (en la ruta por efecto /var/lib/libvirt/images sólo puede escribir cuando nos conectamos a la URL de sistema).

Según las pruebas que he hecho, los comandos virsh y virt-instal (explicados en la siguiente sección) se comportan de manera distinta a la hora de conectarse. virsh por defecto se conecta a quemu:///system, mientras que virt-install se conecta a quemu:///session. Por esto, en los siguientes ejemplos, se especifica siempre como URL de conexión quemu:///system, ya que las imágenes de disco se van a crear en /var/lib/libvirt/images. Si no especificásemos URL de conexión, o pusiéramos la de sesión del usuario, deberíamos establecer una ruta de imagen de disco donde el propio usuario pueda escribir, como ${HOME}.

Instalación de virt-manager actualizado

Uso Ubuntu 13.10 y la versión en los repositorios es la 0.9.5. La última versión de virt-manager es la 1.0.1, pero no está en los repositorios para esta versión de Ubuntu (aunque sí a partir de la 14.04); esta última versión tiene bastantes mejoras, entre ellas, la gestión de snapshots. Para instalar la nueva versión no hay más que descargarse el fuente (está escrita en Python); no hay que compilar ni instalar como root (se pueden tener las 2 versiones de virt-manager, la de los repositorios y la instalada a mano, pero hay que tener cuidado con cuál ejecutamos para no volverse uno loco).

En primer lugar, tenemos que descargar una serie de dependencias adicionales que necesitamos (referencias uno y dos):

sudo apt-get install gir1.2-spice-client-gtk-3.0 python-gtk-vnc libglib2.0-bin python-ipaddr libvirt-glib-1.0-dev gir1.2-gtk-vnc-2.0

En principio esto también valdría para Red Hat/CentOS, pero no he encontrado el paquete necesario para la dependencia gi.repository en CentOS 6, y no he podido hacerlo funcionar.

yum install python-argparse ...

Después de instalar las dependencias, nos bajamos el paquete fuente, lo descomprimimos y lo ejecutamos:

wget http://virt-manager.org/download/sources/virt-manager/virt-manager-1.0.1.tar.gz -O - | tar -xz
cd virt-manager-1.0.1
./virt-manager

Comandos útiles

Mostrar la lista de máquinas en ejecución en el sistema:

virsh -c qemu:///system list

Mostrar todas las máquinas configuradas en el sistema:

virsh -c qemu:///system list --all

En los comandos anteriores, podemos sustituir qemu:///system por quemu:///session para ver las máquinas asociadas a nuestro usuario (ver apartado anterior).

Mostrar lista de tipos de sistemas operativos; esto es necesario saberlo para cuando vayamos a instalar una máquina con virt-install, ya que deberemos especificar el tipo en el momento de la creación:

virt-install --os-variant list

Parar a lo bruto una máquina:

virsh destroy nombre_maquina

Eliminar una máquina y todos sus ficheros asociados (snapshots, ficheros de disco, etc.):

virsh undefine --managed-save --snapshots-metadata --remove-all-storage nombre_maquina

Creación rápida de máquinas comunes

CentOS 5 32 bits:

virt-install --connect qemu:///system -n centos5x32 -r 512 --vcpus=1 --os-variant=rhel5.4 \
--graphics spice --disk path=/var/lib/libvirt/images/centos5x32.qcow2,format=qcow2,size=8 \
-l http://sunsite.rediris.es/mirror/CentOS/5/os/i386 \
-x "lang=es_ES keyboard=es"

CentOS 5 64 bits:

virt-install --connect qemu:///system -n centos5x64 -r 512 --vcpus=1 --os-variant=rhel5.4 \
--graphics spice --disk path=/var/lib/libvirt/images/centos5x64.qcow2,format=qcow2,size=8 \
-l http://sunsite.rediris.es/mirror/CentOS/5/os/x86_64 \
-x "lang=es_ES keyboard=es"

CentOS 6 32 bits:

virt-install --connect qemu:///system -n centos6x32 -r 1024 --vcpus=1 --os-variant=rhel6 \
--graphics spice --disk path=/var/lib/libvirt/images/centos6x32.qcow2,format=qcow2,size=8 \
-l http://sunsite.rediris.es/mirror/CentOS/6/os/i386 \
-x "lang=es_ES keyboard=es"

CentOS 6 64 bits:

virt-install --connect qemu:///system -n centos6x64 -r 1024 --vcpus=1 --os-variant=rhel6 \
--graphics spice --disk path=/var/lib/libvirt/images/centos6x64.qcow2,format=qcow2,size=8 \
-l http://sunsite.rediris.es/mirror/CentOS/6/os/x86_64 \
-x "lang=es_ES keyboard=es"

CentOS 7 64 bits ( no existe versión de 32 bits):

virt-install --connect qemu:///system -n centos7x64 -r 1024 --vcpus=1 --os-variant=rhel7 \
--graphics spice --disk path=/var/lib/libvirt/images/centos7x64.qcow2,format=qcow2,size=8 \
-l http://sunsite.rediris.es/mirror/CentOS/7/os/x86_64 \
-x "lang=es_ES keyboard=es"

Debian 7 32 bits:

virt-install --connect qemu:///system -n debian7x32 -r 512 --vcpus 1 --os-variant debianwheezy \
--graphics spice --disk path=/var/lib/libvirt/images/debian7x32.qcow2,format=qcow2,size=8 \
-l http://ftp.debian.org/debian/dists/wheezy/main/installer-i386/ \
-x "language=es country=ES debian-installer/locale=es_ES.UTF-8 keyboard-configuration/xkb-keymap=es\
    time/zone=Europe/Madrid passwd/make-user=false"

Debian 7 64 bits:

virt-install --connect qemu:///system -n debian7x64 -r 512 --vcpus 1 --os-variant debianwheezy \
--graphics spice --disk path=/var/lib/libvirt/images/debian7x64.qcow2,format=qcow2,size=8 \
-l http://ftp.debian.org/debian/dists/wheezy/main/installer-amd64/ \
-x "language=es country=ES debian-installer/locale=es_ES.UTF-8 keyboard-configuration/xkb-keymap=es \
    time/zone=Europe/Madrid passwd/make-user=false"

Los comandos anteriores tienen el parámetro -x (--extra-args). Estos parámetros se pasan automáticamente al kernel de arranque de instalación del sistema operativo. Con ellos, podemos configurar automáticamente ciertos parámetros que se nos pide durante la instalación (los más usados en los ejemplos anteriores sirven para configurar el idioma, la localización, la distribución del teclado, la zona horaria, o incluso si crear o no un usuario regular en el sistema). También es posible pasar una ruta a un fichero KickStart (Red Hat/CentOS) o Preseed (Debian/Ubuntu) para automatizar completamente la instalación. Más información:

Para especificar un proxy de instalación en los casos anteriores, se deben especificar las siguientes opciones:

  • Para Debian/Ubuntu: mirror/http/proxy=http://[usuario:contraseña@]proxy.dominio.com:3128/
  • Para CentOS/Red Hat: proxy=http://[usuario:contraseña@]proxy.dominio.com:3128/

La opción --graphics spice especificada en los comandos anteriores permite una mejor calidad y mayor rendimiento de los gráficos en la máquina virtual, usando el driver qxl, así como una mejor integración con el host a través del protocolo Spice, permitiendo el cambio de resolución de la máquina virtual según redimensionemos el visor, redirección del sonido, copiar y pegar, etc. En caso de que no se especifique esta opción se usaría una comunicación mediante VNC y un driver Cirrus. Para que el protocolo Spice funcion correctamente en la máquina virtual, deberemos asegurarnos que está instalado el driver gráfico adecuado y el agente de Spice, según lo indicado en el siguiente apartado.

Cambiar Cirrus/VNC por QXL/Spice

Como he comentando antes, el protocolo Spice ofrece un rendimiento mayor y mejor integración con el huésped. Si tenemos alguna máquina virtual creada con las opciones por defecto, podemos actualizarla cambiando las opciones adecuadas. Para ello, con la máquina virtual parada, editaremos su configuración XML y mofificaremos los bloques especificados a continuación:

virsh edit nombre_maquina
    <channel type='spicevmc'>
      <target type='virtio' name='com.redhat.spice.0'/>
      <address type='virtio-serial' controller='0' bus='0' port='1'/>
    </channel>
    <graphics type='spice' autoport='yes'/>
    <video>
      <model type='qxl' ram='65536' vram='65536' heads='1'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>

Tras esto, ya podemos arrancar la máquina virtual y debemos asegurarnos de tener instalado tanto el driver gráfico correspondiente, como el agente de Spice. Para ello, ejecutaremos los siguientes comandos en distribuciones Debian/Ubuntu:

sudo apt-get install xserver-xorg-video-qxl spice-vdagent
sudo update-rc.d spice-vdagent defaults
sudo service spice-vdagent start

Estos otros en distribuciones Red Hat/CentOS con SysV (versiones 6 y anteriores):

sudo yum install xorg-x11-drv-qxl spice-vdagent
sudo chkconfig spice-vdagentd on
sudo service spice-vdagentd start

Y estos otros en distribuciones Red Hat/CentOS con Systemd (versiones 7 y posteriores):

sudo yum install xorg-x11-drv-qxl spice-vdagent
sudo systemctl enable spice-vdagentd
sudo systemctl start spice-vdagentd

Para finalizar, deberemos reiniciar la máquina virtual para que se apliquen los cambios.

Intercambiar entre KVM y VirtualBox

Si se tiene instalado VirtualBox, KVM no se ejecutará con todas las características de virtualización completas, sino que delegará en QEMU (que es mucho más lento), o bien VirtualBox no se ejecutará diciendo que no se han podido cargar sus módulos ( dependiendo del orden de carga de los módulos de KVM o VirtualBox, será uno u otro el que no funcione). Para solventar esto, o bien debemos desinstalar uno de los dos sistemas, o bien debemos desactivar los módulos del otro cuando vayamos a ejecutar un sistema de virtualización.

Para usar KVM:

sudo /etc/init.d/vboxdrv stop
sudo modprobe kvm
sudo modprobe kvm_intel

Para usar VirtualBox:

sudo modprobe -r kvm_intel
sudo modprobe -r kvm
sudo /etc/init.d/vboxdrv start

En mi caso, que tengo en el trabajo un Dell OptiPlex 755, hay que tocar algunas cosas en la BIOS para que funcione correctamente KVM, ya que cuando intentaba cargar el módulo kvm_intel me daba un error de Operation not supported. En esta pregunta de serverfault, que a su vez hace referencia a ésta, indican las opciones de la BIOS que se deben poner para que funcione; en resumen:

  • Security: Execute Disable should be On
  • Performance: Virtualization should be On
  • Performance: VT for Direct I/O Access should be On
  • Performance: Trusted Execution should be Off

Snapshots

Para poder tomar snapshots, el formato de los discos debe ser alguno que sea compatible; si al crear la máquina, no se especifica uno, se crearán con el formato raw, que no los permite; por eso, en todos los comandos anteriores se usa el formato qcow2.

Mostrar los snapshots de una máquina:

virsh snapshot-list nombre_maquina

Tomar un snapshot de una máquina:

virsh snapshot-create-as nombre_maquina "Nombre del snapshot (opcional)" "Descripción del snapshot (opcional)"

Revertir a un snapshot anterior:

virsh snapshot-revert nombre_maquina [nombre_snapshot|--current]

Eliminar un snapshot:

virsh snapshot-delete nombre_maquina [nombre_snapshot|--current] [{--children | --children-only}]

Convertir imágenes de disco a QCOW2

En caso de que tengamos una máquina virtual con un disco en formato raw, no podremos utilizar la funcionalidad de snapshots, como hemos comentado antes. Para solucionar esto, deberemos convertir el fichero de imagen de la máquina a formato qcow2, y luego editar la configuración de la máquina virtual para decirle que hemos cambiado el formato del disco.

Para convertir el formato (se debe hacer con la máquina apagada, y con sudo ya que necesita acceder directamente al disco para leerlo y luego poder crear el nuevo):

sudo qemu-img convert -f raw -O qcow2 /var/lib/libvirt/images/centos7x64.{img,qcow2}

Tras esto, debemos reconfigurar la máquina virtual para indicar el nuevo nombre del fichero y formato del disco (al igual que antes, con la máquina apagada):

virsh edit centos7x64
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/centos7x64.qcow2'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </disk>

Clonar máquinas virtuales

A la hora de clonar máquinas virtuales debemos tener en cuenta varias cosas:

  • Se debe duplicar el disco
  • Se debe generar una nueva dirección MAC para cada una de las tarjetas de red
  • A nivel de sistema operativo:
    • Cambiar la dirección MAC con la nueva en los archivos de configuración (/etc/sysconfig/network-scripts/ifcfg-eth* en Red Hat/CentOS)
    • Se deben eliminar y regerenerar las claves SSH antiguas
    • Se deberían eliminar los usuarios del sistema original
  • Y cualquier cosa más que se nos ocurra

Para realizar todas estas tareas, disponemos principalmente de 2 herramientas:

  • virt-clone: realiza el clonado en sí de la máquina, copiando el disco, y cambiando las direcciones MAC de las tarjetas (a nivel de KVM sólo, no a nivel del sistema operativo virtual).
  • virt-sysprep: permite realizar modificaciones en el sistema operativo para configurarlo correctamente con las nuevas especificaciones (MAC, SSH, etc.).

Desde la aplicación virt-manager es bastante sencillo, pues se realiza en apenas 2 clicks por la interfaz gráfica. Para hacerlo por comandos, realizaremos los siguientes pasos. En primer lugar, clonaremos la máquina en sí (si no especificamos manualmente un disco de destino con la opción --file, se nos creará uno automáticamente con el nombre de a nueva máquina; si no especificamos tampoco una MAC manualmente con el parámetro --mac, se generará una aleatoria automáticamente):

virt-clone --connect qemu:///system --original centos6x32 --auto-clone --name centos6x32-clone

Tras esto, ejecuataremos (virt-sysprep se tiene que ejecutar con sudo o dar permisos de lectura y escritura al usuario actual sobre el archivo de imagen de la máquina virtual, ya que tiene que realizar modificaciones directamente sobre él):

sudo virt-sysprep --connect qemu:///system --domain centos6x32-clone

El comando anterior lanzará una serie de modificaciónes estándar; estas modificaciones se pueden personalizar con los parámetros --enable y --operations; es posible ver la lista de operaciones posibles con el parámetro --list-operations, y ver lo que se haría sobre la máquina sin realmente hacerlo con el parámetro --dry-run.

NOTA: La versión de Ubuntu que utilizo es la 13.10, que tiene una versión bastante antigua del comando virt-sysprep, y no reconoce varias de las opciones anteriores, y tiene este bug; para solventarlo, lo que hago es pasarle manualmente la lista de operaciones a realizar:

sudo virt-sysprep --connect qemu:///system -d centos6x32-clone --enable bash-history,logfiles,hostname,machine-id,net-hwaddr,ssh-hostkeys,ssh-userdir

Hay una herramienta adicional (virt-customize) que permite realizar modificaciones sobre el sistema operativo (al estilo de Ansible, Puppet, Salt, Chef, etc. pero más básico), pudiendo establecer la contraseña de root y de usuarios, instalar paquetes, actualizar el sistema, establecer el nombre de host, etc. Lamentablemente, esta aplicación sólo está disponible a partir de la versión 1.26 de libguestfs, que es bastante posterior a la que hay en Ubuntu. Simplemente, a modo de referencia, el comando funcionaría de la siguiente forma:

sudo virt-customize --connect qemu:///system -d centos6x32-clone --hostname nuevonombre.pruebas.test

Referencias:

comments powered by Disqus