Virtualización con KVM bajo GNU/Linux
Este artículo presenta un resumen de cómo instalar y utilizar la tecnología de virtualización KVM para provisionar y ejecutar máquinas virtuales en Hosts GNU/Linux.
¿Qué es KVM?
La descripción oficial de KVM dice aproximadamente:
KVM (de Kernel-based Virtual Machine) es una solución de virtualización para Linux corriendo sobre hardware x86 que hace uso de las extensiones de virtualización por hardware del procesador (Intel VT o AMD-V).
Con KVM, un host Linux puede ejecutar múltiples máquinas virtuales con Linux o Windows sin ninguna modificación necesaria en estos. Cada máquina virtual tiene hardware virtualizado privado: tarjeta de red, disco, adaptador gráfico, etc.
KVM es parte del kernel desde la versión 2.6.20 y consta de:
- Un módulo del kernel (kvm.ko) que proporciona el core de la infraestructura de virtualización.
- Un módulo específico para cada procesador (kvm-intel.ko o kvm-amd.ko).
Otras partes (algunas de apoyo, otras opcionales) de KVM son:
- libvirt: Una biblioteca para interactuar con las capacidades de virtualización de Linux independientemente de la solución de virtualización que hay debajo (KVM, XEN, etc), con la que arrancar/parar/etc máquinas virtuales.
- virt-manager: Herramienta GUI para la gestión de máquinas virtuales de un host.
- virt-install: script de python desarrollado por RedHat para la provisión desatendida de guests.
- ubuntu-vm-builder: desarrollado por Canonical, permite la provisión desatendida de guests Ubuntu.
- tigervnc / xtightvncviewer: Cliente de VNC, para conectarse a la consola "física" de los guests virtuales remotamente.
- libmigration: Necesaria para disponer de HA entre hosts KVM.
- OpenNebula: Interfaz web para la administración de una infraestructura Cloud ("en la nube") entre hosts KVM y XEN (y, teóricamente, VMWare).
Instalación de KVM
Verificamos si la CPU soporta virtualization por hardware (HVT):
# egrep -c '(vmx|svm)' --color=always /proc/cpuinfo 0 = Nuestra CPU no soporta virtualización por hardware (KVM funcionará, pero más lento) >1 = La CPU sí soporta virtualización por hardware.
Verificamos que estamos utilizando un procesador y kernel de 64 bits. En caso contrario, no podremos levantar máquinas virtuales de 64 bits o con más de 2GB de RAM.
# egrep -c ' lm ' /proc/cpuinfo 0 = CPU de 32 bits. >1 = CPU de 64 bits. # uname -m x86_64 = kernel de 64 bits i386/i486/i586/i686 = kernel de 32 bits
Instalamos los paquetes necesarios para virtualización:
En el caso de CentOS / RedHat:
# rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY* # yum groupinstall Virtualization "Virtualization Client" bridge-utils \ "Virtualization Platform" "Virtualization Tools" # yum install dejavu-lgc-sans-fonts xorg-x11-xauth # yum install tigervnc (if you plan to connect to machines locally) # yum install virt-manager openssh-askpass (Instalará qemu-kvm, qemu-kvm-tools, libvirt, python-virtinst, y virt-manager)
En el caso de Ubuntu / Debian:
# apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils # apt-get install virt-viewer xtightvncviewer # apt-get install virt-manager
Reiniciamos el servidor para asegurarnos de que se arrancan todos los servicios necesarios y que se aplican las reglas de udev para KVM. Esto también permitirá a dbus crear el machine-id. Si no lo hacemos, al arrancar virt-manager obtendremos el siguiente error:
# virt-manager D-Bus library appears to be incorrectly set up; failed to read machine uuid: Failed to open "/var/lib/dbus/machine-id": No such file or directory
Si no podemos reiniciar por algún motivo (aunque es lo recomendado), podemos generar el machine-id a mano con el siguiente comando:
# dbus-uuidgen > /var/lib/dbus/machine-id
A continuación, cargamos en memoria los módulos de kvm y arrancamos libvirtd (si no lo ha hecho ya el sistema tras el reinicio). Para ello cargamos los módulos kvm y kvm_intel o kvm_amd y arrancamos libvirtd. Si es necesario, añadiremos la configuración del sistema necesaria para que se carguen en el arranque.
# modprobe kvm # modprobe kvm_intel # o kvm_adm # lsmod | grep kvm kvm_intel 46589 0 kvm 292815 1 kvm_intel # /etc/init.d/libvirtd start # chkconfig libvirtd on (en CentOS/Redhat)
Verificamos la instalación, comprobando que todo ha levantado correctamente. Lo haremos solicitando el listado de máquinas en ejecución. Si todo está correcto, veremos (inicialmente) un listado de VMs vacío:
OK: # virsh -c qemu:///system list Id Name State ---------------------------------- ERROR: # virsh -c qemu:///system list libvir: Remote error : Permission denied error: failed to connect to the hypervisor
(En ese caso específico de error, verifica que existen permisos de escritura de grupo sobre /var/run/libvirt/libvirt-sock y que hemos reentrado en el sistema con el usuario ya dentro del grupo concreto).
SELINUX / PolicyKit
Puede resultar conveniente desactivar SELINUX en el host KVM. Si decidimos no desactivarlo, pueden ser necesarios cambios para mover la ubicación por defecto de las máquinas virtuales (normalmente /var/lib/libvirt/images). Si, por ejemplo, queremos mover los datos a /vm/, deberemos (por ejemplo, en CentOS):
# yum install policycoreutils-python # semanage fcontext -a -t virt_image_t "/vm(/.*)?" restorecon -R /vm
Si queremos acceder a libvirt (una vez instalado) con algún usuario no privilegiado, tendremos que hacer cambios en PolicyKit:
# vim /etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla [libvirt Management Access] Identity=unix-user:USER_NAME_HERE Action=org.libvirt.unix.manage ResultAny=yes ResultInactive=yes ResultActive=yes (En lugar de unix-user:USER_NAME, podemos usar Identity=unix-group:GROUP_NAME) # /etc/init.d/libvirtd restart
Configuración de red
Lo normal si planeamos prestar servicios con las máquinas virtuales bajo KVM es que debamos reconfigurar el host para que el interfaz de red con el direccionamiento donde se prestarán estos servicios haga de bridge para el tráfico de las máquinas virtuales.
Tanto en RedHat / CentOS como en Ubuntu, esto pasa por instalar el paquete bridge-utils y por reconfigurar los interfaces de red para pasar la configuración de red del interfaz en cuestión a un interfaz "br0" (br1, br2…) que será el que hará el bridging.
En el caso de RedHat / Centos:
# yum install bridge-utils # cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-br0
Modificamos ifcfg-eth0 y comentamos BOOTPROTO, IPADDR, PREFIX, GATEWAY, DNS1, DNS2, etc y añadimos BRIDGE=br0. Modificamos ifcfg-br0 y mantenemos las anteriores variables añadiendo TYPE=Bridge en lugar de TYPE=Ethernet:
# cat /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 HWADDR=xx:yy:zz:aa:bb:cc ONBOOT=yes BRIDGE=br0 # cat /etc/sysconfig/network-scripts/ifcfg-br0 DEVICE=br0 TYPE=Bridge BOOTPROTO=static ONBOOT=yes IPADDR=192.168.1.3 NETMASK=255.255.255.0 (...) # service network restart
En el caso de Ubuntu / Debian:
Lo primero que tenemos que hacer es asignar la "capability" CAP_NET_ADMIN al usuario que va a gestionar las máquinas virtuales (si no es root) ya que desde el kernel 2.6.18 se requieren para usar TUN/TAP.
# apt-get install libcap2-bin Para 64 bits: # setcap cap_net_admin=ei /usr/bin/qemu-system-x86_64 Para 32 bits: # setcap cap_net_admin=ei /usr/bin/qemu # cat /etc/security/capability.conf: cap_net_admin USER-NAME-HERE
Después, editamos /etc/network/interfaces y renombramos eth0 como br0:
auto lo iface lo inet loopback auto eth0 iface eth0 inet manual auto br0 iface br0 inet static address 192.168.1.3 network 192.168.1.0 netmask 255.255.255.0 broadcast 192.168.1.255 gateway 192.168.1.1 bridge_ports eth0 bridge_stp off bridge_fd 0 bridge_maxwait 0
Si queremos usar DHCP:
auto lo iface lo inet loopback auto eth0 iface eth0 inet manual auto br0 iface br0 inet dhcp bridge_ports eth0 bridge_stp off bridge_fd 0 bridge_maxwait 0
Después, reiniciamos la red:
# /etc/init.d/networking restart
Si detectamos una pequeña parada en el host KVM cuando arrancamos o detenemos un guest, deberemos añadir lo siguiente a la configuración de br0:
post-up ip link set br0 address xx:yy:zz:aa:bb:cc
Reemplazando xx:yy:zz:aa:bb:cc por la MAC del adaptador ethernet físico qu forma parte del bridge.
NOTA para todas las versiones de Linux: El Bridging podría no funcionar si el dispositivo físico de red es un dispositivo wireless, ya que no todos los dispositivos wireless soportan bridging.
Creación de máquinas virtuales
Para crear las máquinas virtuales tenemos diferentes alternativas:
- virt-manager: interfaz gráfica de usuario para la gestión y creación de las máquinas virtuales, tanto localmente en el propio host (con ssh + X11 Forwarding) como en remoto.
- virt-install / ubuntu-vm-builder: scripts para provisionar una nueva máquina completa incluyendo la instalación de la misma y la configuración de parámetros como networking, hostname, memoria, procesadores, paquetes instalados, etc.
- virsh / qemu-img: Creación de discos y máquinas virtuales manualmente, utilizando los comandos apropiados para ello.
[EN PREPARACION]