jueves, 24 de julio de 2014

KVM y Open vSwitch (OVS): Componentes, ventajas y configuración de conectividad básica para máquinas virtuales

"En esta entrada se repasan los componentes del Open vSwitch, sus ventajas frente a los bridges, y las posibilidades de configuración que ofrece , tanto en un despliegue standalone, como cuando se integra con Controladores SDN externos"


El Open vSwitch (OVS) es una implementación Software de switch virtual programable, el cual se puede utilizar para proporcionar conectividad a las máquinas virtuales, sustituyendo a bridges y bondings (ver "KVM: bridges, bondigs y VLANs con VMs (bridge mode & routed mode)").

Puede funcionar en dos modos: cómo un switch tradicional (resolución de MACs), o gestionado por un Controller (configuración de flujos). Este último es el que puede parecer más interesante, al poder utilizarse para desplegar una plataforma SDN, e integrar esta con otras herramientas de gestión del Data Center (por ejemplo los orquestadores de virtualización) para aportar soluciones escalables a la hora de implementar arquitecturas Cloud.

Como se ha dicho, el OVS es un elemento interesante para el despliegue de plataformas Cloud, ya que proporciona la posibilidad de incorporar las ventajas de las redes basadas en flujos programables (SDN), y es por ello que varios desarrolladores de Software lo han utilizado como "base" para generar nuevos productos destinados a proporcionar funcionalidades avanzadas de red en entornos Cloud. Un ejemplo de esto se puede ver en el componente Virtual Routing & Switching (VRS) de Nuage.

En esta entrada no se desarrollarán conceptos de conectividad avanzada (VXLAN, túneles GRE, etc) ya que lo que se pretende es dar una visión introductoria al OVS. Este tipo de configuraciones se revisarán en una futura entrada.

Descripción del Open vSwitch


El Open vSwitch dispone de un diseño de mayor complejidad que los bridges, siendo este compuesto por varios componentes. Mientras que los bridges solo se ejecutan en el espacio del kernel del Host, el OVS, al necesitar un código más complejo que los bridges para poder proporcionar todas las funcionalidades avanzadas, hace uso no solo del espacio del kernel, sino también del user space, en concreto para realizar la decisión de cómo procesar los paquetes "nuevos".

Hay que recordar que el kernel y el user space son dos separaciones lógicas de la memoria que hacen los Sistemas Operativos para proteger el sistema ante fallos o ataques. En el espacio del kernel se ejecutarían los módulos y los drivers del sistema, mientras que en el espacio de usuarios se encontraría la mayoría del Software.

Un paquete "nuevo" es aquel tipo de paquete de un flujo del cual no se ha realizado todavía ninguna decisión de forwarding, y por tanto dicha decisión no pude encontrarse en la caché. Cuando un paquete de un nuevo flujo llega al OVS, este realizará una decisión bajo el user space, pero los sucesivos paquetes de ese flujo serán encaminados directamente por el kernel (más rápido).

Componentes del Open vSwitch

Los componentes del OVS son tres:
  • ovsdb-server
  • ovs-vswitchd
  • openvswitch_mod.ko

Los dos primeros se ejecutan en el user space, mientras que el tercero lo hace en el espacio del kernel.

El ovsdb-server es un servidor ligero de bases de datos. En la base de datos que gestiona se encuentran todos los parámetros de configuración del OVS, los cuales se almacenan de forma que dicha información se mantenga tras un reinicio del Host. 

A modo de ejemplo, algunas de las tablas que existen en esa base de datos, las cuales contienen la configuración de su elementos correspondientes, serían Bridge, Port, Interface, Flow_Table, QoS, Mirror, Controller, ...

Esta base de datos puede ser modificada desde elementos externos utilizando el protocolo Open vSwitch Database Management Protocol (OVSDB), el cual será tratado más adelante en el punto sobre gestión externa del OVS.

El ovs-vswitchd es el proceso que implementa las funcionalidades de switch (junto con el módulo del kernel openvswitch_mod.ko). Implementa el comportamiento ante VLANs, el bonding o la monitorización. 

Este proceso es el Core del OVS, y se ha de comunicar con los otros dos componentes. El proceso ovs-vswitchd debe comunicarse con el ovsdb-server para poder guardar y aplicar las configuraciones almacenadas en la base de datos albergada por el servidor ovsdb-server. Esta comunicación se realiza mediante sockets Unix con el protocolo OVSDB.

El módulo del kernel openvswitch_mod.ko también debe ser contactado por el demonio ovs-vswitchd para poder tomar decisiones sobre los nuevos flujos que reporta el kernel (como se ha visto anteriormente). Para ello utiliza el protocolo netlink el cual permite comunicar el espacio del kernel con el del usuario.

El módulo del kernel openvswitch_mod.ko es quien maneja el packet switching. Ha sido designado para ser muy simple y rápido, por lo que no puede ser modificado mediante Openflow, ni lleva a cabo el borrado de flujos, tan solo maneja una memoria caché en la que tiene determinado qué hacer con cada flujo y, de no conocerlo, contactará con el proceso ovs-vswitchd mediante netlink para saber qué hacer con él.

Los anteriores componentes, así como la relación entre ellos se puede ver en el siguiente esquema:



Figura 1 - Componentes del Open vSwitch

Gestión del Open vSwitch
Sobre los OVS se puede realizar una gestión directamente sobre él, o incluir un elemento controlador central (Controller) utilizando el modo de funcionamiento de OVS de flujos configurables. Como se puede imaginar, se recomienda disponer de un Controller, ya que de esta manera se podrán utilizar las ventajas asumidas de los despliegues SDN (ver "Ideas básicas sobre Software Defined Network").

Si no se dispone de Controller (modo de funcionamiento standalone), se pueden utilizar una serie de herramientas:
  • Gestión de ovsdb-server: se gestiona mediante ovsdb-client
  • Gestión de ovs-vswitchd: Con ovs-vsctl se puede manipular la configuración y con ovs-appctl también se pueden modificar ciertos parámtros de funcionamiento como por ejemplo el logging.
  • Gestión de openvswitch_mod.ko: se puede modificar la configuración del módulo del kernel directamente con ovs-dpctl y mostrar los flujos cacheados con ovs-ofctl.

Con un Controller que centralice la gestión de flujos, se hará uso de los protocolos de gestión externa del OVS: Openflow y OVSDB, los cuales permitirán sacar el máximo partido al OVS en una topología de virtualización compleja.

El protocolo Openflow permite consultar y modificar las tablas de flujos del proceso ovs-vswitchd, haciendo posible que el Software residente en el controller tome decisiones  atendiendo a una serie de variables (recogidas de orígenes diversos), y "reprograme" dinámicamente el comportamiento del OVS con este protocolo, para que los paquetes sean reenviados en consecuencia a uno u otro puerto.

Por otro lado, el protocolo Openflow permite modificar la tabla de flujos, pero no es capaz de cambiar la configuración de un dispositivo, por ejemplo deshabilitando un interfaz, por lo que para todas las gestiones que no estén directamente relacionadas con la modificación de las tablas de flujos se utilizará el protocolo OVSDB. 

El protocolo OVSDB management protocolcomo se ha visto, permite consultar y modificar la configuración del OVS, permitiendo un medio de reprogramar las variables de la base de datos interna, realizando de esta manera tareas como por ejemplo:
  • Creación y modificación de puertos
  • Creación de datapaths 
  • Configuración de los controllers que gestionan la plataforma
  • Recolección de estadísticas
  • Configuración de túneles
  • Configuración de QoS
  • etc...

En este esquema se muestran las comunicaciones externas del Open vSwitch cuando existen elementos controladores:


Figura 2 - Comunicaciones del OVS con el Controller


Ventajas del Open vSwitch

Las ventajas de este sustituto de los bridges a la hora de dar conectividad a las máquinas virtuales son varias. Algunas de ellas se pueden encontrar en ambos métodos de funcionamiento (standalone y con Controller), mientras que otras son exclusivas de la utilización de flujos programados regidos por Controller:
  • Incorporación de funcionalidades de red similares a los switches Hardware
El OVS, a parte de las funcionalidades L2 y L3, VLAN tagging (por puerto) y agregación de enlaces, también provee  funcionalidades propias de un switch Hardware configurable, como puedan ser SPAN/RSPAN, Netflow/sFlow, QoS, Túneles GRE, etc.

Las configuraciones de VLANs y agregados se realizan directamente sobre el OVS, no sobre terceros elementos (bondings, un bridge por VLAN,...) asemejándose de este modo a los switches Hardware.

  • OVSDB y Openflow (OVS en modo flujos configurables)
Si el KVM es parte de un Cloud, hay que tener en cuenta que estas infraestructuras son muy dinámicas, con lo que los cambios en la red se producen numerosas veces y ante multitud de eventos. Gracias al OVS y la utilización de Controller SDN, se facilita el responder dinámicamente a esa gran tasa de cambios que se producen en la infraestructura, modificando la configuración de red

Como se ha visto, el OVS mantiene una la base de datos llamada OVSDB (Open vSwitch Network State Database), la cual alberga toda la información distribuida de la configuración y el estado de los OVS de una infraestructura. Utilizando la información contenida en esa base de datos, ser puede realizar triggers de numerosos aspectos de red más allá de los tradicionales, como por ejemplo el movimiento de máquinas virtuales, de modo que las herramientas de orquestación puedan conocer el estado de la Cloud y utilizar esa información para modificar, mediante el Controller SDN, el comportamiento de reenvío de paquetes dentro de los flujos con Openflow

Con OVSDB, aportando una visibilidad general pormenorizada del estado, y Openflow, con el que se pueden realizar casi cualquier reconfiguración del plano de forwarding que se desee, el Open vSwitch (en modo de funcionamiento por flujos) proporciona los medios para que capas de control/gestión superiores manejen las modificaciones necesarias en la red como respuesta a los cambios que se producen dinámicamente en los entornos virtualizados. Estas mismas modificaciones dinámicas serían imposibles de trasladar a una arquitectura en la que únicamente se hubiesen utilizado bridges en la conectividad de máquinas virtuales.

También, gracias a la base de datos OVSDB, el estado del puerto de red de una máquina virtual puede ser fácilmente migrado junto con la máquina.

El Open vSwitch funcionando por flujos, a su vez, también soporta algunas de las últimas innovaciones desarrolladas para los Data Centers Multitenant, incluso mejora la escalabilidad de las VXLAN. Para explicar esto último hay que recordar que la implementación clásica de VXLAN (por parte de VMware), no dispone de un plano de control, y para el auto-descubrimiento de los Host integrantes de la VXLAN utiliza multicast, lo cual plantea diferentes problemas, desde la necesidad de una arquitectura de red que soporte multicast extremo a extremo, como posibles problemas de recursos cuando se escala a un elevado número de nodos y máquinas virtuales, ya que se ha de hacer flooding (multicast) de las direcciones MAC de estas.

Como ya se comentó (ver "TRILL, SPB, VXLAN, NVGRE, EVI, OTV, EVB, VNTag: nuevas soluciones para antiguos problemas") la problemática de la falta de un plano de control puede ser solventada mediante la utilización de Controladores SDN, los cuales puedrán utilizar Openflow y OVSDB.


  • Offloading de procesamiento de paquetes a Hardware
Una ventaja añadida de Open vSwitch es que está diseñado para poder realizar el procesamiento en Hardware, es decir, que puede realizar un offloading del procesamiento de paquetes a las NICs de los Host KVMs en los que residen, en lugar de hacerlo por Software, con la consiguiente mejora del rendimiento. Ya hay algunos fabricantes, como Broadcom, con los que conseguir este offloading.

  • Compatibilidad con Software basado en bridges
En el caso de que se necesitase hacer compatible el OVS con algún Software basado en bridges (por ejemplo el Virt-manager), esto podría ser llevado a cabo configurando el Open vSwitch de manera que pueda emular el comportamiento de un bridge ("fake bridge") frente a las VLANs. De este modo se contemplaría un bridge por cada VLAN (como se vió en "KVM: bridges, bondigs y VLANs con VMs (bridge mode & routed mode)"), en lugar del comportamiento normal en el cual, dentro de un mismo OVS (bridge), cada puerto tiene una configuración propia (un puerto de acceso a cierta VLAN o un puerto "trunk" 802.1q), del mismo modo que se hace en un switch tradicional.


Este sería un esquema comparativo de la utilización de OVS con fake bridges para proporcionar conectividad de VLANs frente a la configuración "normal":



 Figura 3 - Comparativa de despliegue normal frente a la utilización de fake bridges

Para configurar estos "fake bridges" se utilizará las herramienta ovs-vsctl vista anteriormente, y se tratará cada "fake bridge" como si de bridges tradicionales se tratasen.


Configuración del Open vSwitch

Para la configuración de los bridges se disponían de tres métodos: el manual, la utilización de herramientas CLI como las proporcionadas por libvirt, y el uso de herramientas GUI (ver "KVM: bridges, bondigs y VLANs con VMs (bridge mode & routed mode)"). Para la configuración del OVS se dispone, en algunos casos, de ciertas integraciones con el Sistema Operativo que permiten una configuración puramente manual (generando, por ejemplo, ficheros ifcfg-xxx en sistemas RHEL), no obstante se prefiere a estas el uso de herramientas CLI (ovs-vsctlovs-appctl, etc) así como la utilización de Openflow y OVSDB por parte de los Controllers.


La API de libvirt también es útil en los despliegues en los que exista el OVS, configurando las conectividades de las máquinas virtuales al OVS utilizando los XML. Los nombres de los puertos de las vNICs de las máquinas virtuales cambian en el tiempo (lo cual puede ser un problema a la hora de configurar el OVS) y libvirt puede hacer un trabajo de mediador necesario entre el OVS y la configuración de los puertos, haciendo transparentes estos cambios, con lo que se simplifica la gestión y configuración.

Como se ha visto, las modificaciones de configuración del OVS se hacen sobre una base de datos. Esta base de datos tiene una serie de tablas, sobre las que existen variables con unos posibles valores predeterminados. Para conocer los nombres de las tablas, de las variables y de sus posibles valores se puede consultar la documentación facilitada por la página openvswitch.org.

A continuación se muestran algunos aspectos interesantes de la configuración, aunque existen multitud de configuraciones adicionales (spanning-tree, Sflow, port status, ...) que pueden ser consultados en la documentación de openvswitch.org.

Instalación del Open vSwitch

La instalación se puede llevar a cabo mediante paquetes precompilados con yum, apt-get, etc o bajando la última versión del código y compilándolo uno mismo, lo cual es recomendable para poder disfrutar de las últimas funcionalidades y correcciones de Bugs.

Si se opta por la descarga del fichero con la última versión se podrá comprobar cómo dentro de él (es un .tar) existen varios ficheros de texto nombrados como "INSTALL" e "INSTALL.XXX". En ellos se describen los pasos para instalar correctamente el OpenvSwitch en cada uno de los Sistemas Operativos soportados (en los ejemplos de más abajo se utilizó el procedimiento de INSTALL.RHEL).

Tras la instalación propiamente dicha, se crearán los bridges que utilizará el proceso ovs-vswitchd para realizar las funciones Core dentro del userspace, tal y como se explicó anteriormente (ver ejemplo de configuración más abajo). 

Incorporación de interfaces al Open vSwitch

La vinculación de las interfaces al OVS se puede hacer por dos métodos. El primero, y preferido, es la utilización de las herramientas de gestión propias del Open vSwitch (como ovs-vsctl). Un ejemplo para incluir una interfaz sería el siguiente (ovsbr1 es el nombre del bridge vinculado al OVS):

ovs-vsctl add-port ovsbr1 eth4

Open vSwitch también proporciona una segunda vía de  configuración mediante la integración con el Sistema Operativo (por ejemplo en los sistemas tipo RHEL creando ficheros "ifcfg-xxx"). Para los Sistemas Operativos en los que esta integración sea posible, dentro del propio fichero .tar, también existirán los archivos de texto correspondientes en los que se explican las posibilidades de esta vía opcional (en el caso de los sistemas RHEL el fichero se encuentra en rhel/README.RHEL). El mismo ejemplo de introducción de un interfaz, utilizando la integración con los ficheros de sistema, sería el siguiente:

vi /etc/sysconfig/network-scripts/ifcfg-eth4


DEVICE=eth4
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=ovsbr1
BOOTPROTO=none
HOTPLUG=no


Se recomienda el primer método ya que es independiente del Sistema Operativo en el que se instale y porque incluye todos los parámetros posibles de configuración (no están todos en las integraciones con los ficheros de sistema).

Configuración de bondings

Del mismo modo que para la incorporación de interfaces, para la configuración de bondings también existen los dos métodos: el uso de las herramientas de OVS y la utilización de la integración con el SO.


Los modos de bonding soportados son los siguientes:
  • Balanceo SLB: Se balancea respecto a la MAC origen y periódicamente se hace un re-balanceo. No necesita configurar nada en el switch físico que conecta las interfaces externas del Host, ni siquiera un agregado de enlace, siempre y cuando el switch permita varias MACs por puerto físico. Es recomendable conectarlo al mismo switch para que no exista pérdidas de paquetes en los re-balanceos.
  • Activo/Backup: En este caso no existe balanceo, hay un enlace que es activo y el resto son backups que entrarán en funcionamiento en el caso de la necesidad de un failover. Esta configuración se puede utilizar sin problemas cuando se conectan los interfaces externos a diferentes switches físicos y por supuesto no es necesario configurar ningún agregado en estos. 
  • Balanceo TCP: Se balancea atendiendo a parámetros L2. L3 y L4 de los paquetes TCP. En este caso si se necesita la configuración de un agregado de enlace LACP en los switches físicos que conectan al Host (todos los enlaces de un agregado LACP a un mismo switch físico o a un stack físico o virtual).

Se recomienda el balanceo LACP por los mismos motivos que los especificados en "KVM: bridges, bondigs y VLANs con VMs (bridge mode & routed mode)". Además, se puede configurar que, en el caso de fallar la negociación LACP, automáticamente se pase al funcionamiento activo/backup.

También se puede configurar cómo se realiza la detección de la necesidad de acometer un failover (o poner un interfaz como "caído"). Por defecto se detecta el estado físico de la interfaz (detección de la portadora o "carrier"), pero también se puede configurar la detección errores, no solo el estado de la interfaz, si se configura la monitorización del MII (Media Independent Interface). Se podrá ver un ejemplo de configuración más adelante.

Configuración de VLANs

Los puertos de OpenvSwtich pueden ser configurados con cuatro modos diferentes de tratamiento de los tags de VLANs. Alguno de ellos podrían llevar a confusión teniendo en cuenta cómo funcionan habitualmente los switches físicos:
  • Modo trunk: En la entrada de estos puertos se esperan paquetes con tags de las VLANs definidas (si no está definida el paquete se desecha) y si llega un paquete sin tag lo incluirá en la "VLAN 0". En la salida de estas interfaces, todos los paquetes irán con la tag de su VLAN, menos los paquetes de la VLAN 0 que se enviarán sin tag.
  • Modo acceso: Es un puerto que transmite los paquetes de una VLAN determinada, pero ni en su salida ni su entrada los paquetes serán marcados con un tag. Si llega a este tipo de puerto un paquete con tag, este será descartado. 
  • Modo "native-untagged": En la entrada se esperan paquetes con tag y, en caso de que llegue un paquete sin tag, el OVS lo tomará como parte de la VLAN asignada como nativa (ha de ser definida por configuración). La salida del puerto serán paquetes con tag menos el tráfico de la VLAN nativa que se enviará sin tag.
  • Modo "native-tagged": Este modo es igual que el modo native-untagged con la excepción de que los paquetes de salida de la VLAN nativa sí que se enviarán con tag, es decir,  que un paquete que se recibe en el puerto sin tag se destina a la VLAN nativa, pero cuando el paquete de la VLAN nativa sale por el puerto (por ejemplo la respuesta al anterior paquete), a este se le asigna el tag, de modo que al switch le llegará el paquete con el tag de la VLAN nativa, en lugar de un paquete sin tag que el incluiría en la VLAN nativa directamente.

Como se puede ver, los modos que tienen un comportamiento similar al de los switches tradicionales son el modo acceso y el modo "native-untagged", ya que el modo trunk utiliza la VLAN 0 para la VLAN nativa y no hay nada similar al modo "native-tagged".

A pesar de lo anterior, todos los modos anteriores pueden funcionar correctamente con los switches tradicionales siempre y cuando en los puertos 802.1q no se utilice la VLAN nativa (si no hay que utilizar el modo "native-untagged")

Por defecto los puertos del OVS se encuentran en modo trunk permitiendo todas las VLANs.

Estos modos de funcionamiento pueden ser configurados tanto en los puertos externos  como en los internos que conectan las VMS, por lo que se podría permitir que estas realizasen tag de VLANs.

Más adelante se mostrará un ejemplo de configuración de modo de funcionamiento ante las VLANs, todos ellos utilizando las herramientas proporcionadas por el OVS.


Por otro lado, tal y como se ha comentado antes, existe otro diseño del OVS para dar soporte a las VLANs en caso de necesitarse compatibilidad con Software basado en bridges: uso de "fake bridges". Un ejemplo de este "Software basado en bridges" podría ser el virt-manager, quien muestra los bridges disponibles en el sistema para poder vincular las máquinas virtuales a ellos.

Los fake bridges se pueden configurar tanto mediante las herramientas de OVS como por mediación de las integraciones con el Sistema Operativo (el mismo método visto anteriormente, utilizando los ficheros de sistema).

En este diseño se creará un fake bridge por cada VLAN el cual se conectará al OVS mediante un puerto de acceso.

Routing con OVS

Se puede realizar enrutamiento con el openvswitch utilizando la funcionalidad de routing del kernel del SO donde está instalado cuando el OVS está funcionando en modo standalone creando fake bridges y realizando el mismo proceso que se vió en 
"KVM: bridges, bondigs y VLANs con VMs (bridge mode & routed mode)".

Si se utiliza el OVS como un switch Openflow (en lugar de standalone), al reenviar este los paquetes según una tabla de flujos programable, el Open vSwitch realmente puede trabajar como un switch o como un router, ya que las decisiones de encaminamiento se pueden hacer tanto por las etiquetas L2 (MACs) como por las L3 (IP), es más, como se ha visto incluso se pueden utilizar elementos de la capa L4 para dichas decisiones. 

Modo de funcionamiento (MAC learning / tabla de flujos)

Hasta ahora en este apartado de configuración, se ha estado tratando al OVS como un Software que lleva a cabo las funciones de un switch tradicional (MAC learning), en las cuales él determina los puertos a los que se han de reenviar los paquetes atendiendo a parámetros como son las MACs, la configuración de VLANs, bonding, etc...


No obstante hay que recordar que el Open vSwitch puede funcionar mediante la configuración de flujos, en lugar de utilizar el modo tradicional, lo cual aporta una gran flexibilidad y abre la puerta a las arquitecturas SDN (ver "Ideas básicas sobre Software Defined Network"). Estos flujos pueden ser configurados ya sea manualmente o mediante un Controller.

Para hacer funcionar el OVS mediante este método de consulta a su tabla de flujos tan solo hay que añadir en su configuración la dirección IP del Controller. Cuando se configura el Controller también es buena idea configurar el modo de funcionamiento en caso de que se pierda la comunicación con él. En este sentido existen dos posibilidades de funcionamiento mientras no hay conectividad con el controller (durante una serie de segundos configurables):
  • Standalone: Cuando se pierde la conectividad (no se reciba ningún paquete desde el Controller durante tres veces un temporizador determinado) el OVS comenzará a funcionar según el método tradicional (MAC learning), en el cual él mismo es quien determina dónde enviar los paquetes según su configuración. Este es el método por defecto en la versión actual de OVS.
  • Secure: El switch continuará funcionando según el método de flujos, pero al no existir Controller no se podrán configurar nuevos flujos. El OVS no admitirá nuevos flujos, ya que no se le permite tomar sus propias decisiones sin controlador, como sucede en el modo standalone, pero los continuará reenviando los paquetes de los flujos que sí que tiene definidos.

El segundo método se llama "seguro" ya que el método standalone tiene el riesgo de que, de no estar correctamente configurado, puede dar lugar a bucles, perdidas de conectividad o paquetes, etc. Por contra, el "método seguro" tiene el riesgo de que los nuevos flujos serán descartados.

Hay que señalar que cuando se recupera la conectividad nuevamente se vuelve al comportamiento de reenvío basado en flujos.


Ejemplo de configuración


El ejemplo de configuración se centrará en la configuración mediante las herramientas CLI del OVS. La configuración mediante la  integración con los ficheros de sistema no se mostrará ya que aparece claramente especificada en el archivo README del .tar y, además, es bastante parecida a la ya vista en "KVM: bridges, bondigs y VLANs con VMs (bridge mode & routed mode)".

También se hará una rápida mención a la configuración necesaria para activar en el OVS el comportamiento por flujos regidos por un Controller. Será breve ya que la mayoría de la configuración se realizaría sobre el propio Controller, lo único a llevar a cabo en el OVS es la propia integración de los dos componentes.

Para estos ejemplos se utilizará el Sistema Operativo CentOS 6.5. Antes de comenzar con la instalación y configuración del OVS, se realiza la instalación del Host KVM y las herramientas libvirt:

yum install kvm qemu-kvm libvirt virt-manager libguestfs-tools libvirt-python python-virtinst

Ya que se va a descargar el fichero con el código de la última versión de OVS, también hay que instalar otras dependencias para poder compilarlo:


yum install gcc make python-devel openssl-devel kernel-devel graphviz kernel-debug-devel autoconf automake rpm-build redhat-rpm-config libtool

El fichero con el código de la versión 2.1 de OVS se puede descargar del siguiente modo:


curl -o openvswitch-2.1.2.tar.gz http://openvswitch.org/releases/openvswitch-2.1.2.tar.gz

Una vez descargado se puede descomprimir:

tar xvfz openvswitch-2.1.2.tar.gz

Dentro del directorio descomprimido se puede encontrar el fichero INSTALL.RHEL el cual muestra los siguientes pasos para configurar correctamente el OVS (compilación de las fuentes en RPMs):


1) Copiar el fichero .tar en el directorio de fuentes RPM:

cp openvswitch-2.1.2.tar.gz /root/rpmbuild/SOURCES/


2) Crear los RPMs del userspace. Para ello antes se ha de entrar en el directorio openvswitch descomprimido:

cd openvswitch-2.1.2
Y luego se crear el RPM:

rpmbuild -bb rhel/openvswitch.spec

Esto crea dos RPMs:
  

[root@kvm2 openvswitch-2.1.2]# ls /root/rpmbuild/RPMS/x86_64/
openvswitch-2.1.2-1.x86_64.rpm  openvswitch-debuginfo-2.1.2-1.x86_64.rpm


3) Crear los RPMs del módulo del kernel.

rpmbuild -bb rhel/openvswitch-kmod-rhel6.spec

Este paso puede originar un error (en algunas versiones de Sistema Operativo) debido a que faltarían por incorporar ficheros necesarios para completar el compilado. El error sería como el siguiente: "error: Installed (but unpackaged) file(s) found:  /etc/depmod.d/openvswitch.conf"

Para solucionarlo se pueden incluir las siguientes líneas al final del fichero de texto openvswitch-kmod-rhel6.speckmod-rhel6.spec (tras el comando de la definición "%clean") de dentro del archivo.tar descomprimido: 

vi rhel/openvswitch-kmod-rhel6.speckmod-rhel6.spec


%files
%defattr(-,root,root,-)
/etc/depmod.d/openvswitch.conf


Tras esta modificación se puede volver a lanzar el comando rmpbuild y, si en esta ocasión no existen errores adicionales, se generarán otros dos RPMs adicionales: 


[root@kvm2 openvswitch-2.1.2]# ls /root/rpmbuild/RPMS/x86_64
kmod-openvswitch-2.1.2-1.el6.x86_64.rpm  openvswitch-debuginfo-2.1.2-1.x86_64.rpm
openvswitch-2.1.2-1.x86_64.rpm           openvswitch-kmod-2.1.2-1.el6.x86_64.rpm


Una vez que se tienen estos cuatro RPMs se pueden instalar en el sistema:


rpm -ivh /root/rpmbuild/RPMS/x86_64/kmod-openvswitch-2.1.2-1.el6.x86_64.rpm
rpm -ivh /root/rpmbuild/RPMS/x86_64/openvswitch-debuginfo-2.1.2-1.x86_64.rpm
rpm -ivh /root/rpmbuild/RPMS/x86_64/openvswitch-2.1.2-1.x86_64.rpm
rpm -ivh /root/rpmbuild/RPMS/x86_64/openvswitch-kmod-2.1.2-1.el6.x86_64.rpm

Desde este punto ya se habría completado la instalación del OVS en el Sistema. Ya que el OpenvSwitch dispone de los dos métodos de funcionamiento comentados (el similar a un switch tradicional y el funcionamiento por flujos), a continuación se dividirá el resto de la configuración en dos secciones, según el caso de uso que se quiera hacer del OVS: una configuración standalone (utilizando tanto las herramientas de OVS como su integración con los ficheros de sistema) o una configuración de las tablas de flujos utilizando un Controller externo.

Configuración para funcionamiento tradicional standalone

En este punto se realizará una configuración primero utilizando las herramientas de OVS y más tarde una configuración similar utilizando la integración con los ficheros de sistema (aunque se recomienda la primera de ellas para entornos reales).


En el siguiente esquema se puede ver la implementación que se realizará en este ejemplo:



 Figura 4 - Esquema del ejemplo de configuración standalone

Como primer paso se ha de crear una bridge al cual se vincule el proceso ovs-vswitchd de manera que se pueden tratar los paquetes recibidos. En este caso se c rea un bridge llamado "ovsbr1":

ovs-vsctl add-br ovsbr1

Una vez ejecutado este comando, se puede comprobar su creación del siguiente modo:


[root@kvm2 ~]# ovs-vsctl show
7f0948cf-6534-46b3-b462-cc2c57e857e4
    Bridge ovsbr1
        Port ovsbr1
            Interface ovsbr1
                type: internal
    ovs_version: "2.1.2"


Como se puede apreciar, el bridge OVS se crea con un puerto incluido de tipo interno. Este puerto es utilizado para configuraciones propias del Open vSwitch, como pueda ser la asignación de una dirección IP a este bridge.

El siguiente paso sería añadir las interfaces externas. Para agregar la interfaz eth2 al OVS,se haría lo siguiente:

ovs-vsctl add-port ovsbr1 eth2

Se comprueba cómo se ha incluido:


[root@kvm2 ~]# ovs-vsctl show
7f0948cf-6534-46b3-b462-cc2c57e857e4
    Bridge "ovsbr1"
        Port "ovsbr1"
            Interface "ovsbr1"
                type: internal
        Port "eth2"
            Interface "eth2"
    ovs_version: "2.1.2"


Pero si lo que realmente se busca es crear un bonding LACP de varias interfaces, se utilizará el comando:

ovs-vsctl add-bond ovsbr1 bond0 eth2 eth3 lacp=active bond_mode=balance-tcp other_config:lacp-time=fast other_config:bond-detect-mode=miimon

En el comando se incluye el tipo de balanceo (balance-tcp), así como la activación de LACP y el método de detección de fallo basando en MII.

NOTA: Para utilizar el eth2 en el bonding primero hay que eliminarlo del OVS antes si se ejecutó el comando del anterior ejemplo, para ello se utilizará: "ovs-vsctl del-port ovsbr1 eth2"

Los puertos del bonding se presentan de esta manera dentro del OVS:


[root@kvm2 ~]# ovs-vsctl show
7f0948cf-6534-46b3-b462-cc2c57e857e4
    Bridge "ovsbr1"
        Port "ovsbr1"
            Interface "ovsbr1"
                type: internal
        Port "bond0"
            Interface "eth3"
            Interface "eth2"
    ovs_version: "2.1.2"


La información de configuración del puerto ya creado se puede obtener así:


[root@kvm2 ~]# ovs-vsctl list port bond0
_uuid               : c23f91b6-0e65-4ffb-8f6e-dca1e2f9d965
bond_downdelay      : 0
bond_fake_iface     : false
bond_mode           : balance-tcp
bond_updelay        : 0
external_ids        : {}
fake_bridge         : false
interfaces          : [0b62165d-98b8-4500-afb0-6b397624938e, 2a7fdc8c-2e45-4a5e-ac68-295e646c2054]
lacp                : active
mac                 : []
name                : "bond0"
other_config        : {bond-detect-mode=miimon, lacp-time=fast}
qos                 : []
statistics          : {}
status              : {}
tag                 : []
trunks              : []
vlan_mode           : []


Para comprobar más información sobre el método de funcionamiento del bond0 se puede utilizar el siguiente comando:


[root@kvm2 ~]# ovs-appctl bond/show bond0
---- bond0 ----
bond_mode: balance-tcp
bond-hash-basis: 0
updelay: 0 ms
downdelay: 0 ms
next rebalance: 2479 ms
lacp_status: configured

slave eth2: disabled
        may_enable: false

slave eth3: disabled
        may_enable: false


Existe un comando adicional que proporciona más información sobre el estado de los enlaces pertenecientes a un agregado LACP:


[root@kvm2 ~]# ovs-appctl lacp/show bond0
---- bond0 ----
        status: active
        sys_id: 00:0c:29:c5:09:fc
        sys_priority: 65534
        aggregation key: 6
        lacp_time: fast

slave: eth2: defaulted detached
        port_id: 6
        port_priority: 65535
        may_enable: false

        actor sys_id: 00:0c:29:c5:09:fc
        actor sys_priority: 65534
        actor port_id: 6
        actor port_priority: 65535
        actor key: 6
        actor state: activity timeout aggregation collecting distributing defaulted

        partner sys_id: 00:00:00:00:00:00
        partner sys_priority: 0
        partner port_id: 0
        partner port_priority: 0
        partner key: 0
        partner state:

slave: eth3: defaulted detached
        port_id: 7
        port_priority: 65535
        may_enable: false

        actor sys_id: 00:0c:29:c5:09:fc
        actor sys_priority: 65534
        actor port_id: 7
        actor port_priority: 65535
        actor key: 6
        actor state: activity timeout aggregation collecting distributing defaulted

        partner sys_id: 00:00:00:00:00:00
        partner sys_priority: 0
        partner port_id: 0
        partner port_priority: 0
        partner key: 0
        partner state:


NOTA: en este ejemplo no se formará el agregado LACP porque el Host no está conectado a un switch físico con LACP configurado

Por defecto, los puertos del OVS se encuentran configurados en modo trunk permitiendo todas las VLANs, pero si se desea configurar el agregado como un trunk que permita ciertas vlans con tag y la VLAN nativa (VLAN 1) y, a la vez, sea compatible con los switches físicos tradicionales, habrá que modificar los parámetros del puerto bond0 mediante este comando:

ovs-vsctl set port bond0 trunks=125,126 tag=1 vlan_mode=native-untagged

En este comando se indica los tags de VLANs permitidos (125 y 126), a la vez que se modifica el modo de comportamiento a "native-untagged", que es como funcionan los switches tradicionales. La variable "tag" en este caso indicaría la VLAN nativa. Como se verá más adelante, la variable tag lo que hace es eliminar el tag de la VLAN indicada, por eso se utiliza en la configuración de los puertos tipo "acceso", en los cuales se desea que el tráfico salga del puerto sin tag alguno.

La configuración del puerto quedará del siguiente modo:


[root@kvm2 ~]# ovs-vsctl list port bond0
_uuid               : 5a5f8f53-5e3b-4ca7-adfa-dae5faa65ec4
bond_downdelay      : 0
bond_fake_iface     : false
bond_mode           : balance-tcp
bond_updelay        : 0
external_ids        : {}
fake_bridge         : false
interfaces          : [b480b60b-50fa-49b1-bf99-2a6562e3ff85, b482f09e-1754-4543-a1f4-03143d5304b9]
lacp                : active
mac                 : []
name                : "bond0"
other_config        : {bond-detect-mode=miimon, lacp-time=fast}
qos                 : []
statistics          : {}
status              : {}
tag                 : 1
trunks              : [125, 126]
vlan_mode           : native-untagged


En lugar de modificar el puerto con la configuración del trunk, también se podrían haber indicado estos valores durante la creación del agregado de este modo:

ovs-vsctl add-bond ovsbr1 bond0 eth2 eth3 lacp=active bond_mode=balance-tcp trunks=125,126 tag=1 vlan_mode=native-untagged other_config:lacp-time=fast other_config:bond-detect-mode=miimon


Con los uplinks externos configurados, solo resta la configuración de los puertos de las máquinas virtuales. Para facilitar esta tarea y que las configuraciones sean mantenidas tras los rebotes del Host, se utilizarán las herramientas libvirt.

Lo primero será crear los virtual networks asociados al Open vSwitch, para ello se deberá crear un fichero XML con una definición parecida a esta:

vi xml-ovs


<network>
  <name>ovs-net</name>
  <forward mode='bridge'/>
  <bridge name='ovsbr1'/>
  <virtualport type='openvswitch'/>
  <portgroup name='Vlan1' default='yes'>
  </portgroup>
  <portgroup name='Vlan125'>
    <vlan>
      <tag id='125'/>
    </vlan>
  </portgroup>
  <portgroup name='Vlan126'>
    <vlan>
      <tag id='126'/>
    </vlan>
  </portgroup>
  <portgroup name='Trunk_all_Vlans'>
    <vlan trunk='yes'>
      <tag id='125'/>
      <tag id='126'/>
    </vlan>
  </portgroup>
</network>


En el fichero se indica que es un puerto vinculado al OVS creado antes ("<bridge name='ovsbr1'/>") y, además, se habilitan las VLANs a las cuales se podrán vincular las VMs creando portgroups. En este ejemplo se han creado dos portgroups de tipo "acceso" a las VLANs 125 y 126, y otro portgroup tipo trunk, por si se desea que la máquina virtual pueda realizar tag de los paquetes.

Hay que recordar que también se pueden añadir servicios como DHCP a la red creada por libvirt.

Con el XML ya se puede definir la red virtual con el siguiente comando:

virsh net-define xml-ovs

La red ya aparecerá pero se encontrará inactiva (hay que recordar que "default" es la red virtual por defecto de libvirt que hace NAT):


[root@kvm2 ~]# virsh net-list --all
Name                 State      Autostart     Persistent
--------------------------------------------------
default              active     yes           yes
ovs-net              inactive   no            yes


Para ponerla activa y que se active automáticamente en los inicios del Host:

virsh net-start ovs-net
virsh net-autostarovs-net 

Con estos comandos ya se puede ver lo siguiente:


[root@kvm2 ~]# virsh net-list --all
Name                 State      Autostart     Persistent
--------------------------------------------------
default              active     yes           yes
ovs-net              active     yes           yes


Una vez que la red virtual está creada, ya se pueden crear las máquinas virtuales y asociarlas a ellas:

virt-install --name=VM_OVS_test --arch=x86_64 --vcpus=1 --ram=512 --os-type=linux  --hvm --connect=qemu:///system  --vnc --noautoconsole --nodisk --boot cdrom

Se puede ver cómo no se ha indicado el parámetro "--network". Esto es porque para vincularlo al portgroup hay que modificar directamente el XML donde se encuentra la definición de la máquina, con lo que se apagará la máquina:

virsh shutdown VM_OVS_test o con virsh destroy VM_OVS_test.

Se puede comprobar el estado de la máquina:


[root@kvm2 ~]# virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     VM_OVS_test                    shut off


Y más tarde se editará el fichero con este comando:

virsh edit VM_OVS_test

Se deberá modificar esta sección:


    <interface type='network'>
      <mac address='52:54:00:84:be:d8'/>
      <source network='default'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>


de la siguiente manera


    <interface type='network'>
      <mac address='52:54:00:84:be:d8'/>
      <source network='ovs-net' portgroup='Vlan125'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>


 Esta máquina virtual se ha vinculado a la VLAN 125. Para comprobar que el OVS puede "ver" el puerto de la vNIC de esta VM, se encenderá la máquina (virsh start VM_OVS_test)

Una vez que está encendida, se pueden volver a comprobar los puertos vinculados al OVS:


[root@kvm2 ~]# ovs-vsctl show
7f0948cf-6534-46b3-b462-cc2c57e857e4
    Bridge "ovsbr1"
        Port "ovsbr1"
            Interface "ovsbr1"
                type: internal
        Port "bond0"
            tag: 1
            trunks: [125, 126]
            Interface "eth2"
            Interface "eth3"
        Port "vnet0"
            tag: 125
            Interface "vnet0"
    ovs_version: "2.1.2"


Se puede ver cómo existe un nuevo puerto llamado vnet0, que será el interfaz de la VM, el cual se encuentra configurado como un puerto de acceso a la VLAN 125.

Configuración para funcionamiento por flujos con Controller


Las únicas configuraciones necesarias en el OVS (si se dispone de uno ya configurado) para que este sea gestionado por un Controller son la elección del modo de funcionamiento en caso de fallo de conexión ("standalone" frente a "secure") y la indicación de la IP y puerto del Controller, ya que el resto de configuración se llevará a cabo en el Controlador, y por tanto no será tratado aquí.

Si se parte de cero, habría que crear el bridge al cual vincular el OVS, y añadir las interfaces externas del mismo modo que se ha hecho antes.

El modo ante fallo se puede indicar de esta manera (en este caso el método "secure"):

ovs-vsctl set-fail-mode ovsbr1 secure

Y la IP y puerto del Controller para el Openflow:

ovs-vsctl set-controller ovsbr1 tcp:1.0.1.100:6633

Y para el OVSDB:

ovs-vsctl set-controller ovsbr1 tcp:1.0.1.100:6640

Es importante tener en cuenta que esa IP necesita ser alcanzable por el Host. Para ello utilizará su propia tabla de enrutamiento, es decir, no tiene por qué utilizar los interfaces vinculados al OVS, si no que puede usar los de gestión, por ejemplo.

Para comprobar que se ha conectado se puede revisar el parámetro "status" de la salida de este comando

ovs-vsctl list controller

Una cosa más a tener en cuenta cuando se utiliza un Controller es que, al crear las máquinas virtuales, ya no será necesario incluir en al configuración el portgroup al que pertenecen, ya que el camino que siga el paquete dependerá de los flujos instalados por el Controlador, no por las VLANs y resolución de MACs. Es por ello que la sección "interface" del XML de la máquina virtual se podría cambiar simplemente por esto:



    <interface type='network'>
      <mac address='52:54:00:84:be:d8'/>
      <source network='ovs-net'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>


Existen comandos que pueden instalar flujos concretos directamente sobre el OVS, pero este despliegue debería disponer de un Controller complejo desde el que se pueda configurar el comportamiento del OVS (VLANs, bondings, etc).

2 comentarios:

  1. Sensacional tutorial de openvswitch. Están perfectamente explicadas de forma sencilla conceptos muy complejos y excelente la aplicación de estos conceptos en los ejemplos.

    ResponderEliminar
  2. Muchas gracias por el súper tutorial.

    ResponderEliminar