KVM “a pelo”


QEMU-KVM (en adelante KVM) es el sistema de virtualización completa utilizado por defecto en sistemas GNU/Linux. KVM proporciona principalmente el módulo del kérnel kvm.ko que está integrado desde hace años en el kérnel Linux y utiliza las herramientas del espacio de usuario del proyecto QEMU (de ahí que el nombre correcto del sistema de virtualización completo sea QEMU-KVM), que se instalan con el paquete qemu-kvm en sistemas Debian.

Es muy habitual no utilizar KVM directamente, sino hacerlo a través de libvirt, que es una API de virtualización y un proyecto independiente, pero en este caso no haremos uso de libvirt porque precisamente nos interesa ir modificando los parámetros manualmente para ir entendiendo cómo funcionan.

El objetivo de esta entrada es explicar con detalle la configuración de un escenario sencillo de KVM para hacer prácticas de redes, con algunas adaptaciones y modificaciones para utilizar en exposiciones en clase a través de un proyector.

La expresión “a pelo” hace referencia a la acción de montar a caballo directamente, sin una silla de montar. No se me ocurre mejor símil para la situación que vamos a presentar, en la que vamos a interactuar con KVM directamente sin utilizar libvirt por medio.

Virtualización por hardware

Para poder utilizar KVM es preciso que el procesador del hipervisor, equipo donde se van a ejecutar las máquinas virtuales, incluya extensiones de virtualización por hardware, una característica bastante habitual hoy en día pero que es preciso comprobar, para lo que ejecutamos la siguiente instrucción en nuestro equipo:

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

Si nuestro procesador no tiene extensiones de virtualización por hardware no devolverá ningún resultado, en caso contrario, veremos una o varias líneas destacando vmx o svm en función de que tengamos un procesador Intel o AMD.

Nota: Si no tenemos posibilidad de utilizar una máquina con extensiones de virtualización por hardware, todo lo presentado aquí podríamos hacerlo utilizando el ejecutable “qemu-system-x86_64” (o “qemu-system-i386” en sistemas de 32 bits) en lugar de kvm, con lo que utilizaríamos simplemente QEMU, que es totalmente funcional, aunque con un rendimiento significativamente menor.

Configuración previa de la red en modo “bridge”

En mi opinión, una de las cosas más odiosas de utilizar sistemas de virtualización como VMware o Virtualbox es que utilizan sus propios mecanismos de gestión de las redes que “facilitan” el trabajo a los usuarios pero que a la vez ocultan el modo en que lo hacen, impidiendo en muchos casos hacer modificaciones a medida. A diferencia de éstos, KVM utiliza los mecanismos nativos de sistemas GNU/Linux, lo que lo convierte en una herramienta muy útil para el objetivo que tenemos que es aprender cómo funcionan las redes en GNU/Linux.

El punto de partida en una máquina anfitriona con Debian Jessie instalado, conectada a través de la interfaz eth0 a una red Ethernet y con Network-Manager deshabilitado (puesto que nos interesa hacer modificaciones de las interfaces de red manualmente), de manera que la conexión de red con el exterior está definida para configurarse automáticamente con DHCP:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

Vamos a modificar esta configuración inicial instalando el paquete “bridge-utils” que nos proporciona las herramientas para definir los conocidos “bridge-linux” que son bridges por software muy sencillos y ampliamente utilizados hasta ahora. Una vez instalado el paquete “bridge-utils”, echamos abajo la interfaz eth0 (con ifdown) y realizamos la siguiente modificación en /etc/network/interfaces:

auto lo
iface lo inet loopback

auto br0
iface br0 inet dhcp
	bridge_ports eth0

De manera que la interfaz eth0 pasa a ser el puerto que nos conecta nuestro bridge software con el exterior y al que conectaremos posteriormente las máquinas virtuales que queramos que estén conectadas a la misma red que nuestro equipo anfitrión. Levantamos br0 y comprobamos el estado de br0:

root@host:~# ifup br0

root@host:~# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.902b34bfb129       no              eth0

Y ahora es el dispositivo br0 el que tiene asociada la dirección IP en el equipo anfitrión:

root@host:~# ip l
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0:  mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 1000
    link/ether 90:2b:34:bf:b1:29 brd ff:ff:ff:ff:ff:ff
3: br0:  mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 90:2b:34:bf:b1:29 brd ff:ff:ff:ff:ff:ff

root@host:~# ip a
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
    link/ether 90:2b:34:bf:b1:29 brd ff:ff:ff:ff:ff:ff
3: br0:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 90:2b:34:bf:b1:29 brd ff:ff:ff:ff:ff:ff
    inet 172.22.9.64/16 brd 172.22.255.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::922b:34ff:febf:b129/64 scope link 
       valid_lft forever preferred_lft forever

Proceso de instalación y creación de una máquina virtual

Vamos a instalar una máquina virtual con un sistema Debian Jessie mínimo, por lo que nos descargamos la “ISO de Debian Netinst” y creamos con qemu-img (del paquete qemu-utils) un fichero de imagen que tendrá una tamaño máximo de 10 GiB y que contendrá el disco duro que va a utilizar la máquina virtual:

user@host:~$ qemu-img create -f qcow2 jessie.qcow2 10G
Formatting 'jessie.qcow2', fmt=qcow2 size=10737418240 encryption=off cluster_size=65536 lazy_refcounts=off

El siguiente paso consiste en crear una interfaz de red virtual utilizando un dispositivo tap, asociar el dispositivo al usuario que va a lanzar la máquina virtual, conectar el dispositivo al bridge br0 y activar tap0 (el nombre de la interfaz tap creada):

root@host:~# ip tuntap add mode tap user user

root@host:~# ip tuntap list
tap0: tap UNKNOWN_FLAGS:800 user 1000

root@host:~# brctl addif br0 tap0

root@host:~# ip l set dev tap0 up

Hay otras formas alternativas de configurar la red en QEMU, incluyendo la más sencilla User Networking (SLIRP), pero preferimos en este caso utilizar interfaces gestionadas manualmente por nosotros porque precisamente queremos modificarlas y adaptarlas posteriormente.

Por último, utilizamos la siguiente instrucción para generar una dirección MAC aleatoria para asociar a la interfaz de red virtual:

user@host:~$ MAC0=$(echo "02:"`openssl rand -hex 5 | sed 's/\(..\)/\1:/g; s/.$//'`)

user@host:~$ echo $MAC0
02:57:a4:4d:e3:f3

Ya podemos levantar nuestra máquina virtual con el usuario normal utilizando la “sencilla” instrucción:

user@host:~$ kvm -m 512 -hda jessie.qcow2 \
-cdrom debian-8.3.0-amd64-netinst.iso \
-device virtio-net,netdev=n0,mac=$MAC0 \
-netdev tap,id=n0,ifname=tap0,script=no,downscript=no

Explicación línea a línea:

  1. Utilizamos el ejecutable “kvm” que es equivalente a “qemu-system-x86_64 -enable-kvm”, asignamos 512 MiB de RAM a la máquina virtual y hacemos que utilice como disco duro el fichero de imagen jessie.qcow2.
  2. Asociamos como CD-ROM la ISO de Debian
  3. Creamos en la máquina virtual un dispositivo de red virtio, denominado n0 y con la dirección MAC anteriormente generada.
  4. Asociamos el dispositivo n0 de la máquina virtual con la interfaz tap0 que existe en el anfitrión, no utilizando ningún tipo de script al levantar ni al bajar dicha interfaz.

Al lanzar la instrucción anterior aparecerá una ventana mostrando el instalador de Debian:

kvm1

Procedemos a realizar la instalación como habitualmente y la máquina ya estaría preparada para su uso. Como el fichero de imagen ha ido aumentando su tamaño a medida que se realizaba la instalación, podemos aprovechar la funcionalidad de compresión que incluye qemu-img para reducirlo y hacer el fichero más portable (en este caso pasamos de una imagen de 1.7 GiB a otra de 598 MiB):

user@host:~$ qemu-img convert -O qcow2 -c jessie.qcow2 jessie-min.qcow2

Utilizar imágenes comprimidas de qcow2 no es una buena idea en general porque tienen peor rendimiento, pero en este caso vamos a utilizarla como una imagen base, por lo que no va a modificarse y no tiene problemas de rendimiento.

Aprovisionamiento ligero con imágenes qcow2

Una funcionalidad muy interesante que tienen las imágenes qcow2 es lo que se denomina aprovisionamiento ligero (“thin provisioning”) que permite utilizar la misma imagen base para varias máquinas virtuales y crear rápidamente nuevas máquinas virtuales sin tener que instalar desde cero:

user@host:~$ qemu-img create -b jessie-min.qcow2 -f qcow2 jessie1.qcow2
Formatting 'jessie1.qcow2', fmt=qcow2 size=10737418240 backing_file='jessie-min.qcow2' encryption=off cluster_size=65536 lazy_refcounts=off 

user@host:~$ qemu-img info jessie1.qcow2 
image: jessie1.qcow2
file format: qcow2
virtual size: 10G (10737418240 bytes)
disk size: 196K
cluster_size: 65536
backing file: jessie-min.qcow2
Format specific information:
    compat: 1.1
    lazy refcounts: false

La idea detrás de esta funcionalidad es que las máquinas virtuales que se vayan a utilizar no utilicen nunca la imagen base, sino que se crea para ellas un nuevo fichero de imagen, que “comparte” una imagen base y que realmente registra sólo las modificaciones que vaya teniendo a medida que va cambiando.

Tarjeta gráfica QXL y SPICE

Cuando hemos arrancado la máquina virtual para la instalación se ha utilizado por defecto SDL que emula una interfaz estándar VGA de 640×480 píxeles. A continuación vamos a describir los pasos que se pueden dar para manejar una resolución diferente utilizando un dispositivo QXL y conectándonos a través de la red con SPICE, que es una alternativa al clásico VNC. Siguiendo los pasos de la documentación de SPICE, le pasamos por comandos una tarjeta gráfica QXL y habilitamos la conexión por spice desde localhost a través del puerto 5900/tcp:

user@host:~$ kvm -m 512 -hda jessie1.qcow2 \
-device virtio-net,netdev=n0,mac=$MAC0 \
-netdev tap,id=n0,ifname=tap0,script=no,downscript=no \
-vga qxl -spice port=5900,addr=127.0.0.1,disable-ticketing

Y para conectarnos a esa máquina virtual lo haremos con el cliente spice (instalamos en el anfitrión el paquete spice-client):

spicec -h 127.0.0.1 -p 5900

Que nos mostrará una ventana como la siguiente (sin ningún cambio aparente respecto a la situación anterior):

spice

Sin embargo ahora la máquina virtual tiene una tarjeta gráfica que sí soporta múltiples resoluciones, por lo que podemos cambiarla editando el fichero /etc/default/grub de la máquina virtual y añadiendo las siguientes líneas (se puede seleccionar cualquiera de los modos soportados por el dispositivo QXL):

GRUB_GFXMODE=1280x768x32
GRUB_GFXPAYLOAD_LINUX=keep

Actualizamos los cambios en GRUB y reiniciamos la máquina virtual:

root@guest:~# update-grub
...
root@guest:~# reboot

Modificando la fuente de la consola

Puesto que uno de los objetivos es utilizar esta máquina virtual en una clase a través de un proyector, nos interesa utilizar una fuente mayor y con más contraste que la habitual, para lo que ejecutamos en la máquina virtual:

root@guest:~# dpkg-reconfigure console-setup

Y vamos contestando a las diferentes preguntas de debconf:

  • Codificación: Mantenemos UTF-8
  • Conjunto de Caracteres: Mantenemos Latino1 y Latino5
  • Tipo de letra: Cambiamos a TerminusBold
  • Tamaño del tipo de letra: Escogemos una mayor que la 8×16, en nuestro caso 14×28

Y tendremos una máquina virtual con una resolución modificada que podemos utilizar sin problemas a través de un proyector:

spice2

Nota:Manuel Alcocer, ha escrito un script que automatiza la creación de esta máquina virtual y lo ha colgado en Github

, , , ,

  1. #1 por antonioruiz1974 el 31-03-16 - 4:17 pm

    Reblogueó esto en antonioruiz1974.

    Me gusta

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: