Descargar - Archivo Digital UPM - Universidad Politécnica de Madrid

Universidad Politécnica de Madrid
Escuela Técnica Superior de Ingenieros de Telecomunicación
DESARROLLO DE ESCENARIOS VIRTUALES
PARA PRÁCTICAS DE LABORATORIO SOBRE
ARQUITECTURAS DE SERVICIOS EN LA NUBE
Autor: Raúl Álvarez Pinilla
Tutor: David Fernández Cambronero
Miembros del tribunal
Presidente: Alejandro Alonso Muñoz
Vocal: David Fernández Cambronero
Secretario: Joaquín Salvachúa Rodríguez
Suplente: Francisco Javier Ruiz Piñar
Fecha de lectura y defensa:
Calificación:
Universidad Politécnica de Madrid
Escuela Técnica Superior de Ingenieros de Telecomunicación
Grado en Ingeniería de Tecnologías y
Servicios de Telecomunicación
TRABAJO FIN DE GRADO
DESARROLLO DE ESCENARIOS VIRTUALES
PARA PRÁCTICAS DE LABORATORIO SOBRE
ARQUITECTURAS DE SERVICIOS EN LA NUBE
Autor: Raúl Álvarez Pinilla
Tutor: David Fernández Cambronero
Miembros del tribunal
Presidente: Alejandro Alonso Muñoz
Vocal: David Fernández Cambronero
Secretario: Joaquín Salvachúa Rodríguez
Suplente: Francisco Javier Ruiz Piñar
Fecha de lectura y defensa:
Calificación:
Resumen
El trabajo consiste en el diseño, desarrollo y prueba de escenarios basados en máquinas
virtuales que implementan servicios en la nube, haciendo énfasis en las soluciones actuales
para dotar de fiabilidad y escalabilidad a dichos servicios.
El escenario virtual en el que se fundamenta el trabajo está compuesto por servidores web,
servidores de disco y un cortafuegos, y mediante él se comprobarán diferentes configuraciones
a implantar. Se centrará principalmente en la creación de un sistema de ficheros distribuido
y en el estudio de las nuevas arquitecturas de red basadas en software para dotar la
funcionalidad de balanceo de carga en el escenario proporcionando alta disponibilidad y
tolerancia a posibles fallos.
Con todo ello se pretende combinar los componentes de una arquitectura de servicios en la
nube y profundizar en el funcionamiento de ella, acercando la visión de un centro de datos
mediante la virtualización de un escenario.
Palabras clave: Computación en la nube, Centro de datos, Virtualización, Sistema de ficheros
_distribuido, Balanceador de carga, Redes definidas por software
Abstract
The project consist of the design, development and testing of scenarios based on virtual
machines which implement cloud services, emphasizing current solutions to provide reliability
and scalability to such services.
The virtual scenario of this project is composed of web servers, disk servers and a firewall,
and through him, different configurations will be checked to introduce. It will focus mainly
on the creation of a distributed file system and the study of new network architectures based
on software to supply the functionality of load balancing providing high availability and
fault tolerance.
All of this is intended to combine the components of a cloud service architecture and go into
detail about its functioning, bringing closer the vision of a data center by virtual network
scenarios.
Key words: Cloud computing, Data center, Virtualization, Distributed file system,
_Load balancer, Software Defined Networking (SDN)
INDICE DE CONTENIDOS
.
1.
INTRODUCCIÓN ....................................................................................................................... 1
1.1. Motivación ................................................................................................................................. 1
1.2. Objetivos .................................................................................................................................... 1
1.3. Estructura de la memoria ........................................................................................................... 2
2.
DESARROLLO............................................................................................................................ 3
2.1. Preparación del escenario .......................................................................................................... 4
2.1.1. Instalación de VNX ................................................................................................................ 4
2.1.2. Configuración del escenario .................................................................................................. 5
2.1.2.A. Modificación del sistema de ficheros ............................................................................ 7
2.1.2.B. Conexión del escenario con redes externas ................................................................... 8
2.2. Arranque del escenario............................................................................................................. 13
2.3. Sistema de ficheros .................................................................................................................. 15
2.3.1.Configuración de los servidores de disco ............................................................................. 15
2.3.1.A. Volumen distribuido .................................................................................................... 17
2.3.1.B. Volumen en réplica ...................................................................................................... 17
2.3.1.C. Volumen seccionado .................................................................................................... 18
2.3.2. Montaje desde los servidores web ..................................................................................... 19
2.3.2.A. Montaje mediante el comando mount ........................................................................ 19
2.3.2.B. Montaje mediante el fichero fstab .............................................................................. 20
2.3.2.C. Montaje creando un archivo de configuración del volumen ....................................... 21
2.4. Aplicación web ......................................................................................................................... 22
2.5. Balanceador de carga ............................................................................................................... 24
2.5.A. Controlador Floodlight ........................................................................................................ 25
2.5.B. Controlador POX ................................................................................................................. 27
2.6. Firewall ..................................................................................................................................... 30
2.7. Clientes..................................................................................................................................... 35
3.
PRUEBAS Y RESULTADOS ................................................................................................. 37
3.1. Análisis de GlusterFS ................................................................................................................ 37
3.2. Recuperación de un Servidor de Disco ...................................................................................... 39
3.3. Análisis del balanceador de carga ............................................................................................. 41
3.4. Comprobación de las políticas de seguridad ............................................................................. 46
4.
CONCLUSIONES ..................................................................................................................... 47
BIBLIOGRAFÍA ...................................................................................................................... 49
INDICE DE FIGURAS
DESARROLLO
Figura 2-1: Diagrama lógico del escenario de Centro de Datos y Provisión de Servicios ...................................... 3
Figura 2-2: Diagrama lógico del escenario del trabajo ......................................................................................... 3
Figura 2.1-1 - Sistema COW en un servidor web ................................................................................................... 5
Figura 2.1-2 - Switch de red virtual de libvirt ........................................................................................................ 8
Figura 2.1-3 - Servidor DNS y DHCP de libvirt ....................................................................................................... 8
Figura 2.2-1 - Diagrama de estados de las máquinas virtuales en VNX .............................................................. 13
Figura 2.3-1: Volumen distribuido 10.................................................................................................................... 17
Figura 2.3-2: Volumen en réplica 10 ..................................................................................................................... 17
Figura 2.3-3: Volumen seccionado 10 ................................................................................................................... 18
Figura 2.3-4 - Modelo maestro-esclavo en GlusterFS 11 ...................................................................................... 19
Figura 2.4-1: Página de incio de la Aplicación web ............................................................................................. 22
Figura 2.4-2: Función de Subida de ficheros ........................................................................................................ 23
Figura 2.4-3: Función de Descarga de ficheros .................................................................................................... 23
Figura 2.4-4: Función de Borrado de ficheros ...................................................................................................... 23
Figura 2.5-1: Arquitectura SDN ........................................................................................................................... 24
Figura 2.5-2: Petición de servicio desde FW para comprobar balanceador de carga mediante Floodlight ........ 26
Figura 2.5-3: Arranque del Controlador POX ....................................................................................................... 27
Figura 2.5-4: Arranque del Controlador POX en modo DEBUG ........................................................................... 28
Figura 2.5-5: ARPing hacia los servidores web .................................................................................................... 28
Figura 2.5-6: Envío de una petición de servicio desde un cliente......................................................................... 29
Figura 2.5-7: Envío de una respuesta de servicio desde un servidor web ............................................................ 29
Figura 2.6-1: Pantalla de bienvenida de Firewall Builder .................................................................................... 30
Figura 2.6-2: Creación de un firewall (paso 1) ..................................................................................................... 31
Figura 2.6-3 Creación de un firewall (paso 2) ...................................................................................................... 31
Figura 2.6-4: Configuración de la interfaz eth1 del firewall ................................................................................ 32
Figura 2.6-5: Configuración de la interfaz eth2 del firewall ................................................................................ 32
Figura 2.6-6: Configuración de la interfaz de loopback del firewall .................................................................... 32
Figura 2.6-7: Política de reglas aplicadas en el firewall ...................................................................................... 33
Figura 2.6-8: Instalación de políticas de seguridad en el firewall ........................................................................ 34
Figura 2.7-1: Navegador Firefox desde un cliente a través de un túnel ssh ........................................................ 35
Figura 2.7-2: Código fuente desde Firefox de la Aplicación web ......................................................................... 36
PRUEBAS Y RESULTADOS
Figura 3.1-1 - Captura del envío de la información del volumen ......................................................................... 37
Figura 3.1-2 - Captura de llamada LOOKUP en GlusterFS ................................................................................... 38
Figura 3.1-3: Captura de la llamada WRITE en GlusterFS ................................................................................... 38
Figura 3.2-1 - Uso del comando ifconfig down .................................................................................................... 39
Figura 3.2-2 - Contenido de los servidores de disco ............................................................................................. 39
Figura 3.2-3 - Uso del comando ifconfig up ......................................................................................................... 40
Figura 3.2-4 - Captura de la recuperación de la información en un servidor de disco caído ............................... 40
Figura 3.3-1: Balanceo mediante iperf desde un cliente ..................................................................................... 42
Figura 3.3-2: Balanceo mediante iperf desde varios clientes .............................................................................. 42
Figura 3.3-3: Uso de curl para comprobar balanceo de carga ............................................................................ 43
Figura 3.3-4: Trazas del controlador que verifican el balanceo de carga ............................................................ 43
Figura 3.3-5: Captura de tráfico de paquetes OpenFlow ..................................................................................... 43
Figura 3.3-6: Tabla de flujos del switch virtual en LAN2 ...................................................................................... 44
Figura 3.3-7: Diagrama físico de LAN2 ................................................................................................................ 45
Figura 3.3-8: Trazas del controlador al realizar una petición de servicio desde un navegador ........................... 45
Figura 3.4-1: Ping desde C1 hacia FW ................................................................................................................. 46
Figura 3.4-2: Captura de tráfico para comprobar la regla 4 del firewall ............................................................. 46
1. Introducción
En el día de hoy la computación en la nube sigue en continuo crecimiento y progresivamente
ofrece a los usuarios más tipos de servicios. Las aplicaciones telemáticas son de gran
complejidad y cada vez demandan mayor cantidad de recursos de computación, red y
almacenamiento. Asimismo, los usuarios exigen a los servicios un comportamiento eficiente,
fiable y seguro. Por ello surge la necesidad de grandes infraestructuras de redes de
comunicaciones y de centros de datos.
Otra de las razones de la necesidad de disponer de grandes centros de datos es la creciente
tendencia que existe de mover aplicaciones e infraestructuras desde centros de datos
corporativos de un tamaño pequeño a otros de mayor tamaño, que son mantenidos por grandes
proveedores. Esto permite a pequeños negocios ahorrar elevados costes en inversión
económica y pagar únicamente por el consumo efectuado, teniendo un servicio de forma
flexible y adaptativa.
A parte de las características mencionadas, los centros de datos proporcionan muchas más,
como pueden ser, gran escalabilidad, mayor fiabilidad, mejor conectividad con proveedores y
facilidad en la gestión.
1.1. Motivación
Con el objeto de conocer las tecnologías usadas para proporcionar servicios en la nube en
los centros de datos de hoy en día es necesario disponer de escenarios didácticos que
permitan entender y practicar dichas tecnologías.
A través de la virtualización de un escenario que recrea un centro de datos, se proporcionará
a los equipos clientes un servicio de compartición de ficheros escalable que cumplirá los
requisitos de un servicio alojado en la nube.
1.2. Objetivos
Se partirá de un escenario proporcionado en la práctica final de Centro de Datos y Provisión
de Servicios con el propósito de su perfeccionamiento, y así dotarlo de nuevas
funcionalidades usadas actualmente en los grandes centros de datos del mundo.
Con ello se profundizará en el conocimiento de las tecnologías usadas y se propondrán
nuevas funcionalidades. Los puntos en los que se centrará principalmente el trabajo serán el
análisis de un sistema de ficheros distribuido para el servicio a través de GlusterFS y el
estudio e incorporación de un balanceador de carga utilizando la tecnología SDN (Software
Defined Networking). Además, será necesario centrarse en otros aspectos durante el
transcurso del trabajo como la virtualización a través de la herramienta VNX, la
implementación de una aplicación web, y la creación y configuración de un firewall.
1
Introduccion
1.3. Estructura de la memoria
Se ha seguido el siguiente esquema a lo largo de la memoria:
En el Capítulo 2: Desarrollo se presentan las diferentes etapas que se han seguido desde la
preparación del escenario hasta que un cliente puede acceder al servicio, pasando por los
diferentes elementos que son necesarios configurar para cumplir con los requisitos de un
servicio en la nube.
En el Capítulo 3: Pruebas y resultados se han analizado diferentes puntos del escenario para
comprobar el correcto funcionamiento de sus elementos. Las pruebas se han centrado
fundamentalmente en el sistema de ficheros y en el balanceador de carga.
En el Capítulo 4: Conclusiones se ofrece una visión final sobre el trabajo realizado y posibles
líneas de trabajo futuro que se podrían seguir.
Se ha utilizado un código de colores en los diferentes cuadros que aparecerán a lo largo de
la memoria. Un relleno anaranjado mostrará el contenido total o parcial de un fichero
específico, como puede ser un script, y un relleno de color gris claro indicará comandos
ejecutados en un terminal.
CONTENIDO DE FICHEROS
COMANDOS EN UN TERMINAL
Todos los comandos que se muestran a lo largo del trabajo se encuentran con privilegios de
root, por lo tanto el lector puede anteponer sudo a todos ellos o bien pasar a ser root con el
comando sudo su.
2
2. Desarrollo
A lo largo de este capítulo se describirán los diferentes pasos que se han seguido para modificar
y mejorar el escenario virtual que emula el funcionamiento de un servicio de compartición de
ficheros escalable implementado sobre un centro de datos.
El escenario de partida del trabajo es el propuesto en la práctica final de la Centro de Datos y
Provisión de Servicios, que se encuentra compuesto por tres equipos clientes, tres servidores
web, tres servidores de disco y un router que realiza balanceo de carga entre los diferentes
servidores web. Su diagrama lógico es el que se muestra a continuación:
Figura 2-1: Diagrama lógico del escenario de Centro de Datos y Provisión de Servicios 1
Sobre el anterior escenario se ha decidido realizar los siguientes cambios:

La función de balanceador de carga recaerá sobre un controlador SDN que se conectará
a un switch de la subred LAN2 de tipo Open vSwitch 2. Se escogerá este tipo de switch
virtual ya que es compatible con el controlador SDN.

El router LB de acceso al servicio se cambiará por un firewall al que se le aplicarán
unas políticas de seguridad.
De esta forma, el escenario propuesto en el que se basará este trabajo es el siguiente:
Figura 2-2: Diagrama lógico del escenario del trabajo
3
Desarrollo
2.1. Preparación del escenario
Se utilizará la herramienta de virtualización VNX (Virtual Networks over linuX) 3, que se
encargará de la creación del escenario propuesto sobre el ordenador, incluyendo redes
virtuales creadas por switches virtualizados. Para ello será necesario, tras el diseño del
escenario, la especificación de un fichero .xml que tendrá el siguiente formato:
<?xml version="1.0"
<vnx>
(definiciones
(definiciones
(definiciones
(definiciones
</vnx>
encoding="UTF-8"?>
globales: <global>)
de redes virtuales: <net>)
de máquinas virtuales: <vm>)
del equipo host: <host>)
De esta forma se proporcionará a la herramienta VNX la configuración de cada uno de los
elementos que componen el escenario y la interconexión entre ellos.
2.1.1. Instalación de VNX
La instalación se encuentra descrita paso a paso en el portal de la herramienta, y tras ella
será necesario descargar alguno de los sistemas de ficheros preconfigurados que facilita la
herramienta desde su repositorio. En nuestro caso, se utilizará el sistema de ficheros
proporcionado por LXC (Linux Containers) 4, que es una tecnología de contenedores que
permite crear sistemas Linux contenidos dentro de otro aplicándole algunos límites de CPU,
memoria o incluso asignarle interfaces de red, tratándolo como si fuera un equipo
independiente. La ventaja de LXC respecto a otras tecnologías de virtualización es su
ligereza, ya que utiliza recursos mínimos dando así respuestas mucho más rápidas. Como
inconveniente cabe mencionar que no hay interfaz gráfica (GUI) para configuración, por lo
que todo se realizará a través del terminal de cada máquina virtual.
Se puede descargar el sistema de ficheros directamente desde el repositorio o desde la
herramienta vnx_download_rootfs que proporciona VNX. El archivo comprimido
necesario a descargar para nuestro escenario se llama “vnx_rootfs_lxc_ubuntu-XX.XXvXXX.tgz”. Si el sistema operativo lo permite también se encuentra disponible una versión
de 64 bits.
Es importante recordar a lo largo de la práctica que el sistema de ficheros descargado
dispone de los usuarios “root” y “vnx”, con contraseña “xxxx” en ambos.
4
Desarrollo
2.1.2. Configuración del escenario
Las máquinas virtuales pueden utilizar el sistema de ficheros que se ha descargado de dos
formas posibles, en modo directo o en modo cow (copy on write) 5. Cuando una máquina
virtual utiliza el sistema de ficheros en modo directo solo podrá ser usado un sistema de
ficheros por máquina virtual, por lo que para nuestro escenario sería necesario disponer de
numerosas copias de sistemas de ficheros. La opción de copy on write será la que se utilice
ya que permite que varias máquinas virtuales puedan utilizar el mismo sistema de ficheros.
En el escenario propuesto será útil porque los tres servidores web podrán utilizar un mismo
sistema de ficheros, e igual sucede con los servidores de disco y los clientes.
El sistema copy on write devuelve punteros a un mismo sistema de ficheros, y en el
momento en que un proceso intenta modificar algún fichero del sistema, se crea una copia
para prevenir que los cambios producidos por dicho proceso sean visibles por todos los
demás. Todo ocurre de forma transparente para los procesos, y de esta forma no se crea
ninguna copia adicional del recurso si ningún proceso llega a realizar modificaciones.
De esta forma, se dispondrá del sistema de ficheros de sólo lectura que se encontrará
disponible el directorio filesystems de VNX (/usr/share/vnx/filesystems), y del directorio
(read and write) donde se encontrarán las modificaciones del sistema de ficheros. Además
se dispondrá de un directorio en el cual se encuentran punteros del sistema de ficheros
completo de la máquina virtual. En el siguiente diagrama se muestra un ejemplo de lo
comentado en la máquina virtual WWW1:
Figura 2.1-1 - Sistema COW en un servidor web
En este punto se puede plantear la práctica de diferentes formas dependiendo que opción
se utilice respecto a los sistemas de ficheros:

Crear un único sistema de ficheros que compartirán todas las máquinas virtuales
reduciendo el espacio utilizado en disco.

Crear varios sistemas de ficheros para aislar el software de los diferentes grupos de
máquinas virtuales.
5
Desarrollo
Si se escoge la opción de tener varios sistemas de ficheros, se tendrá que realizar la copia
del sistema de ficheros descargado y modificar dos líneas del fichero config de cada uno de
los sistemas de ficheros copiados. En las líneas a modificar se deberá indicar la ruta del
directorio rootfs y del fichero fstab del sistema de ficheros correspondiente. El siguiente
ejemplo corresponde al sistema de ficheros que se utilizará en los servidores web:
lxc.rootfs = /usr/share/vnx/filesystems/vnx_rootfs_lxc_ubuntu-13.10v025-WWW/rootfs
lxc.mount = /usr/share/vnx/filesystems/vnx_rootfs_lxc_ubuntu-13.10v025-WWW/fstab
Además, en la plantilla .xml del escenario se indicará en cada máquina virtual su
correspondiente sistema de ficheros:
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-WWW
</filesystem>
Para la instalación de los diferentes paquetes necesarios en las máquinas virtuales se puede:
a) Modificar directamente el sistema de ficheros descargado cuando el escenario no
se encuentre arrancado. En este caso se está modificando el sistema de ficheros de
sólo lectura que compartirán las máquinas virtuales.
b) Configurar en las máquinas virtuales del escenario una interfaz con conexión a
Internet e instalar en cada máquina los paquetes necesarios. Mediante esta opción
se crearán copias de los archivos modificados del sistema de ficheros en cada
máquina virtual de forma individualizada.
Para el desarrollo del trabajo se instalarán los siguientes paquetes:
Máquina virtual
Identificador
Controlador SDN
CONTROLLER
Servidores de disco
NAS
Servidores web
WWW
Firewall
FW
Clientes
C
Paquetes
Git
GlusterFS
Apache2 , PHP5 , GlusterFS , Iperf
Firewall Builder , Xauth
Firefox , Iperf , Curl , Xauth
6
Desarrollo
Para la instalación de los paquetes mencionados se ejecutarán las siguientes órdenes en las
correspondientes máquinas virtuales:
Paquete
Comando de instalación
Git
# apt-get install git
GlusterFS
# apt-get install glusterfs-server
Apache2
# apt-get install apache2
PHP5
# apt-get install php5
Firewall Builder
# apt-get install fwbuilder
Iperf
# apt-get install iperf
Curl
# apt-get install curl
Xauth
# apt-get install xauth
En los siguientes subapartados se describirán los dos procedimientos comentados para la
instalación de los paquetes necesarios en las máquinas virtuales.
2.1.2.A. Modificación del sistema de ficheros
Dado un cierto sistema de ficheros rootfs_lxc_ubuntu, que se encuentra en el directorio
/usr/share/vnx/filesystems, se explicará cómo modificarlo para añadir los paquetes que se
consideren oportunos. De esta forma, al arrancar el escenario las máquinas virtuales que
dependan de tal sistema de ficheros tendrán modificado su sistema de ficheros con los
cambios que se hayan realizado. Como ventaja de este método cabe nombrar que al estar
utilizando copy on write en la virtualización se reduce el espacio de disco utilizado, ya
que varias máquinas virtuales están utilizando la misma imagen de disco con los paquetes
ya instalados.
Para ello se arrancará una máquina virtual que utilice en modo directo y con conectividad
a Internet el sistema de ficheros descargado:
# lxc-start –n MV –f
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu/config
Una vez arrancada se activará la red utilizando el comando dhclient a la interfaz eth0:
# dhclient eth0
De esta forma, tal interfaz se conectará al switch virtual lxcbr0 que proporcionará acceso
a Internet y ya se podrán instalar los paquetes necesarios. Finalizada la instalación se
parará la máquina virtual con el comando halt, quedando los cambios realizados visibles
desde todas las máquinas virtuales de nuestro escenario que dependan del sistema de
ficheros modificado.
7
Desarrollo
2.1.2.B. Conexión del escenario con redes externas
La otra opción disponible, para la instalación de los paquetes necesarios en el escenario,
es dotar a las diferentes máquinas virtuales de una interfaz de red conectada a un switch
virtual con conexión a Internet. En nuestro caso se dispone de dos redes virtuales creadas
por defecto con sus correspondientes switches virtuales: virbr0 y lxcbr0.
A continuación se explicará el funcionamiento de este tipo de redes y switches virtuales,
más en concreto virbr0, que es proporcionado por libvirt 6.
Libvirt es una interfaz de programación de aplicaciones (API) que interactúa con varios
hipervisores de virtualización y ofrece diferentes funciones, como por ejemplo la creación
de redes virtuales.
Se utilizará el switch de red virtual
virbr0 que está disponible tras la
instalación de la herramienta VNX.
A este switch se conectarán las
diferentes máquinas virtuales de
nuestro escenario y en el momento
que se precise de conexión con el
exterior será posible. 7
Figura 2.1-2 - Switch de red virtual de libvirt 7
Para realizar la conexión es necesario solicitar desde la máquina virtual deseada una
petición desde el cliente de DHCP. De esta forma se enviarán peticiones broadcast por la
interfaz creada solicitando información de configuración, y así conseguir una dirección
IP junto con otros parámetros
relevantes para el correcto
funcionamiento del sistema en la
red, como la máscara de red, el
router por defecto y los servidores
de DNS. El servidor DHCP
otorgará a la máquina virtual una
dirección
IP
del
rango
192.168.122.2 – 192.168.122.254
Figura 2.1-3 - Servidor DNS y DHCP de libvirt 7
8
Desarrollo
Se puede comprobar que está activo el switch virtual virbr0, que viene preconfigurado
por defecto, mediante el comando ifconfig o brctl show en el que se obtendrán los
siguientes resultados:
# ifconfig virbr0
Link encap:Ethernet direcciónHW fe:35:18:d7:76:81
Direc.inet:192.168.122.1
Difus.:192.168.122.255 Másc:255.255.255.0
ACTIVO DIFUSIÓN FUNCIONANDO MULTICAST MTU:1500 Métrica:1
Paquetes RX:27 errores:0 perdidos:0 overruns:0 frame:0
Paquetes TX:18 errores:0 perdidos:0 overruns:0 carrier:0
colisiones:0 long.colaTX:0
Bytes RX:2884 (2.8 KB) TX bytes:1934 (1.9 KB)
# brctl show virbr0
bridge name
virbr0
bridge id
8000.000000000000
STP enabled
yes
interfaces
También existen unas funciones disponibles a través del comando virsh mediante el cual
se obtiene más información, como por ejemplo:
 Muestra el listado de redes (en nuestro caso la red que utilizada es default, que deberá
venir preconfigurada)
# virsh net-list
Nombre
Estado
Inicio automático Persistente
------------------------------------------------------------default
activo
si
si
 Muestra información general sobre la red solicitada
# virsh net-info default
Nombre
default
UUID
70a01cdb-e771-462c-8ec1-8a7f64c57088
Activar:
si
Persistente:
si
Autoinicio:
si
Puente:
virbr0
9
Desarrollo
 Muestra el fichero .xml de la red solicitada
# virsh net-dumpxml default
<network>
<name>default</name>
<uuid>70a01cdb-e771-462c-8ec1-8a7f64c57088</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr0' stp='on' delay='0' />
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
Si en algunas de las comprobaciones no se obtiene un resultado verificando el switch
virtual o se desea crear una nueva red con su switch virtual correspondiente se puede
definir de la siguiente manera:
1 – Creación de un fichero .xml especificando la red a crear en el directorio
/etc/libvirt/qemu/network. A continuación se muestra un ejemplo del fichero
correspondiente de la red preconfigurada default:
<network>
<name>default</name>
<bridge name="virbr0" />
<forward/>
<ip address="192.168.122.1" netmask="255.255.255.0">
<dhcp>
<range start="192.168.122.2" end="192.168.122.254" />
</dhcp>
</ip>
</network>
2 – Definición de la red
# virsh net-define /etc/libvirt/qemu/network/default.xml
La red default se encuentra definida desde default.xml
3 – Configuración de auto-inicio de la red (opcional)
# virsh net-autostart default
La red default se ha sido marcada para iniciarse automáticamente
10
Desarrollo
4 – Inicio de la red
# virsh net-start default
La red default se ha iniciado
Si se desea borrar una red existente se puede hacer uso del siguiente comando:
# virsh net-destroy default
La red default ha sido destruida
Para la creación de la interfaz de red de las máquinas virtuales que se conectará al switch
virtual que se ha descrito se tendrá que modificar la plantilla .xml del escenario.
Se añadirá un nuevo switch virtual con el nombre de virbr0 y la opción managed=”no”
que permitirá a la herramienta VNX en el momento del borrado del escenario no eliminar
la red correspondiente al switch virtual virbr0:
<net name="virbr0" mode="virtual_bridge" managed="no" />
Y en cada una de las máquinas virtuales que se desee tener conexión a Internet se indicará
el nuevo interfaz:
<if id="99" net="virbr0"/>
Una vez arrancado el escenario, como se describe en el apartado 2.1.3. Arranque del
escenario, se podrá comprobar que está disponible tal interfaz de red en las máquinas
virtuales:
# ifconfig eth99
Link encap:Ethernet HWaddr 02:fd:00:00:03:63
inet6 addr: fe80::fd:ff:fe00:363/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:337 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:62098 (62.0 KB) TX bytes:1076 (1.0 KB)
Para solicitar una dirección IP al servidor DHCP, y tener conectividad al exterior, se
utilizará el siguiente comando:
# dhclient eth99
11
Desarrollo
Se puede comprobar la dirección IP asignada utilizando de nuevo el comando ifconfig:
# ifconfig eth99
Link encap:Ethernet HWaddr 02:fd:00:00:03:63
inet addr:192.168.122.153 Bcast:192.168.122.255 Mask:255.255.255.0
inet6 addr: fe80::fd:ff:fe00:363/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:68 errors:0 dropped:0 overruns:0 frame:0
TX packets:14 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:10078 (10.0 KB) TX bytes:1920 (1.9 KB)
Y en la tabla de forwarding de las máquinas virtuales se habrá añadido automáticamente
como puerta de enlace la dirección IP 192.168.122.1:
root@FW:~# route
Kernel IP routing table
Destination
Gateway
default
192.168.122.1
10.1.1.0
*
10.1.2.0
*
192.168.122.0
*
Genmask
0.0.0.0
255.255.255.0
255.255.255.0
255.255.255.0
Iface
eth99
eth1
eth2
eth99
Realizando un ping para comprobar la conectividad a cualquier página web disponible en
Internet se comprueba que el resultado es satisfactorio:
# ping www.dit.upm.es
PING www.dit.upm.es (138.4.2.60) 56(84) bytes of
64 bytes from www.dit.upm.es (138.4.2.60): seq=1
64 bytes from www.dit.upm.es (138.4.2.60): seq=2
64 bytes from www.dit.upm.es (138.4.2.60): seq=3
data.
ttl=51 time=53.5 ms
ttl=51 time=54.5 ms
ttl=51 time=52.8 ms
--- www.dit.upm.es ping statistics --3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 52.814/53.634/54.503/0.715 ms
12
Desarrollo
2.2. Arranque del escenario
El último paso para el funcionamiento del escenario es arrancarlo a través de la herramienta
VNX, la cual ofrece múltiple funcionalidades.
Los comandos a ejecutar tendrán la siguiente estructura:
# vnx –f VNX_file --ACTION [options][-M VM_LIST]
 VNX_FILE es la plantilla .xml creada para el escenario.
 ACTION es una de las diferentes acciones disponibles de la herramienta.
 VM_LIST es una de las posibles opciones en el que la acción a ejecutar sólo se
producirá en la lista de máquinas virtuales indicadas del escenario. Un ejemplo puede
ser -M NAS1,NAS2,NAS3.
A continuación se muestra el diagrama de estados en el que pueden estar las diferentes
máquinas virtuales de un escenario en concreto a través de la herramienta VNX, y sus
diferentes acciones de transición:
Figura 2.2-1 - Diagrama de estados de las máquinas virtuales en VNX
13
Desarrollo
En nuestro caso, las acciones más utilizadas serán create, destroy, shutdown, start y reboot,
siendo sus comandos los siguientes:
# vnx –f VNX_file --create
# vnx –f VNX_file --destroy
# vnx –f VNX_file --shutdown
# vnx –f VNX_file --start
# vnx –f VNX_file --reboot
Cabe mencionar la opción –n al utilizar el comando create o start que permite ocultar las
consolas de las distintas máquinas virtuales arrancadas.
También existen otros comandos de interés de la herramienta VNX a utilizar en el desarrollo
de la práctica como por ejemplo los que se nombran a continuación:
 Ejecuta los comandos indicados con una cierta etiqueta de la plantilla. Este tipo de
comando es útil porque se puede especificar en la plantilla que se ejecuten ciertos
comandos en las máquinas virtuales que se requieran en el momento de arranque de
la propia máquina virtual o cuando se utiliza este comando.
# vnx –f VNX_file --execute TAG [-M VM_LIST]
En la plantilla .xml se configurará de la siguiente forma:
<exec seq="TAG" type="verbatim" ostype="system">
COMANDO_A_EJECUTAR
</exec>
 Muestra las consolas del conjunto de máquinas virtuales del escenario. Aplicando la
opción -M permite mostrar las consolas de aquellas máquinas virtuales indicadas.
# vnx –f VNX_file --console [-M VM_LIST]
 Muestra el estado en el que se encuentran las máquinas virtuales
# vnx –f VNX_file --show-status [-M VM_LIST]
 Muestra un diagrama con las conexiones de red construidas en el escenario.
# vnx –f VNX_file --show-map
14
Desarrollo
2.3. Sistema de ficheros
A continuación se detalla la configuración del sistema de ficheros GlusterFS 8 en el escenario
propuesto con el objetivo de evaluar diferentes propuestas y características de un centro de
datos como pueden ser: escalabilidad, redundancia, tolerancia de fallos, etc.
El proceso se dividirá en dos pasos ya que es necesario configurar tanto los servidores de
disco como los servidores web. El primer paso consistirá en la creación del volumen en los
servidores de disco, donde se podrá disponer de diferentes tipos de volúmenes según las
necesidades requeridas. En el segundo paso se describirán diferentes métodos para realizar
el montaje desde los servidores web, ya que aunque tengan el mismo propósito no son todos
iguales de fiables.
2.3.1. Configuración de los servidores de disco
Para la correcta configuración de los servidores de disco se necesita que cada uno de ellos
disponga de identificadores (UUID) distintos. En nuestro caso, al generar todas las
máquinas virtuales a partir de la misma imagen tienen configurado el mismo identificador.
Por ello, es necesario generar nuevos identificadores. Una posible solución es generar
identificadores nuevos con el comando uuidgen en cada uno de los servidores de disco
NAS2 y NAS3, y sobrescribir el fichero /etc/glusterd/glusterd.info con el nuevo
identificador generado en cada uno de ellos respectivamente. Por ejemplo:
Comandos a ejecutar en el servidor de disco NAS2:
root@NAS2:~# uuidgen
361fbfb4-fa61-49d1-9096-1b8a481476b6
root@NAS2:~# echo UUID=361fbfb4-fa61-49d1-9096-1b8a481476b6>
/etc/glusterd/glusterd.info
Comandos a ejecutar en el servidor de disco NAS3:
root@NAS3:~# uuidgen
6763582b-7fc7-4767-a7d7-e289709c0ba7
root@NAS3:~# echo UUID=6763582b-7fc7-4767-a7d7-e289709c0ba7>
/etc/glusterd/glusterd.info
Tras la ejecución de estos comandos se debe rearrancar el servicio, en cada uno de los NAS,
para que los cambios tengan efecto mediante la siguiente orden:
# service glusterfs-server restart
glusterfs-server stop/waiting
glusterfs-server start/running
15
Desarrollo
El siguiente paso será la creación del clúster de servidores de disco 9. Para ello se necesitará
acceder a uno de los servidores de disco, por ejemplo NAS1, y agregar los servidores al
repositorio ejecutando el comando gluster peer probe seguido de la dirección IP de los
demás servidores:
root@NAS1:~# gluster peer probe 10.1.3.22
Probe successful
root@NAS1:~# gluster peer probe 10.1.3.23
Probe successful
Se puede verificar que se han añadido correctamente desde cualquiera de los servidores
NAS de la siguiente manera:
root@NAS1:~# gluster peer status
Number of Peers: 2
Hostname: 10.1.3.22
Uuid: 361fbfb4-fa61-49d1-9096-1b8a481476b6
State: Peer in Cluster (Connected)
Hostname: 10.1.3.23
Uuid: 6763582b-7fc7-4767-a7d7-e289709c0ba7
State: Peer in Cluster (Connected)
Si se necesita descartar algún servidor añadido al cluster se puede hacer uso del siguiente
comando:
root@NAS1:~# gluster peer detach IPADDRESS
Detach successful
Una vez añadidos los servidores de disco se procederá a crear el volumen con la
configuración que se considere más apropiada. Se deberá seguir el siguiente formato en el
comando de creación:
# gluster volume create VOLNAME [stripe COUNT | replica COUNT]
NEW-BRICK1 NEW-BRICK2 NEW-BRICK3...
Los distintos modelos de configuración se tratarán en los siguientes subapartados:
- Volumen distribuido
- Volumen en replica
- Volumen seccionado
Existen otras posibilidades que se pueden aplicar en GlusterFS que son combinaciones
entre las configuraciones anteriores.
16
Desarrollo
2.3.1.A. Volumen distribuido
Se distribuyen los archivos de
forma aleatoria entre los bloques
del volumen. En este modo de
configuración hay que tener en
cuenta que la avería de algún
servidor de disco puede resultar una
grave pérdida de datos, ya que el
contenido del servidor caído se
perderá del volumen. Como ventaja
en esta configuración cabe destacar
la eficiencia en la escritura de datos.10
Figura 2.3-1: Volumen distribuido 10
El comando de creación en esta configuración debe seguir el siguiente formato:
# gluster volume create NEW-VOLNAME NEW-BRICK...
Siendo en nuestro escenario el siguiente:
# gluster volume create nas 10.1.3.21:/nas 10.1.3.22:/nas
10.1.3.23:/nas
2.3.1.B. Volumen en réplica
Se copian los archivos a través de los
bloques
del
volumen.
Esta
configuración proporciona una
mayor fiabilidad ya que se tendrá
redundancia en la información
almacenada y garantizará mayor
disponibilidad del servicio. El
inconveniente en este tipo de
volumen es la cantidad de tráfico
generado, ya que los cambios se
distribuyen al mismo tiempo a todos
los bloques del volumen.
Figura 2.3-2: Volumen en réplica 10
El comando de creación en esta configuración debe seguir el siguiente formato:
# gluster volume create NEW-VOLNAME [replica COUNT] NEW-BRICK..
Siendo en nuestro escenario el siguiente:
# gluster volume create nas replica 3 10.1.3.21:/nas
10.1.3.22:/nas 10.1.3.23:/nas
17
Desarrollo
2.3.1.C. Volumen seccionado
En esta configuración los archivos
son fragmentos en diferentes
porciones que se reparten entre los
diferentes bloques que componen el
volumen. Es generalmente utilizado
para almacenar archivos de gran
tamaño en entornos de alta
concurrencia.
Figura 2.3-3: Volumen seccionado 10
El comando de creación en esta configuración debe seguir el siguiente formato:
# gluster volume create NEW-VOLNAME [stripe COUNT] NEW-BRICK..
Siendo en nuestro escenario el siguiente:
# gluster volume create nas stripe 3 10.1.3.21:/nas
10.1.3.22:/nas 10.1.3.23:/nas
Una vez creado el volumen se puede comprobar la información del volumen:
# gluster volume info
Volume Name: nas
Type: XXX
Status: Created
Number of Bricks: 3
Transport-type: tcp
Bricks: ...
Tras la creación del volumen será necesario su inicialización mediante el comando:
# gluster volume start nas
Starting volume nas has been successful
Si en algún determinado momento es necesario eliminar el volumen creado se debe seguir
el siguiente procedimiento:
# gluster volume stop nas
Stopping volume will make its data inaccessible.
Do you want to continue? (y/n) y
Stopping volume nas has been successful
# gluster volume delete nas
Deleting volume will erase all information about the volume.
Do you want to continue? (y/n) y
Deleting volume nas has been successful
18
Desarrollo
2.3.2. Montaje desde los servidores web
El último paso para finalizar la configuración del sistema de ficheros es realizar el montaje
desde los servidores web, ya que necesitan conocer el volumen creado, así como su
configuración y bloques que lo componen.
En el momento del montaje se especificará desde cada servidor web uno de los tres
servidores de disco del escenario, los cuales poseen la información del volumen creado en
el directorio/etc/glusterd/vols/nas.
Una vez realizado el montaje, los servidores
web conocerán cada uno de los servidores
de disco que componen el volumen para
mantener el sistema de ficheros.
El sistema de ficheros GlusterFS funciona
basándose en un modelo maestro-esclavo,
siendo en nuestro caso el maestro los
servidores web, y el esclavo los servidores
de disco del escenario.11
Figura 2.3-4 - Modelo maestro-esclavo en GlusterFS 11
Para las diferentes formas de montaje es necesario tener en el sistema un módulo cargable
de núcleo conocido como FUSE (Filesystem in Userspace) 12. Para su creación basta con
ejecutar el siguiente comando mknod 13 creando el correspondiente archivo de dispositivo:
# mknod -m 666 /dev/fuse c 10 229
A continuación se describirán diferentes métodos de montaje que se diferenciarán entre sí
porque proporcionarán distintos grados de automatización y fiabilidad en el montaje.
2.3.2.A. Montaje mediante el comando mount
Para acceder al sistema de ficheros exportado por los servidores de disco se puede utilizar
directamente el comando mount, ya que es una de las opciones más rápidas de montaje.
Solamente será necesaria la creación de un directorio y ejecutar mount indicando el punto
de montaje en el directorio creado del servidor web. Un posible ejemplo es el siguiente:
# mkdir /mnt/nas
root@NAS1:~# mount -t glusterfs 10.1.3.21:/nas /mnt/nas
root@NAS2:~# mount -t glusterfs 10.1.3.22:/nas /mnt/nas
root@NAS3:~# mount -t glusterfs 10.1.3.23:/nas /mnt/nas
En este caso, si falla el servidor de disco que se indica en el momento del montaje se
perderá el sistema de ficheros en el servidor web correspondiente.
19
Desarrollo
2.3.2.B. Montaje mediante el fichero fstab
El fichero /etc/fstab (File System Table) 14 forma parte de la configuración del sistema y
es el encargado de reflejar cómo se montan los discos en el sistema de ficheros. Lo que
está escrito en tal fichero sirve para tener acceso a los discos una vez que se inicia el
sistema operativo.
Este procedimiento se puede considerar una versión avanzada del montaje visto
anteriormente ya que se modificará el fichero fstab para que el sistema monte
automáticamente el sistema de ficheros proporcionado por los servidores de disco.
Para ello, será necesario añadir la siguiente línea al fichero fstab:
IPADDRESS:/VOLNAME MOUNTDIR glusterfs defaults,_netdev 0 0
En nuestro caso, el fichero fstab quedará con el siguiente contenido:
# UNCONFIGURED FSTAB FOR BASE SYSTEM
10.1.3.21:/nas /mnt/nas glusterfs defaults,_netdev 0 0
Para proceder al montaje una vez modificado el fichero fstab se puede reiniciar la máquina
virtual mediante el comando reboot, o directamente utilizar el comando mount –a.
Si al arrancar de nuevo alguna de las máquinas no se cargara automáticamente el sistema
de ficheros será necesario modificar el fichero /etc/rc.local dejándolo con el siguiente
contenido:
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
mount -a
exit 0
Sin embargo, se tiene el mismo problema que en el montaje mediante el comando mount,
donde si no se encuentra disponible el servidor de disco indicado en el momento del
montaje no se cargará el sistema de ficheros en el servidor web correspondiente.
20
Desarrollo
2.3.2.C. Montaje creando un archivo de configuración del volumen
En este modo de montaje se pretende crear un archivo de configuración del volumen
indicando diferentes puntos de montaje. Dado el escenario se indicarán tres puntos de
montaje del volumen, uno por cada servidor de disco del escenario. Este tipo de montaje
se garantiza que se comprobarán todos los puntos de montaje indicados, evitando el
problema que se mencionaba en los otros dos métodos anteriores.
Para ello, se debe modificar el fichero /etc/fstab indicando donde se encuentra el archivo
de configuración del volumen:
# UNCONFIGURED FSTAB FOR BASE SYSTEM
/etc/glusterfs/datastore.vol /mnt/nas glusterfs
rw,allow_other,default_permissions,max_read=131072 0 0
Se creará un archivo de configuración llamado datastore.vol en el directorio /etc/glusterfs.
Su contenido es el siguiente:
volume remote1
type protocol/client
option transport-type tcp
option remote-host 10.1.3.21
option remote-subvolume /nas
end-volume
volume remote2
type protocol/client
option transport-type tcp
option remote-host 10.1.3.22
option remote-subvolume /nas
end-volume
volume remote3
type protocol/client
option transport-type tcp
option remote-host 10.1.3.23
option remote-subvolume /nas
end-volume
volume replicate
type cluster/replicate
subvolumes remote1 remote2 remote3
end-volume
volume writebehind
type performance/write-behind
option window-size 1MB
subvolumes replicate
end-volume
21
Desarrollo
volume cache
type performance/io-cache
option cache-size 512MB
subvolumes writebehind
end-volume
Para realizar el montaje sin reiniciar el sistema es posible utilizar el comando mount -a.
Se puede comprobar el estado del montaje de la siguiente forma:
root@WWW1:/# df -h
S.ficheros
/etc/glusterfs/datastore.vol
Montado en
/mnt/nas
Así, aunque en el momento del montaje no se encuentre accesible el servidor de disco
NAS1, se intentará con NAS2, y en caso de fallo se intentará con NAS3, siendo esta
opción la más fiable de las mencionadas.
2.4. Aplicación web
Se ha desarrollado para el escenario una aplicación web que permite a los diferentes usuarios
subir, descargar y borrar ficheros que se alojan en los servidores de disco. Para ello las
tecnologías utilizadas han sido HTML y PHP5.
Se pretende proporcionar una interfaz sencilla para el usuario donde en todo momento pueda
seleccionar una de las opciones que se han comentado. Por ello se ha utilizado una estructura
de marcos con cuatro frames, donde uno de ellos se encargará de permitir al usuario realizar
la acción que seleccione a partir de un menú. De esta forma, la página principal es la
siguiente:
Figura 2.4-1: Página de incio de la Aplicación web
22
Desarrollo

SUBIDA DE FICHEROS: Se puede realizar una subida múltiple seleccionando
varios archivos en la ventana emergente que se muestra. Para el correcto
funcionamiento es necesario que los directorios /tmp y /mnt/nas dispongan de
permisos de lectura y escritura para todos los usuarios.
Figura 2.4-2: Función de Subida de ficheros

DESCARGA DE FICHEROS: Se mostrará una lista con todos los archivos que se
encuentran disponibles para descargar.
Figura 2.4-3: Función de Descarga de ficheros

BORRADO DE FICHEROS: Se mostrará una lista con los archivos alojados en los
servidores. Se notificará mediante una ventana emergente cuando se haya eliminado
el archivo deseado correctamente.
Figura 2.4-4: Función de Borrado de ficheros
23
Desarrollo
2.5. Balanceador de carga
Según el escenario propuesto se pretende balancear la carga entre los diferentes servidores
web que se disponen y así se podrán repartir las peticiones de servicio que se reciban. En
este caso, se ha decidido realizar esta funcionalidad a través de la tecnología SDN (Software
Defined Networking) 15, ya que proporciona una nueva visión sobre las configuraciones y
funciones de la red mediante el control y centralización gestionado por software.
La aplicación software que se encarga de la red se denomina controlador, y en el escenario
se situará en la máquina virtual denominada CONTROLLER. De esta forma, en el controlador
se encontrará la Capa de Control y en los dispositivos de red la Capa de Infraestructura. Para
la comunicación entre ambas capas será necesario la utilización de un protocolo.
Actualmente, existe un proyecto en el que trabajan varias empresas del mundo, que forman
parte de la Open Networking Fundation (ONF) 16, con el objetivo del desarrollo de un
protocolo de código abierto llamado OpenFlow, siendo el más ampliamente aceptado en
SDN, pero cabe mencionar que existen otras iniciativas para la comunicación entre las capas
mencionadas.
En cada uno de los dispositivos de la red se encuentra una parte denominada Tabla de Flujos,
que recoge todas las acciones que debe realizar un switch a medida que se recibe un nuevo
flujo por alguno de sus puertos. El controlador es el encargado de añadir entradas en la tabla
de flujos de cada switch.
Existe una tercera capa, la Capa de Aplicación, que es la de más alto nivel y aporta la
capacidad de crear aplicaciones a través de una API (application programming interface).
De esta forma, la estructura SDN es la siguiente:
Figura 2.5-1: Arquitectura SDN
24
Desarrollo
Dependiendo de la API utilizada existen múltiples controladores que se diferenciaran
fundamentalmente en cuanto al lenguaje de programación y la plataforma. Algunas de las
alternativas de controladores SDN OpenFlow son:



Python: POX, Ryu
Java: Floodlight, Beacon
Ruby: Trema
El estudio se ha centrado en los controladores Floodlight y POX, ya que son dos
controladores que vienen con la funcionalidad de balanceo de carga implementada en cierta
medida, y por sus características se han considerado apropiados para el escenario.
En un primer momento se trabajó con el controlador Floodlight en el escenario propuesto,
pero no se alcanzó el balanceo de carga correctamente ya que solo se produce en peticiones
que se realizan desde la misma subred. Por ello se decidió examinar nuevas alternativas y se
realizó el estudio con el controlador POX, con el cual se han alcanzado los objetivos
satisfactoriamente y se balancea el tráfico en el escenario en su totalidad. A continuación se
detalla más información sobre cada uno de ellos para dotar de la función de balanceo de
carga al escenario.
2.5.A. Controlador Floodlight
Es un controlador que está basado en Java, y para su correcto funcionamiento debe estar
ejecutándose en el propio host o en una máquina virtual donde el sistema de ficheros sea
en modo directo. Si se decide instalar el controlador en el host se deberá indicar en la
plantilla .xml del escenario que en la red LAN2 el controlador se encontrará en
127.0.0.1:6633. Si se escoge la otra opción, y se decide utilizar una máquina virtual en
modo directo es necesario modificar la plantilla .xml del escenario con la siguiente línea:
<filesystem type="direct">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-CONTROLLER
</filesystem>
El proceso de instalación e inicialización se encuentra descrito en la documentación del
proyecto Floodlight 17, donde también se especifica el funcionamiento del módulo
balanceador de carga.
Para trasmitir los parámetros del balanceador al controlador, será necesario crear un script
y mediante la conexión de curl será suficiente. En el escenario propuesto se utilizará el
siguiente script:
25
Desarrollo
#!/bin/sh
curl -X POST -d
'{"id":"1","name":"vip1","protocol":"tcp","address":"10.1.2.10","port":"8"}'
http://localhost:8080/quantum/v1.0/vips/
curl -X POST -d '{"id":"1","name":"pool1","protocol":"tcp","vip_id":"1"}'
http://localhost:8080/quantum/v1.0/pools/
curl -X POST -d '{"id":"1","address":"10.1.2.11","port":"8","pool_id":"1"}'
http://localhost:8080/quantum/v1.0/members/
curl -X POST -d '{"id":"2","address":"10.1.2.12","port":"8","pool_id":"1"}'
http://localhost:8080/quantum/v1.0/members/
curl -X POST -d '{"id":"3","address":"10.1.2.13","port":"8","pool_id":"1"}'
http://localhost:8080/quantum/v1.0/members/
Con todo esto se tendrá el controlador Floodlight funcionando, pero como se ha comentado
anteriormente, solo balanceará peticiones de la misma subred donde se encuentran los
servidores web. Para ello se puede comprobar realizando una petición de servicio desde la
máquina FW:
Figura 2.5-2: Petición de servicio desde FW para comprobar balanceador de carga mediante Floodlight
Una de las ventajas que se ha encontrado que tiene Floodlight es que incorpora un portal
web en el que se recoge información sobre el controlador. Para acceder basta con conectarse
desde el navegador a la dirección localhost:8080/ui/index.html.
Sin embargo, se han encontrado varios inconvenientes en el escenario:

No se ha alcanzado el balanceo de carga en su totalidad, ya que los clientes deben
encontrarse en la misma subred que los servidores web.

El controlador debe estar ejecutándose en el propio host o en una máquina virtual
donde el sistema de ficheros sea en modo directo, no tipo cow como se estaba
utilizando hasta ahora.

Requiere importante espacio libre en disco, ya que se precisa la instalación de
diferentes paquetes
Por las anteriores razones, se decidió estudiar y probar el controlador POX con el objetivo
de dotar al escenario con la funcionalidad de balanceo de carga a las diferentes peticiones
de servicio que se envíen desde los equipos clientes.
26
Desarrollo
2.5.B. Controlador POX
Es un controlador que tiene una interfaz OpenFlow y puede estar ejecutándose en cualquier
plataforma: Linux, Windows, Mac OS, etc. Se constituye por diversos componentes que
pueden ser reutilizados para la adaptación según considere el usuario. En nuestro caso se
modificará el componente de balanceo de carga para adaptarlo al escenario propuesto.
Para su instalación solo es necesario disponer en la máquina de Git y ejecutar el siguiente
comando para obtener una copia del repositorio del proyecto:
# git clone http://github.com/noxrepo/pox
# cd pox
El componente encargado del balanceo de carga se encuentra implementado, dentro del
proyecto, en el fichero pox/misc/ip_loadbalancer.py. Es necesario realizar diferentes
modificaciones en el fichero para personalizarlo en el escenario propuesto.
Para poner en marcha el controlador se utiliza el componente de inicio pox.py. De esta
forma, para arrancar cualquier modulo se sigue la siguiente orden:
root@CONTROLLER:/pox# ./pox.py NOMBRE_COMPONENTE [OPCIONES]
En nuestro caso, para arrancar el balanceador de carga:
root@CONTROLLER:/pox# ./pox.py misc.ip_loadbalancer
--ip=10.1.2.10 --servers=10.1.2.11,10.1.2.12,10.1.2.13
Figura 2.5-3: Arranque del Controlador POX
27
Desarrollo
También es posible arrancarlo en un modo de depuración donde es posible obtener más
información al respecto de los eventos que suceden en el controlador. Para ello hay que
añadir la opción log.level --DEBUG, como se muestra en la siguiente captura:
Figura 2.5-4: Arranque del Controlador POX en modo DEBUG
Como se muestra en la captura
anterior, el controlador envía
periódicamente mensajes ARP a los
diferentes servidores, que se le han
proporcionado en su arranque, para
comprobar que se encuentran
activos y así enviar las posibles
peticiones de servicio hacia ellos. Si
pasado un cierto tiempo del envío
del mensaje ARP Request no se
recibe ninguna respuesta por parte
de algún servidor, mediante un
mensaje ARP Reply, se considerará
que el servidor está caído y no se
enviarán peticiones hacia él.
Figura 2.5-5: ARPing hacia los servidores web
28
Desarrollo
Al recibir una petición de servicio el switch verificará si en su tabla de flujos tiene algún
flujo asociado. En caso de no tenerlo se lo comunicará al controlador que examinará cuál
de los servidores de encuentra activo y según el algoritmo implementado informará a la
tabla de flujos del switch para redirigir la petición hacia al servidor web seleccionado. En
nuestro caso, se encuentra implementado un algoritmo round robin 18 entre los servidores
web para balancear las diferentes conexiones abiertas en los clientes. En la siguiente imagen
se muestra este proceso:
Figura 2.5-6: Envío de una petición de servicio desde un cliente
Una vez que el servidor web seleccionado recibe la petición, devuelve una respuesta al
cliente, y en el momento que la trama pasa por el switch se cambia la dirección IP origen
del servidor web a la dirección IP virtual del servicio. Este proceso se puede ver en la
siguiente imagen:
Figura 2.5-7: Envío de una respuesta de servicio desde un servidor web
Se puede comprobar el estudio de pruebas realizado del balanceador de carga mediante el
controlador POX en el capítulo 3.3. Análisis del balanceador de carga.
29
Desarrollo
2.6. Firewall
En el escenario se ha elegido utilizar Firewall Builder 19 como sistema cortafuegos ya que
proporciona una interfaz gráfica y profesional al usuario para la configuración de políticas
de seguridad. Sin embargo, es posible utilizar cualquier otro software de seguridad como por
ejemplo, Uncomplicated Firewall 20, que es más ligero y utiliza un pequeño número de
comandos simples para su configuración.
Para el acceso a la interfaz de Firewall Builder es necesario acceder a la máquina FW desde
el host a través de la red, y ejecutar las acciones pertinentes en la máquina remota. Por ello,
ha sido necesario la instalación del paquete xauth que permitirá mostrar la interfaz gráfica
del software en el equipo host de manera remota.
Para crear un túnel ssh a la máquina FW, y así poder conectarse a ella, se ejecutará el
siguiente comando:
# slogin -X [email protected]
[email protected]’s password: xxxx
root@FW:~#
Una vez dentro de la máquina virtual FW se accederá a la interfaz de Firewall Builder:
root@FW:~# fwbuilder
Firewall Builder GUI 5.1.0.3599
La primera vez que se accede se mostrará la siguiente pantalla de bienvenida:
Figura 2.6-1: Pantalla de bienvenida de Firewall Builder
30
Desarrollo
En ella se pulsará la opción Create new firewall, situada en el botón izquierdo de la parte
central. Tras ello se abrirá una nueva ventana solicitando información sobre el firewall a
crear. Aquí se indicará que se utilizará como software iptables 21, como se indica a
continuación:
Figura 2.6-2: Creación de un firewall (paso 1)
Tras seleccionar el botón Next, se permite realizar el descubrimiento automáticamente de las
interfaces de red del firewall mediante SNMP 22 o realizar una configuración manual. En
nuestro caso se realizará una configuración manual de las mismas.
Figura 2.6-3 Creación de un firewall (paso 2)
Para ello será necesario configurar las tres interfaces que tiene el firewall de nuestro
escenario: eth1 (10.1.1.1), eth2 (10.1.2.1) y lo (127.0.0.1).
31
Desarrollo
Figura 2.6-4: Configuración de la interfaz eth1 del firewall
Figura 2.6-5: Configuración de la interfaz eth2 del firewall
Figura 2.6-6: Configuración de la interfaz de loopback del firewall
Tras finalizar el proceso de creación del firewall ya se está en condiciones de crear, según
las necesidades, las reglas de filtrado de paquetes.
En la parte izquierda de la pantalla principal se encuentran disponibles dos librerías, Standard
y User, que muestran un árbol de objetos y servicios que se podrán añadir en las reglas
mediante la técnica conocida como arrastrar y soltar (drag and drop), por lo que será muy
fácil el rellenado de las reglas con el contenido que se desee aplicar.
Es posible crear nuevos objetos en la librería User según las necesidades del usuario. En
nuestro caso se han realizado las siguientes creaciones:
32
Desarrollo
NOMBRE DEL OBJETO
TIPO
DETALLES
Addresses
Address: 10.1.1.10
Networks
Address: 10.1.2.0
Netmask: 255.255.255.0
También se ha agregado un servicio que debe permitir el firewall en nuestro escenario, el
puerto 5001 que utiliza la herramienta iperf por defecto.
NOMBRE DEL SERVICIO
TIPO
TCP
DETALLES
Destination Port: 5001
Una vez creados todos los objetos necesarios para la política de seguridad, en la pestaña
Policy del firewall es posible definir un conjunto de reglas a aplicar en nuestro escenario,
como pueden ser las siguientes:
Figura 2.6-7: Política de reglas aplicadas en el firewall
En este momento, antes de la instalación de las reglas, se debe salvar un fichero de
configuración, con la extensión .fwb, que permite guardar no solo los nombres y definiciones
de los objetos, servicios, etc. que utilizan las reglas de filtrado, sino también las propias reglas
de filtrado. Tras ello es posible realizar la instalación de las reglas mediante la compilación
del fichero de configuración, generando un fichero, con extensión .fw, que es realmente un
archivo tipo Shell-Script que permitirá poner en marcha las reglas especificadas en el fichero
de configuración. Este proceso hay que llevarlo a cabo usando las funciones Compile e Install
que se muestran en la parte superior de la pantalla.
En el momento de instalación aparecerá una pantalla solicitando algunos datos sobre el
firewall, que se deben rellenar como se muestra en la siguiente figura:
33
Desarrollo
Figura 2.6-8: Instalación de políticas de seguridad en el firewall
Al pulsar el botón Install, se procederá a la instalación de todas las reglas configuradas y
mediante el mensaje Firewall policy successfully installed se concluye que ha sido un éxito
la instalación.
La próxima vez que sea necesario configurar nuevas reglas en el firewall será posible cargar
el fichero de configuración mediante la opción Open, y así evitar de nuevo la creación del
firewall desde cero.
Para finalizar la sesión ssh a la máquina FW es necesario ejecutar el comando exit:
root@FW:~# exit
logout
Connection to 10.1.1.1 closed.
34
Desarrollo
2.7. Clientes
Se han configurado en el escenario dos clientes, C1 y C2, además del propio host para
comprobar el correcto acceso a la aplicación web desde diferentes equipos. El sistema
operativo que tienen los clientes también carece de interfaz gráfica, como el resto de las
máquinas virtuales. Por lo que para acceder al navegador Firefox instalado en los clientes se
procederá a crear una sesión ssh, igual que en el caso del firewall.
Para crear la sesión remota a C1, por ejemplo, se introducirá el siguiente comando:
# slogin -X [email protected]
[email protected]’s password: xxxx
root@C1:~#
Una vez dentro de la máquina virtual del cliente es posible abrir el navegador:
root@C1:~# firefox
Figura 2.7-1: Navegador Firefox desde un cliente a través de un túnel ssh
De esta forma es posible visualizar la aplicación web que se ha creado desde los diferentes
clientes. Además, desde el propio navegador se puede comprobar que se está efectuando
correctamente el balanceo de carga configurado en el Controlador. Para ello, es posible
mostrar el código fuente de la página mediante el atajo de teclado Ctrl+U.
35
Desarrollo
Figura 2.7-2: Código fuente desde Firefox de la Aplicación web
En la figura anterior se muestra que la página ha sido obtenida del servidor web WWW1, ya
que en la aplicación web se configuró en el fichero index.html un comentario, que se indica
dentro del rectángulo rojo, aportando información del servidor en el que se encuentra alojada
la aplicación.
Se recuerda que es posible tener conectividad al exterior desde el cliente al cual se está
accediendo. Para ello solo será necesario utilizar el comando dhclient y abrir de nuevo el
navegador.
root@C1:~# dhclient eth99
root@C1:~# firefox
Para finalizar la sesión ssh abierta con el cliente es necesario ejecutar el comando exit:
root@C1:~# exit
logout
Connection to 10.1.1.11 closed.
36
3. Pruebas y resultados
Tras el completo desarrollo del escenario se ha decidido realizar una serie de pruebas de
algunas partes en concreto para comprobar el funcionamiento de diversos aspectos.
Las dos primeras pruebas se han centrado en el sistema de ficheros. La primera de ellas
ofrece un análisis del funcionamiento del protocolo GlusterFS, y la segunda muestra
como un servidor caído es capaz de recuperar la información tras su reanudación.
La tercera prueba se centra en el balanceador de carga, e intenta examinar el
funcionamiento del controlador SDN cuando recibe diferentes peticiones de servicio.
La cuarta prueba es una breve comprobación de la política de seguridad que se ha aplicado
en el firewall.
3.1. Análisis de GlusterFS
En esta prueba se pretende analizar fases destacables en el funcionamiento del protocolo
GlusterFS cuando ya se tiene un volumen creado en los servidores de disco. Se utilizará
el analizador de tráfico Wireshark para mostrar capturas de la información relevante en
los diferentes procesos.
Una vez creado el volumen como se ha descrito en 2.3.1. Configuración de los
servidores de disco, es necesario el montaje desde los servidores web. El montaje es un
proceso en el cual un servidor de disco indicado envía al servidor web correspondiente
toda la información referente al volumen creado.
En este caso se utilizará un volumen en réplica y se analizará el tráfico cuando el montaje
es realizado desde el servidor web WWW1. En la siguiente captura se muestra la trama
enviada por el servidor de disco NAS1 (10.1.3.21) que recibe el servidor web WWW1
(10.1.3.11) con toda la información del volumen creado a través del protocolo GlusterFS
Handshake. Esta información enviada la poseen todos los servidores de disco en el
directorio /etc/glusterd/vols/nas.
Figura 3.1-1 - Captura del envío de la información del volumen
37
Pruebas y resultados
Una vez montado el sistema de ficheros en los servidores web se procede a la creación
de un archivo, y analizando el tráfico se puede comprobar en qué determinado momento
se envía el archivo creado en el servidor web a los diferentes servidores de disco.
En esta acción cabe destacar dos procesos que realiza el protocolo GlusterFS. El primero
de ellos consiste en el envío de información general del archivo creado desde el servidor
web a los diferentes servidores de disco. Lo realiza a través de una llamada denominada
LOOKUP como se puede apreciar en la siguiente captura:
Figura 3.1-2 - Captura de llamada LOOKUP en GlusterFS
Tras la llamada LOOKUP enviada a los diferentes servidores de disco se produce una
llamada WRITE en la que envía el contenido del archivo creado. La siguiente captura
muestra este proceso:
Figura 3.1-3: Captura de la llamada WRITE en GlusterFS
En las tramas 200 y 201 se envía el contenido del archivo desde el servidor web hacia
el servidor de disco NAS1. La trama 202 es el acuse de recibo que envía el servidor de
disco NAS2 tras la recepción de la información, junto con la trama 204 que es la
contestación a la llamada WRITE producida. Lo mismo ocurre en los demás servidores
de disco, como se puede apreciar en las otras tramas capturadas.
38
Pruebas y resultados
3.2. Recuperación de un Servidor de Disco
En esta prueba se pretende deshabilitar un servidor de disco mientras un usuario se
encuentra añadiendo archivos al servidor web. Tras unos segundos se habilitará el
servidor de disco caído y se analizará el proceso de recuperación de la información
perdida.
Para la prueba se configurará un volumen en réplica, ya que en este caso todos los
servidores de disco deberán contener la misma información.
Para simular la caída del servidor de disco se empleará una de las opciones del comando
ifconfig que permite desactivar una interfaz dada.
Figura 3.2-1 - Uso del comando ifconfig down
De esta forma solamente figurará como interfaz de red la de loopback, dejando así el
servidor de disco aislado de la red.
En este momento, si un usuario agrega cualquier archivo a los servidores web no se
encontrará disponible la información en el servidor de disco caído, como se puede
apreciar en la siguiente captura:
Figura 3.2-2 - Contenido de los servidores de disco
39
Pruebas y resultados
Para habilitar de nuevo la interfaz de red del servidor de disco caído se utilizará de nuevo
el comando ifconfig:
Figura 3.2-3 - Uso del comando ifconfig up
De esta forma el servidor de disco caído se encuentra de nuevo habilitado en la red, y al
interaccionar con alguno de los servidores web enviará la información que desconocía.
El envío de la información se realiza de igual forma que el explicado en el apartado 3.1.
Análisis del protocolo GlusterFS. La siguiente captura muestra tal envío de
recuperación de la información que se produce desde el servidor web, en este caso desde
WWW1 (10.1.3.11), hacia el servidor de disco caído NAS1 (10.1.3.21)
Figura 3.2-4 - Captura de la recuperación de la información en un servidor de disco caído
40
Pruebas y resultados
3.3. Análisis del balanceador de carga
Una vez que se tiene el controlador POX funcionando, se pueden realizar diferentes
pruebas para verificar el balanceo de tráfico de las peticiones que se hacen del servicio.
En el momento de iniciar el controlador se muestra en una línea la siguiente
información:
INFO:openflow.of_01:[fa-f5-8d-5d-a8-45 1] connected
En ella se muestra que se ha reconocido un switch del tipo Open vSwitch e indica un
identificador del mismo. Es posible obtener más información sobre el switch creado
mediante los siguientes comandos:
# ovs-vsctl list bridge LAN2
_uuid
: 5d8df5fb-4a9b-45a8-b73f-a50538a410ab
controller
: [5cfbd10a-2de9-444d-934b-9d38826e4d62]
datapath_id
: "0000faf58d5da845"
datapath_type
: ""
external_ids
: {}
fail_mode
: []
flood_vlans
: []
flow_tables
: {}
ipfix
: []
mirrors
: []
name
: "LAN2"
netflow
: []
other_config
: {}
ports
: [119c5e01-30e7-431b-bb25-26d8ef48158f,
5e040e2d-8c24-48e9-8340-2e129e61af75, f8ff6d46-73a0-431a9ab5-3738c6fbdd15, fc9a6f99-a9c0-4a29-accc-166d5fe7e1e9,
fd9266ea-2a50-4496-954e-a79aeb533a07]
protocols
: []
sflow
: []
status
: {}
stp_enable
: false
# ovs-vsctl show
1b0d0349-6984-40cb-bbb1-100a50bcbf1d
Bridge "LAN2"
Controller "tcp:10.1.4.2:6633"
is_connected: true
Port "WWW3-e1"
Interface "WWW3-e1"
Port "WWW1-e1"
Interface "WWW1-e1"
Port "LAN2"
Interface "LAN2"
type: internal
Port "WWW2-e1"
Interface "WWW2-e1"
Port "FW-e2"
Interface "FW-e2"
ovs_version: "2.0.1"ports
41
Pruebas y resultados
Mediante la herramienta iperf ejecutándola desde alguno de los clientes se puede
comprobar el balanceo entre los diferentes servidores web. A continuación se muestra
una captura de la prueba:
Figura 3.3-1: Balanceo mediante iperf desde un cliente
De la misma forma, también es posible realizar la prueba con más clientes, y comprobar
que se sigue balanceando sin ningún problema:
Figura 3.3-2: Balanceo mediante iperf desde varios clientes
En las capturas anteriores se comprueba que a medida que se inicia una nueva conexión
con la dirección 10.1.2.10 se va balanceando el tráfico entre los tres servidores web, a
pesar que se estén realizando peticiones simultáneamente entre diferentes clientes.
42
Pruebas y resultados
Otra prueba se podría realizar con la herramienta curl, y así obtener el contenido de una
página web en modo texto. Como en el index.html de la aplicación web se ha añadido
un comentario indicando la procedencia del servidor, será de utilidad para comprobar el
balanceador de carga. En la siguiente captura se muestra tal comando:
Figura 3.3-3: Uso de curl para comprobar balanceo de carga
A la vista del resultado se puede asegurar que el servidor web seleccionado para obtener
el fichero index.html ha sido WWW1. Además, si se comprueba la ventana del
controlador se mostrará una traza indicando el redireccionamiento:
Figura 3.3-4: Trazas del controlador que verifican el balanceo de carga
También es posible analizar el tráfico en la interfaz del CONTROLLER y comprobar
que se está enviando información hacia la tabla de flujos del switch para la nueva
petición del servicio realizada.
Figura 3.3-5: Captura de tráfico de paquetes OpenFlow
43
Pruebas y resultados
En la captura de tráfico se aprecia que desde el controlador se está creando un nuevo
flujo como respuesta al nuevo paquete que se ha recibido desde el cliente hacia la IP
virtual de servicio. Y comprobando la tabla de flujos se verifican los flujos creados:
Figura 3.3-6: Tabla de flujos del switch virtual en LAN2
Resumiendo la información más relevante de la captura anterior de la tabla de flujos
queda de la siguiente forma:
in_port
dl_src
nw_src
tp_src
FLUJO 1
1
output
02:fd:00:00:02:02
dl_dst
10.1.1.11
nw_dst
42449
tp_dst
mod_dl_dst
mod_nw_dst
FLUJO 2
2
output
02:fd:00:00:04:01
dl_dst
10.1.2.11
nw_dst
80
tp_dst
mod_dl_src 00:00:00:11:22:33
10.1.2.10
mod_nw_src
in_port
dl_src
nw_src
tp_src
2
00:00:00:11:22:33
10.1.2.10
80
02:fd:00:00:04:01
10.1.2.11
1
02:fd:00:00:02:02
10.1.1.11
42449
Observando las tablas cabe mencionar que igual que existe una dirección IP virtual de
servicio, también existe una dirección MAC virtual, 00:00:00:11:22:33. De esta forma,
todas las peticiones del servicio se dirigen hacia la IP virtual y en el último salto se
proporciona la dirección MAC virtual.
Así, en las peticiones que se reciben desde el cliente se modifica la dirección física de
destino (mod_dl_dst) y la dirección lógica de destino (mod_nw_dst). Y en las respuestas
que se proporcionan desde el servidor web se modifica la dirección física de origen
(mod_dl_src) y la dirección lógica de origen (mod_nw_src).
44
Pruebas y resultados
En nuestro escenario el mapa físico en la red LAN2 es el siguiente:
Figura 3.3-7: Diagrama físico de LAN2
Si se realiza la misma prueba desde el navegador de alguno de los clientes y se examina
el controlador, se comprobará que se han añadido diferentes flujos para una única
petición de servicio. Esto es así porque la aplicación web está creada con marcos y se
compone de cinco ficheros .html. El navegador se encarga de abrir diferentes puertos
para los ficheros que necesita obtener y con ello el controlador balancea todas las
peticiones. En la siguiente captura se muestra lo obtenido en las trazas del controlador:
Figura 3.3-8: Trazas del controlador al realizar una petición de servicio desde un navegador
45
Pruebas y resultados
3.4. Comprobación de las políticas de seguridad
Tras la instalación de las políticas de seguridad del firewall descritas en el apartado 2.6.
Firewall, es posible realizar aquellas acciones configuradas con denegar y rechazar para
comprobar su correcto funcionamiento.
La regla 2 no permite ningún tipo de tráfico con destino el propio firewall, a excepción
si proviene desde el host mediante el servicio ssh. Por lo que se puede comprobar que
deniega ese tipo de tráfico realizando un ping desde alguno de los clientes disponibles
del escenario. En la siguiente figura se muestra el resultado:
Figura 3.4-1: Ping desde C1 hacia FW
La regla 4 no permite ningún tráfico saliente desde las máquinas situadas en LAN2
distinto de ICMP. Para comprobar el funcionamiento de ella es posible utilizar la
herramienta iperf desde uno de los servidores web, e indicar la dirección de alguno de
los clientes como dirección del servidor. Así, ejecutando el comando se indica que la
red es inalcanzable:
root@WWW1:~# iperf –c 10.1.1.11
connect failed: Network is unreachable
Si se analiza el tráfico que se encuentra en la interfaz eth1 (10.1.2.11) del servidor web
WWW1 se aprecia que desde el firewall se indica que el acceso a la red está prohibido,
tal y como se indicó en la regla mediante la acción Reject: ICMP net prohibited.
Figura 3.4-2: Captura de tráfico para comprobar la regla 4 del firewall
46
4. Conclusiones
El trabajo se ha finalizado cumpliendo las expectativas iniciales, dejando un escenario
didáctico que representa el concepto de centro de datos y computación en la nube.
A lo largo de su desarrollo se han encontrado diferentes problemas relacionados
fundamentalmente con la virtualización y la configuración de un controlador capaz de realizar
la función de balanceador de carga satisfactoriamente en el escenario propuesto. Sin embargo,
todo ello ha ayudado en el aprendizaje de diferentes conceptos, como el de las SDN.
Durante la utilización de la herramienta VNX para la gestión del escenario virtual, se han
notificado diferentes fallos y se han propuesto nuevas extensiones, como la conexión a
Internet de las máquinas virtuales de un escenario, ayudando con ello al perfeccionamiento de
la misma.
A través de este trabajo, que se ha centrado en cuestiones prácticas partiendo del desarrollo
de ideas, he aprendido que una primera propuesta a un problema no es siempre la correcta, y
por ello es necesario buscar nuevas soluciones a todos los problemas que van surgiendo hasta
encontrar una válida.
En cuanto al apartado de Pruebas y resultados se han especificado algunas de las posibles
pruebas que se pueden realizar en un escenario como el descrito con el objetivo de comprobar
y asimilar conceptos a través de los resultados, pero se pueden efectuar muchas otras.
Las líneas futuras de desarrollo que pueden partir de este trabajo son varias, ya que un
escenario como el utilizado permite profundizar en diferentes aspectos de un centro de datos.
A continuación se nombran algunas:
 La importancia que actualmente están teniendo las redes definidas por software en los
grandes centros de datos es una línea de desarrollo para seguir investigando. De la
misma forma que se ha implementado un balanceador de carga en un controlador SDN,
es posible hacerlo con otras funciones, como puede ser un firewall. Además, en este
trabajo solo se han estudiado dos tipos de controlador, por lo que ampliar el análisis
podría añadir nuevas funcionalidades al escenario.
 La evaluación de alternativas a GlusterFS para sistemas de archivos distribuidos en un
entorno de red de área local puede optimizar de la red y el uso de los servidores de disco.
Una opción puede ser Ceph.
 La creación de una base de datos alojada en una nueva máquina virtual en el escenario
puede permitir a la aplicación un control centralizado de los usuarios al almacenamiento
de ficheros.
Finalmente, mencionar que mediante la realización de este trabajo se han aplicado diferentes
conocimientos adquiridos a lo largo de la carrera que permiten ser relacionados entre ellos y
puestos en práctica en un escenario tan completo como el utilizado.
47
Bibliografía
1
Práctica final de Centro de Datos y Provisión de Servicios - E.T.S.I. Telecomunicación
2
Open vSwitch - Wikipedia
(http://en.wikipedia.org/wiki/Open_vSwitch)
3
Portal de Virtual Networks over linuX
(http://web.dit.upm.es/vnxwiki)
4
Información sobre LinuX Containers - Ubuntu Documentation
(https://help.ubuntu.com/lts/serverguide/lxc.html)
5
Copy on write – Wikipedia
(http://en.wikipedia.org/wiki/Copy-on-write)
6
Libvirt
(http://libvirt.org/index.html)
7
Virtual Networking – WikiLibvirt
(http://wiki.libvirt.org/page/VirtualNetworking)
8
GlusterFS – Gluster Community
(http://www.gluster.org/about/)
9
Filesystem Administration Guide – Gluster Community
(http://gluster.org/community/documentation/index.php/Gluster_3.2_Filesystem_Admi
nistration_Guide)
Setting up Storage Volumes – Red Hat Storage (Administration Guide)
(https://access.redhat.com/site/documentation/enUS/Red_Hat_Storage/2.0/html/Administration_Guide/index.html)
10
11
Resumen sobre GlusterFS - Escuela Latinoamericana de Redes
(http://www.eslared.org.ve/walc2012/material/track5/GlusterFS.pdf)
12
Sistema de archivos en el espacio de usuario (SAEU / FUSE) - Wikipedia
(http://es.wikipedia.org/wiki/Sistema_de_archivos_en_el_espacio_de_usuario)
13
Comando mknod - Ubuntu Manuals
(http://manpages.ubuntu.com/manpages/karmic/es/man1/mknod.1.html)
14
Fichero fstab - Wikipedia
(http://es.wikipedia.org/wiki/Fstab)
15
Sotware Defined Networking - Wikipedia
(http://en.wikipedia.org/wiki/Software-defined_networking)
49
16
Open Networking Foundation
(https://www.opennetworking.org/about/onf-overview)
17
Floodlight Documentation
(http://www.openflowhub.org/display/floodlightcontroller/Floodlight+Documentation)
18
Algoritmo Round Robin - Wikipedia
(http://es.wikipedia.org/wiki/Planificaci%C3%B3n_Round-robin)
19
Firewall Builder
(http://www.fwbuilder.org)
20
Uncomplicated Firewall - Ubuntu Wiki
(https://wiki.ubuntu.com/UncomplicatedFirewall?action=show&redirect=UbuntuFire
wall)
21
IPTables - Wikipedia
(http://es.wikipedia.org/wiki/Netfilter/iptables)
22
Simple Network Management Protocol - Wikipedia
(http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol)
50
Apéndice A: Plantilla del escenario
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?xml version="1.0" encoding="UTF-8"?>
<!-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DESARROLLO DE ESCENARIOS VIRTUALES
PARA PRÁCTICAS DE LABORATORIO SOBRE
ARQUITECTURAS DE SERVICIOS EN LA NUBE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Autor: Raúl Álvarez Pinilla
Tutor: David Fernández Cambronero
Departamento de Ingeniería de Sistemas Telemáticos (DIT)
Universidad Politécnica de Madrid
SPAIN
-->
<vnx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="/usr/share/xml/vnx/vnx-2.00.xsd">
<global>
<version>2.0</version>
<scenario_name>TFG:Arquitecturas_de_servicios_en_la_nube
</scenario_name>
<automac/>
<vm_mgmt type="none" />
<vm_defaults>
<console id="0" display="no"/>
<console id="1" display="yes"/>
<forwarding type="ip" />
</vm_defaults>
</global>
<net
<net
<net
<net
<net
name="LAN1" mode="virtual_bridge" />
name="LAN2" mode="openvswitch" controller="tcp:10.1.4.2:6633" />
name="LAN3" mode="virtual_bridge" />
name="virbr0" mode="virtual_bridge" managed="no"/>
name="MNG" mode="virtual_bridge" />
<vm name="C1" type="lxc">
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-CLIENT
</filesystem>
<if id="1" net="LAN1">
<ipv4>10.1.1.11/24</ipv4>
</if>
<if id="99" net="virbr0"/>
<route type="ipv4" gw="10.1.1.1">10.1.2.0/24</route>
</vm>
<vm name="C2" type="lxc">
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-CLIENT
</filesystem>
<if id="1" net="LAN1">
<ipv4>10.1.1.12/24</ipv4>
</if>
<if id="99" net="virbr0"/>
<route type="ipv4" gw="10.1.1.1">10.1.2.0/24</route>
</vm>
51
Apéndicé A: Plantilla dél éscénario
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<vm name="FW" type="lxc">
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-FW
</filesystem>
<if id="1" net="LAN1">
<ipv4>10.1.1.1/24</ipv4>
</if>
<if id="2" net="LAN2">
<ipv4>10.1.2.1/24</ipv4>
</if>
<if id="99" net="virbr0"/>
</vm>
<vm name="CONTROLLER" type="lxc">
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-CONTROLLER
</filesystem>
<if id="1" net="MNG">
<ipv4>10.1.4.2/24</ipv4>
</if>
<if id="99" net="virbr0"/>
</vm>
<vm name="WWW1" type="lxc">
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-WWW
</filesystem>
<if id="1" net="LAN2">
<ipv4>10.1.2.11/24</ipv4>
</if>
<if id="2" net="LAN3">
<ipv4>10.1.3.11/24</ipv4>
</if>
<if id="99" net="virbr0"/>
<route type="ipv4" gw="10.1.2.1">10.1.1.0/24</route>
<exec seq="on_boot" type="verbatim"
ostype="system">/etc/init.d/apache2 start</exec>
</vm>
<vm name="WWW2" type="lxc">
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-WWW
</filesystem>
<if id="1" net="LAN2">
<ipv4>10.1.2.12/24</ipv4>
</if>
<if id="2" net="LAN3">
<ipv4>10.1.3.12/24</ipv4>
</if>
<if id="99" net="virbr0"/>
<route type="ipv4" gw="10.1.2.1">10.1.1.0/24</route>
<exec seq="on_boot" type="verbatim"
ostype="system">/etc/init.d/apache2 start</exec>
</vm>
52
Apéndicé A: Plantilla dél éscénario
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<vm name="WWW3" type="lxc">
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-WWW
</filesystem>
<if id="1" net="LAN2">
<ipv4>10.1.2.13/24</ipv4>
</if>
<if id="2" net="LAN3">
<ipv4>10.1.3.13/24</ipv4>
</if>
<if id="99" net="virbr0"/>
<route type="ipv4" gw="10.1.2.1">10.1.1.0/24</route>
<exec seq="on_boot" type="verbatim"
ostype="system">/etc/init.d/apache2 start</exec>
</vm>
<vm name="NAS1" type="lxc">
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-NAS
</filesystem>
<if id="1" net="LAN3">
<ipv4>10.1.3.21/24</ipv4>
</if>
<if id="99" net="virbr0"/>
</vm>
<vm name="NAS2" type="lxc">
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-NAS
</filesystem>
<if id="1" net="LAN3">
<ipv4>10.1.3.22/24</ipv4>
</if>
<if id="99" net="virbr0"/>
</vm>
<vm name="NAS3" type="lxc">
<filesystem type="cow">
/usr/share/vnx/filesystems/rootfs_lxc_ubuntu-NAS
</filesystem>
<if id="1" net="LAN3">
<ipv4>10.1.3.23/24</ipv4>
</if>
<if id="99" net="virbr0"/>
</vm>
<host>
<hostif net="LAN1">
<ipv4>10.1.1.10/24</ipv4>
</hostif>
<hostif net="MNG">
<ipv4>10.1.4.1/24</ipv4>
</hostif>
<route type="ipv4" gw="10.1.1.1">10.1.0.0/16</route>
</host>
</vnx>
53
Apéndice B: Scripts del sistema de ficheros
Mediante los siguientes scripts se pretende aclarar el proceso de configuración del
sistema de ficheros, y de esta forma proporcionar una guía a seguir.
B.1. Script para la creación del sistema de ficheros
El siguiente script pretende automatizar el proceso de configuración en los servidores
de disco para la creación de un cierto volumen. Se permitirá al usuario elegir entre un
volumen distribuido, en réplica, o seccionado. Además, se dará la opción de eliminar
un volumen ya creado.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/bash
# Definición de funciones
function anadirServidores(){
lxc-attach -n NAS2 -- bash -c "echo UUID=361fbfb4-fa61-49d1-90961b8a481476b6 > /etc/glusterd/glusterd.info"
lxc-attach -n NAS3 -- bash -c "echo UUID=6763582b-7fc7-4767a7d7e289709c0ba7 > /etc/glusterd/glusterd.info"
lxc-attach -n NAS2 -- service glusterfs-server restart
lxc-attach -n NAS3 -- service glusterfs-server restart
sleep 2
lxc-attach -n NAS1 -- gluster peer probe 10.1.3.22
lxc-attach -n NAS1 -- gluster peer probe 10.1.3.23
echo
lxc-attach -n NAS1 -- gluster peer status
echo
}
function compruebaVolumen(){
com=$( lxc-attach -n NAS1 -- gluster volume info | grep "No
volumes present" )
if [ "$com" ]
then
echo "No hay ningún volumen creado"
else
echo "Hay algún volumen creado"
echo "Elimínelo e inténtelo de nuevo"
exit 0
fi
}
function iniciarVolumen(){
lxc-attach -n NAS1 -- gluster volume start nas
lxc-attach -n NAS1 -- gluster volume info
}
function eliminarVolumen(){
lxc-attach -n NAS1 -- bash -c "gluster volume stop nas"
lxc-attach -n NAS1 -- bash -c "gluster volume delete nas"
}
55
Apéndicé B: Scripts dél sistéma dé fichéros
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#Programa principal
clear
echo "CONFIGURACIÓN DE LOS SERVIDORES DE DISCO"
echo "Seleccione la opción a realizar:"
echo "1 - Crear volumen"
echo "2 - Eliminar volumen"
echo -n "Opción seleccionada: "
read opcion
clear
case $opcion in
"1")
echo "CREACION DEL VOLUMEN"
compruebaVolumen
echo "Seleccione el tipo de volumen deseado:"
echo "1 - Volumen distribuido"
echo "2 - Volumen en réplica"
echo "3 - Volumen seccionado"
echo -n "Opción seleccionada: "
read tipo
clear
case $tipo in
"1")
echo "CREACION DE VOLUMEN DISTRIBUIDO"
anadirServidores
lxc-attach -n NAS1 -- gluster volume create nas 10.1.3.21:/nas
10.1.3.22:/nas 10.1.3.23:/nas
iniciarVolumen
;;
"2")
echo "CREACION DE VOLUMEN EN REPLICA"
anadirServidores
lxc-attach -n NAS1 -- gluster volume create nas replica 3
10.1.3.21:/nas 10.1.3.22:/nas 10.1.3.23:/nas
iniciarVolumen
;;
"3")
echo "CREACION DE VOLUMEN SECCIONADO"
anadirServidores
lxc-attach -n NAS1 -- gluster volume create nas stripe 3
10.1.3.21:/nas 10.1.3.22:/nas 10.1.3.23:/nas
iniciarVolumen
;;
esac
;;
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
"2")
echo "ELIMINACION DEL VOLUMEN"
eliminarVolumen
;;
esac
56
Apéndicé B: Scripts dél sistéma dé fichéros
B.2. Script para el montaje del sistema de ficheros
Con la ejecución de este script se pretende automatizar el proceso de montaje del
sistema de ficheros que hay que realizar desde los servidores web. Se permitirá al
usuario la opción de montar el sistema de ficheros como de desmontarlo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/bin/bash
# Definición de funciones
function creaFstab(){
echo -e "# UNCONFIGURED FSTAB FOR BASE SYSTEM
/etc/glusterfs/datastore.vol /mnt/nas glusterfs
rw,allow_other,default_permissions,max_read=131072 0 0" > /tmp/fstab
}
function creaDatastore(){
echo "volume remote1
type protocol/client
option transport-type tcp
option remote-host 10.1.3.21
option remote-subvolume /nas
end-volume
volume remote2
type protocol/client
option transport-type tcp
option remote-host 10.1.3.22
option remote-subvolume /nas
end-volume
volume remote3
type protocol/client
option transport-type tcp
option remote-host 10.1.3.23
option remote-subvolume /nas
end-volume
volume replicate
type cluster/replicate
subvolumes remote1 remote2 remote3
end-volume
volume writebehind
type performance/write-behind
option window-size 1MB
subvolumes replicate
end-volume
volume cache
type performance/io-cache
option cache-size 512MB
subvolumes writebehind
end-volume" > /tmp/datastore.vol
}
57
Apéndicé B: Scripts dél sistéma dé fichéros
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
function copiaFstab(){
cp /tmp/fstab /var/lib/lxc/WWW1/rootfs/etc
cp /tmp/fstab /var/lib/lxc/WWW2/rootfs/etc
cp /tmp/fstab /var/lib/lxc/WWW3/rootfs/etc
}
function copiaDatastore(){
cp /tmp/datastore.vol /var/lib/lxc/WWW1/rootfs/etc/glusterfs
cp /tmp/datastore.vol /var/lib/lxc/WWW2/rootfs/etc/glusterfs
cp /tmp/datastore.vol /var/lib/lxc/WWW3/rootfs/etc/glusterfs
}
function compruebaNAS(){
com=$( lxc-attach -n NAS1 -- gluster volume info | grep "No
volumes present" )
if [ "$com" ]
then
echo "No hay ningún volumen creado"
echo "Cree un nuevo volumen e inténtelo de nuevo"
exit 0
fi
}
function compruebaMontaje(){
com=$( lxc-attach -n WWW1 -- df -h | grep "datastore.vol" )
if [ "$com" ]
then
echo "Ya se encuentra el sistema de ficheros montado"
exit 0
fi
}
function creaDirectorios(){
carpeta1=/var/lib/lxc/WWW1/rootfs/mnt/nas
carpeta2=/var/lib/lxc/WWW2/rootfs/mnt/nas
carpeta3=/var/lib/lxc/WWW3/rootfs/mnt/nas
if [ ! -d $carpeta1 ]
then
mkdir $carpeta1
fi
if [ ! -d $carpeta2 ]
then
mkdir $carpeta2
fi
if [ ! -d $carpeta3 ]
then
mkdir $carpeta3
fi
}
function compruebaFUSE(){
com1=$( lxc-attach -n WWW1 -- ls /dev | grep "fuse" )
if [ "$com1" ]
then
echo "Módulo FUSE ya instalado en WWW1"
else
echo "Instalando módulo FUSE en WWW1..."
lxc-attach -n WWW1 -- mknod -m 666 /dev/fuse c 10 229
fi
58
Apéndicé B: Scripts dél sistéma dé fichéros
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
com2=$( lxc-attach -n WWW2 -- ls /dev | grep "fuse" )
if [ "$com2" ]
then
echo "Módulo FUSE ya instalado en WWW2"
else
echo "Instalando módulo FUSE en WWW2..."
lxc-attach -n WWW2 -- mknod -m 666 /dev/fuse c 10 229
fi
com3=$( lxc-attach -n WWW3 -- ls /dev | grep "fuse" )
if [ "$com3" ]
then
echo "Módulo FUSE ya instalado en WWW3"
else
echo "Instalando módulo FUSE en WWW3..."
lxc-attach -n WWW3 -- mknod -m 666 /dev/fuse c 10 229
fi
}
function asignaPermisos(){
lxc-attach -n WWW1 -- chmod
lxc-attach -n WWW2 -- chmod
lxc-attach -n WWW3 -- chmod
lxc-attach -n WWW1 -- chmod
lxc-attach -n WWW2 -- chmod
lxc-attach -n WWW3 -- chmod
777
777
777
777
777
777
/mnt/nas
/mnt/nas
/mnt/nas
/tmp
/tmp
/tmp
}
#Programa principal
clear
echo "MONTAR/DESMONTAR EL SISTEMA DE FICHEROS"
echo "Seleccione la opción a realizar:"
echo "1 - Montar sistema de ficheros"
echo "2 - Desmontar sistema de ficheros"
echo -n "Opción seleccionada: "
read opcion
clear
case $opcion in
"1")
echo "MONTAJE DEL SISTEMA DE FICHEROS"
compruebaNAS
compruebaMontaje
creaFstab
creaDatastore
copiaFstab
copiaDatastore
creaDirectorios
compruebaFUSE
lxc-attach -n WWW1 -- mount -a
lxc-attach -n WWW2 -- mount -a
lxc-attach -n WWW3 -- mount -a
echo "Sistema de ficheros montado correctamente"
;;
59
Apéndicé B: Scripts dél sistéma dé fichéros
165
166
167
168
169
170
171
172
"2")
echo "DESMONTAJE DEL SISTEMA DE FICHEROS"
lxc-attach -n WWW1 -- umount -l /mnt/nas
lxc-attach -n WWW2 -- umount -l /mnt/nas
lxc-attach -n WWW3 -- umount -l /mnt/nas
echo "Sistema de ficheros desmontado correctamente"
;;
esac
60
Apéndice C: Código de la Aplicación Web
A continuación se muestran los diferentes archivos que han sido creados para la
Aplicación Web del centro de datos.
 index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~ Servidor Web X (10.1.2.1X) ~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
<html>
<head>
<title>Almacenamiento de ficheros</title>
</head>
<frameset rows="86,*,45z" frameborder="0" border="0"
framespacing="0">
<frame name="topNav" src="webTop_nav.html">
<frameset cols="200,*" frameborder="0" border="0"
framespacing="0">
<frame name="menu" src="webMenu.html" marginheight="0"
marginwidth="0" scrolling="auto" noresize>
<frame name="content" src="webContent.html"
marginheight="0" marginwidth="0" scrolling="auto" noresize>
</frameset>
<frame name="footer" src="webFooter.html">
</frameset>
</html>
 webTop_nav.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
<head>
<meta charset="utf-8">
<title>Top Nav</title>
<style type="text/css">
body {
font-family:verdana,arial,sans-serif;
font-size:14.2pt;
margin:30px;
background-color:#a08029;}
</style>
</head>
<body>
<h3>Desarrollo de Escenarios Virtuales para Prácticas de
Laboratorio sobre Arquitecturas de Servicios en la Nube</h3>
</body>
</html>
61
Apéndicé C: Codigo dé la Aplicacion Wéb
 webMenu..html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<head>
<title>Menu</title>
<style type="text/css">
body {
font-family:verdana,arial,sans-serif;
font-size:10pt;
margin:15px;
background-color:#ff9900;}
</style>
</head>
<body>
<p><a href="webContent.html" target="content">INICIO</a></p>
<p><a href="pagSubida.php" target="content">Subida de
ficheros</a></p>
<p><a href="pagDescarga.php" target="content">Descarga de
ficheros</a></p>
<p><a href="pagBorrado.php" target="content">Borrado de
ficheros</a></p>
</body>
</html>
 webContent.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<head>
<meta charset="utf-8">
<title>Content</title>
<style type="text/css">
body {
font-family:verdana,arial,sans-serif;
font-size:10pt;
margin:30px;
background-color:#ffcc00;}
</style>
</head>
<body>
<h1>Bienvenido</h1>
<h2>Desde esta página web podrá realizar el almacenamiento de
ficheros</h2>
<ul>
<li><a href="pagSubida.php" target="content">Subida de
ficheros</a></li><p/>
<li><a href="pagDescarga.php" target="content">Descarga de
ficheros</a></li><p/>
<li><a href="pagBorrado.php" target="content">Borrado de
ficheros</a></li>
</ul>
</body>
</html>
62
Apéndicé C: Codigo dé la Aplicacion Wéb
 webFooter.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<html>
<head>
<meta charset="utf-8">
<title>Footer</title>
<style type="text/css">
body {
font-family:verdana,arial,sans-serif;
font-size:10pt;
margin:10px;
text-align: right;
background-color:black;
color:white;}
</style>
</head>
<body>
<table width="100%">
<tr>
<td align="left"><strong>Raúl Álvarez
Pinilla</strong></td>
<td align="right"><strong>Escuela Técnica Superior
de Ingenieros de Telecomunicación (UPM)</strong></td>
</tr>
</table>
</body>
</html>
63
Apéndicé C: Codigo dé la Aplicacion Wéb
 pagSubida.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<html>
<head>
<title>Subida</title>
<style type="text/css">
body {
font-family:verdana,arial,sans-serif;
font-size:10pt;
margin:30px;
background-color:#a1f861;}
</style>
<script type="text/javascript" src="funciones.js"></script>
</head>
<body>
<h1>Subida de ficheros</h1>
<ol>
<li value="1">
<span><input id="archivos" type="file"
name="archivos[]" multiple="multiple"/></span><p/>
</li>
<li>
<button onclick="subido();"/>Subir</button>
</li>
</ol>
</body>
</html>
 scriptSubir.php
1
2
3
4
5
6
7
8
9
10
11
12
<?php
$ruta="/mnt/nas/";
foreach($_FILES as $key)
{
if($key["error"]==UPLOAD_ERR_OK){
move_uploaded_file($key["tmp_name"],$ruta.$key["name"]);
echo "Subida realizada correctamente\n";
}else{
echo $key["Error en la subida"];
}
}
?>
64
Apéndicé C: Codigo dé la Aplicacion Wéb
 pagDescarga.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<html>
<head>
<title>Descarga</title>
<style type="text/css">
body {
font-family:verdana,arial,sans-serif;
font-size:10pt;
margin:30px;
background-color:#58FAD0;}
</style>
<script type="text/javascript" src="funciones.js"></script>
</head>
<body>
<h1>Descarga de ficheros</h1>
<?php
$ruta="/mnt/nas/";
$archivos=scandir($ruta);
$lista="";
foreach($archivos as $value){
if($value!="."&&$value!=".."){
$lista.=
'<form
action="javascript:getFile(\''.$value.'\');">
<input type="submit" value="Descargar
archivo =>"><a>'.$value.'</a>
</form><p/>';
}
}
echo $lista;
?>
</body>
</html>
 scriptBajar.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$ruta="/mnt/nas/";
$name=$_GET["file"];
$archivo=$ruta.$name;
if(file_exists($archivo)){
header("Content-Description: File transfer");
header("Content-Type: application/octect-stream");
header("Content-Disposition: attachment;
filename=".basename($archivo));
header("Content-Transfer-Encoding: binary");
header("Expires: 0");
header("Cache-Control: must-revalidate");
header("Pragma: public");
ob_clean();
flush();
readfile($archivo);
exit;
}
?>
65
Apéndicé C: Codigo dé la Aplicacion Wéb
 pagBorrado.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<html>
<head>
<title>Borrado</title>
<style type="text/css">
body {
font-family:verdana,arial,sans-serif;
font-size:10pt;
margin:30px;
background-color:#F5A9A9;}
</style>
<script type="text/javascript" src="funciones.js"></script>
</head>
<body>
<h1>Borrado de ficheros</h1>
<?php
$ruta="/mnt/nas/";
$archivos=scandir($ruta);
$lista="";
foreach($archivos as $value){
if($value!="."&&$value!=".."){
$lista.=
'<form
action="javascript:deleteFile(\''.$value.'\');">
<input type="submit" value="Borrar archivo
=>"><a>'.$value.'</a>
</form><p/>';
}
}
echo $lista;
?>
</body>
</html>
 scriptBorrar.php
1
2
3
4
5
<?php
$ruta="/mnt/nas/";
unlink($ruta.$_POST["file"]);
echo $_POST["file"]." ha sido borrado";
?>
66
Apéndicé C: Codigo dé la Aplicacion Wéb
 funciones.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//SUBIDA DE FICHEROS
function subido(){
var archivo =document.getElementById("archivos").files;
if(archivo.length==0){
alert("No se ha subido ningún fichero");
return;
}
createFile(archivo);
}
function createFile(archivo){
var xhr=new XMLHttpRequest();
var data=new FormData();
for (var i=0; i<archivo.length; i++){
data.append("archivo"+i,archivo[i]);
}
xhr.open("POST", "scriptSubir.php", true);
xhr.onreadystatechange= function(){
if(xhr.readyState!=4){
return;
}
if(xhr.status==200){
alert(xhr.responseText);
location.href="pagDescarga.php";
}
};
xhr.send(data);
}
//DESCARGA DE FICHEROS
function getFile(file){
location.href="scriptBajar.php?file="+file;
}
//BORRADO DE FICHEROS
function deleteFile(file){
var xhr=new XMLHttpRequest();
var data=new FormData();
data.append("file",file);
xhr.open("POST", "scriptBorrar.php", true);
xhr.onreadystatechange= function(){
if(xhr.readyState!=4){
return;
}
if(xhr.status==200){
alert(xhr.responseText);
location.href="pagBorrado.php";
}
}
xhr.send(data);
}
67
68
Apéndice D: Balanceador de carga
(Controlador POX)
El fichero pox/misc/ip_loadbalancer.py es el encargado de la función de balanceador de
carga del escenario. Viene por defecto tras la instalación del controlador pero es
necesario realizar diversos cambios para el correcto funcionamiento en el escenario.
A continuación se muestra su contenido:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#
#
#
#
#
#
#
#
#
#
#
#
#
Copyright 2013 James McCauley
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
A very sloppy IP load balancer.
Run it with --ip=<Service IP> --servers=IP1,IP2,...
Please submit improvements. :)
"""
from pox.core import core
import pox
log = core.getLogger("iplb")
from
from
from
from
from
pox.lib.packet.ethernet import ethernet, ETHER_BROADCAST
pox.lib.packet.ipv4 import ipv4
pox.lib.packet.arp import arp
pox.lib.addresses import IPAddr, EthAddr
pox.lib.util import str_to_bool, dpid_to_str
import pox.openflow.libopenflow_01 as of
import time
import random
FLOW_IDLE_TIMEOUT = 5
FLOW_MEMORY_TIMEOUT = 60 * 5
selected_server=0
class MemoryEntry (object):
"""
Record for flows we are balancing
69
Apéndicé D: Balancéador dé carga (Controlador POX)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
Table entries in the switch "remember" flows for a period of time, but
rather than set their expirations to some long value (potentially leading
to lots of rules for dead connections), we let them expire from the
switch relatively quickly and remember them here in the controller for
longer.
Another tactic would be to increase the timeouts on the switch and use
the Nicira extension which can match packets with FIN set to remove them
when the connection closes.
"""
def __init__ (self, server, first_packet, client_port):
self.server = server
self.first_packet = first_packet
self.client_port = client_port
self.refresh()
def refresh (self):
self.timeout = time.time() + FLOW_MEMORY_TIMEOUT
@property
def is_expired (self):
return time.time() > self.timeout
@property
def key1 (self):
ethp = self.first_packet
ipp = ethp.find('ipv4')
tcpp = ethp.find('tcp')
return ipp.srcip,ipp.dstip,tcpp.srcport,tcpp.dstport
@property
def key2 (self):
ethp = self.first_packet
ipp = ethp.find('ipv4')
tcpp = ethp.find('tcp')
return self.server,ipp.srcip,tcpp.dstport,tcpp.srcport
class iplb (object):
"""
A simple IP load balancer
Give it a service_ip and a list of server IP addresses. New TCP flows
to service_ip will be randomly redirected to one of the servers.
We probe the servers to see if they're alive by sending them ARPs.
"""
def __init__ (self, connection, service_ip, servers = []):
self.service_ip = IPAddr(service_ip)
self.servers = [IPAddr(a) for a in servers]
self.con = connection
#self.mac = self.con.eth_addr
self.mac = EthAddr("00:00:00:11:22:33")
self.live_servers = {} # IP -> MAC,port
70
Apéndicé D: Balancéador dé carga (Controlador POX)
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
try:
self.log = log.getChild(dpid_to_str(self.con.dpid))
except:
# Be nice to Python 2.6 (ugh)
self.log = log
self.outstanding_probes = {} # IP -> expire_time
# How quickly do we probe?
self.probe_cycle_time = 5
# How long do we wait for an ARP reply before we consider a server dead?
self.arp_timeout = 3
# We remember where we directed flows so that if they start up again,
# we can send them to the same server if it's still up. Alternate
# approach: hashing.
self.memory = {} # (srcip,dstip,srcport,dstport) -> MemoryEntry
self._do_probe() # Kick off the probing
# As part of a gross hack, we now do this from elsewhere
#self.con.addListeners(self)
def _do_expire (self):
"""
Expire probes and "memorized" flows
Each of these should only have a limited lifetime.
"""
t = time.time()
# Expire probes
for ip,expire_at in self.outstanding_probes.items():
if t > expire_at:
self.outstanding_probes.pop(ip, None)
if ip in self.live_servers:
self.log.warn("Server %s down", ip)
del self.live_servers[ip]
# Expire old flows
c = len(self.memory)
self.memory = {k:v for k,v in self.memory.items()
if not v.is_expired}
if len(self.memory) != c:
self.log.debug("Expired %i flows", c-len(self.memory))
def _do_probe (self):
"""
Send an ARP to a server to see if it's still up
"""
self._do_expire()
server = self.servers.pop(0)
self.servers.append(server)
71
Apéndicé D: Balancéador dé carga (Controlador POX)
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
r = arp()
r.hwtype = r.HW_TYPE_ETHERNET
r.prototype = r.PROTO_TYPE_IP
r.opcode = r.REQUEST
r.hwdst = ETHER_BROADCAST
r.protodst = server
r.hwsrc = self.mac
r.protosrc = self.service_ip
e = ethernet(type=ethernet.ARP_TYPE, src=self.mac,
dst=ETHER_BROADCAST)
e.set_payload(r)
self.log.debug("ARPing for %s", server)
msg = of.ofp_packet_out()
msg.data = e.pack()
msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
msg.in_port = of.OFPP_NONE
self.con.send(msg)
self.outstanding_probes[server] = time.time() + self.arp_timeout
core.callDelayed(self._probe_wait_time, self._do_probe)
@property
def _probe_wait_time (self):
"""
Time to wait between probes
"""
r = self.probe_cycle_time / float(len(self.servers))
r = max(.25, r) # Cap it at four per second
return r
def _pick_server (self, key, inport):
"""
Pick a server for a (hopefully) new connection, round robin based
"""
global selected_server
a=self.live_servers.keys()
if selected_server<=-(len(self.live_servers)):
selected_server=0
#print selected_server, len(self.live_servers)
b=a[selected_server]
selected_server-=1
return b
#return random.choice(self.live_servers.keys())
def _handle_PacketIn (self, event):
inport = event.port
packet = event.parsed
def drop ():
if event.ofp.buffer_id is not None:
# Kill the buffer
msg = of.ofp_packet_out(data = event.ofp)
self.con.send(msg)
return None
tcpp = packet.find('tcp')
72
Apéndicé D: Balancéador dé carga (Controlador POX)
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
if not tcpp:
arpp = packet.find('arp')
if arpp:
# Handle replies to our server-liveness probes
if arpp.opcode == arpp.REPLY:
if arpp.protosrc in self.outstanding_probes:
# A server is (still?) up; cool.
del self.outstanding_probes[arpp.protosrc]
if (self.live_servers.get(arpp.protosrc, (None,None))
== (arpp.hwsrc,inport)):
# Ah, nothing new here.
pass
else:
# Ooh, new server.
self.live_servers[arpp.protosrc] = arpp.hwsrc,inport
self.log.info("Server %s up", arpp.protosrc)
return
# Not TCP and not ARP.
return drop()
Don't know what to do with this.
Drop it.
# It's TCP.
ipp = packet.find('ipv4')
if ipp.srcip in self.servers:
# It's FROM one of our balanced servers.
# Rewrite it BACK to the client
key = ipp.srcip,ipp.dstip,tcpp.srcport,tcpp.dstport
entry = self.memory.get(key)
if entry is None:
# We either didn't install it, or we forgot about it.
self.log.debug("No client for %s", key)
return drop()
# Refresh time timeout and reinstall.
entry.refresh()
#self.log.debug("Install reverse flow for %s", key)
# Install reverse table entry
mac,port = self.live_servers[entry.server]
actions = []
actions.append(of.ofp_action_dl_addr.set_src(self.mac))
actions.append(of.ofp_action_nw_addr.set_src(self.service_ip))
actions.append(of.ofp_action_output(port = entry.client_port))
match = of.ofp_match.from_packet(packet, inport)
msg = of.ofp_flow_mod(command=of.OFPFC_ADD,
idle_timeout=FLOW_IDLE_TIMEOUT,
hard_timeout=of.OFP_FLOW_PERMANENT,
data=event.ofp,
actions=actions,
match=match)
self.con.send(msg)
73
Apéndicé D: Balancéador dé carga (Controlador POX)
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
elif ipp.dstip == self.service_ip:
# Ah, it's for our service IP and needs to be load balanced
# Do we already know this flow?
key = ipp.srcip,ipp.dstip,tcpp.srcport,tcpp.dstport
entry = self.memory.get(key)
if entry is None or entry.server not in self.live_servers:
# Don't know it (hopefully it's new!)
if len(self.live_servers) == 0:
self.log.warn("No servers!")
return drop()
# Pick a server for this flow
server = self._pick_server(key, inport)
self.log.info("Directing from %s (%s) to %s (%s)",
ipp.srcip,tcpp.srcport,server,tcpp.dstport)
entry = MemoryEntry(server, packet, inport)
self.memory[entry.key1] = entry
self.memory[entry.key2] = entry
# Update timestamp
entry.refresh()
# Set up table entry towards selected server
mac,port = self.live_servers[entry.server]
actions = []
actions.append(of.ofp_action_dl_addr.set_dst(mac))
actions.append(of.ofp_action_nw_addr.set_dst(entry.server))
actions.append(of.ofp_action_output(port = port))
match = of.ofp_match.from_packet(packet, inport)
msg = of.ofp_flow_mod(command=of.OFPFC_ADD,
idle_timeout=FLOW_IDLE_TIMEOUT,
hard_timeout=of.OFP_FLOW_PERMANENT,
data=event.ofp,
actions=actions,
match=match)
self.con.send(msg)
# Remember which DPID we're operating on (first one to connect)
_dpid = None
def launch (ip, servers):
servers = servers.replace(","," ").split()
servers = [IPAddr(x) for x in servers]
ip = IPAddr(ip)
# Boot up ARP Responder
from proto.arp_responder import launch as arp_launch
arp_launch(eat_packets=False,**{str(ip):True})
import logging
logging.getLogger("proto.arp_responder").setLevel(logging.WARN)
def _handle_ConnectionUp (event):
global _dpid
74
Apéndicé D: Balancéador dé carga (Controlador POX)
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
if _dpid is None:
log.info("IP Load Balancer Ready.")
core.registerNew(iplb, event.connection, IPAddr(ip), servers)
_dpid = event.dpid
if _dpid != event.dpid:
log.warn("Ignoring switch %s", event.connection)
else:
log.info("Load Balancing on %s", event.connection)
# Gross hack
core.iplb.con = event.connection
event.connection.addListeners(core.iplb)
core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp)
75