Recursos complementarios
En estas prácticas se empleará el software de virtualización VIRTUALBOX para simular los equipos GNU/Linux sobre los que se realizarán las pruebas.
alumno@pc: $ sh ejercicio-haproxy.sh
Powershell.exe -executionpolicy bypass -file ejercicio-haproxy.ps1
Notas:
$DIR_BASE
especifica donde se descargarán las imágenes y se crearán las MVs.
Por defecto en GNU/Linux será en $HOME/CDA2122 y en Windows en C:/CDA2122.
Puede modificarse antes de lanzar los scripts para hacer la instalación en otro directorio más conveniente (disco externo, etc)
.vdi.zip
de http://ccia.esei.uvigo.es/docencia/CDA/2122/practicas/ y copiarlos en el directorio anterior ($DIR_BASE
) para que el script haga el resto.
VBoxManage startvm <nombre MV>_<id>
Contiene un sistema Debian 9 con herramientas gráficas y un entorno gráfico ligero LXDE (Lighweight X11 Desktop Environment) [LXDE].
login | password |
---|---|
root | purple |
usuario | usuario |
root@datos:~# startx
Dispositivos -> Portapapeles compartido -> bidireccional
de la ventana de la máquina virtual.
Nota: para hacer más evidente el efecto del balanceo de carga, la capacidad de uso de la CPU en las dos máquinas del cluster de balanceo de carga (apache1 y apache2) está reducida al 30%.
HAProxy es un balanceador de carga que funciona como un proxy inverso (reverse proxy) repartiendo las conexiones recibidas de los clientes entre un conjunto de ”servidores reales”.
cliente <-> HAproxy
y HAproxy <-> servidor real
, sobre las que retransmite los mensajes de petición y respuesta
cliente
el balanceador HAproxy
decide a cúal de los servidores reales
se retransmitirá el tráfico de esa nueva conexión
servidor real
cliente <-> HAproxy
, Haproxy <-> servidor real
) en ambos sentidos mientras la conexión con el cliente
esté establecida
Funcionalidades
Detalles en http://cbonte.github.io/haproxy-dconv/1.7/intro.html#3
Configuración por defecto en /etc/haproxy/haproxy.cfg
Fichero de configuración organizado en secciones
user, group, chroot, setenv, ...
ca-base, ssl-default-xxx-xxx, ...
maxconn, tune.buffers.xxx, ...
mode
(tipo de proxy http
ó tcp
), timeouts, etc
frontend
(pueden definirse varios)
bind [<address>]:<port_range>
: define uno (o varios) puertos de escucha (opcionalmente también dirección IP) de un proxy inverso / balanceador
stats enable|auth|admin|scope|uri|...
: configuración de la página de estadísticas del proxy
default-backend
: nombre del backend al que por defecto se redigirán las conexiones recibidas (excepto las que se controlen mediante use_backend
)
use_backend <nombre> if|unless <condicion>
: especifica el backend
que atenderá las conexiones indicadas
en las ACL que indique la <condicion>
acl <nombre> <criterio> <valor>
: declara una lista de control y la condición sobre un criterio (src, src_port, hdr(...), ...
) que debe cumplir una conexión
backend
(pueden definirse varios)
servidores reales
a donde serán reenviadas las conexiones de los clientes ”balanceadas” por HAProxy
balance <algorithm>
: algoritmo usado para seleccionar el serividor real a usar en cada nueva conexión (roundrobin, leastconn, first, source, uri,...
)
server <name> <address>[:port] [settings ...]
: definición de cada uno de los servidores reales del backend
cookie <name> rewrite|insert|prefix ...
: habilita la ”persiscencia de sesiones” basada en el seguimiento de la cookie con el nombre indicado.
frontend
y un backend
para describir un proxy inverso completo.
Detalles en http://cbonte.github.io/haproxy-dconv/1.7/configuration.html
cliente:~# startx
apache1:~# nano /etc/apache2/apache2.conf ... KeepAlive Off ...
apache2:~# nano /etc/apache2/apache2.conf ... KeepAlive Off ...
Nota:
apache1:~# nano /var/www/html/index.html ... ... <h1> Servidor por APACHE_UNO </h1> ...
apache1:~# nano /var/www/html/sesion.php ... ... <h1> Servidor por la máquina APACHE_UNO </h1> ...
apache2:~# nano /var/www/html/index.html ... ... <h1> Servidor por APACHE_DOS </h1> ...
apache2:~# nano /var/www/html/sesion.php ... ... <h1> Servidor por la máquina APACHE_DOS </h1> ...
Notas:
Se realizarán varias pruebas de carga sobre el servidor Apache ubicado en la máquina apache1 para determinar el rendimiento que puede llegar a ofrecer una instancia única del servidor Apache.
Pasos a realizar
balanceador:~# service haproxy stop
balanceador:~# service apache2 stop
Nota: En ocasiones no tiene efecto la parada del servicio apache2, puede comprobarse si el proceso sigue en ejecución con pidof apache2 y ”matar” los posibles procesos supervivientes si fuera necesario.
balanceador:~# pidof apache2 wwww xxxx yyyy zzzz balanceador:~# kill -9 wwww xxxx yyyy zzzz
balanceador:~# echo 1 > /proc/sys/net/ipv4/ip_forward balanceador:~# iptables -P FORWARD ACCEPT balanceador:~# iptables -t nat -A PREROUTING \ --in-interface enp0s3 --protocol tcp --dport 80 \ -j DNAT --to-destination 10.10.10.11
Notas:
iptables
establece una política de aceptar por defecto en la cadena FORWARD
Normalmente esta regla no sería necesaria (por defecto el kernel arranca con una política ”aceptar por defecto” en todas las cadenas),
pero en este caso la instalación de Docker en la MV estableció un DROP
por defecto en la
cadena FORWARD
que impediría el tráfico del ejercicio.
apache1:~# service apache2 restart (ó service apache2 start)
Nota: Desde la máquina cliente [193.147.87.33] se puede abrir en un navegador web la URL http://193.147.87.47 para comprobar que el servidor está arrancado y que la redirección del puerto 80 está funcionando.
Pruebas a realizar:
cliente:~# ab -n 2000 -c 10 http://193.147.87.47/index.html cliente:~# ab -n 2000 -c 50 http://193.147.87.47/index.html
Envía 2000 peticiones HTTP sobre la URI ”estática” index.html, manteniendo, respectivamente, 10 y 50 conexiones concurrentes. ( 1 minuto)
Pruebas a realizar:
cliente:~# ab -n 250 -c 10 http://193.147.87.47/sleep.php cliente:~# ab -n 250 -c 30 http://193.147.87.47/sleep.phpEnvía 250 peticiones HTTP sobre la URI ”dinámica”, manteniendo, respectivamente, 10 y 30 conexiones concurrentes. (aprox 3-4 minutos)
En cada ejecución del comando ab se muestran las estadísticas obtenidas. Para el tipo de prueba informal que se realiza en este ejemplo, basta prestar atención a los parámetros Requests per second (num. peticiones por segundo) ó Time per request (tiempo en milisegundos para procesar cada petición).
balanceador:~# iptables -t nat -F balanceador:~# iptables -t nat -Z
balanceador:~# service apache2 stop
apache1:~# service apache2 restart (ó service apache2 start) apache2:~# service apache2 restart (ó service apache2 start)
balanceador:~# apt-get update balanceador:~# apt-get install haproxy
balanceador:~# cd /etc/haproxy balanceador:/etc/haproxy/# mv haproxy.cfg haproxy.cfg.original balanceador:/etc/haproxy/# nano haproxy.cfg
Contenido a incluir:
global daemon maxconn 256 user haproxy group haproxy defaults mode http log global timeout connect 5000ms timeout client 50000ms timeout server 50000ms frontend web_cda bind 193.147.87.47:80 mode http stats enable stats auth cda:cda default_backend servidores_cda backend servidores_cda balance roundrobin server uno 10.10.10.11:80 maxconn 128 server dos 10.10.10.22:80 maxconn 128
Define (en la sección frontend) un ”proxy inverso” de nombre web_cda que:
servidores_cda
backend
) la lista de servidores reales servidores_cda
Más detalles en Opciones de configuración HAPproxy 1.7
Antes de hacerlo es necesario habilitar en /etc/default/haproxy el arranque de HAproxy desde los scripts de inicio de Debian, estableciendo la variable ENABLED=1
balanceador:/etc/haproxy/# nano /etc/default/haproxy ... ENABLED=1
Inicio empleando el script de arranque de HAproxy (preferente)
balanceador:/etc/haproxy/# service haproxy stop # ya estaba arrancado balanceador:/etc/haproxy/# service haproxy start
balanceador:/etc/haproxy/# haproxy -d -V -f /etc/haproxy/haproxy.cfg
QupZilla
, abrir la URL en una ventana en modo ”incognito” (para evitar usar la caché del navegador)
lynx
, se puede recargar la página con [control]+R
Nota: Si no se ha deshabilitado la opción KeepAlive de Apache, es necesario esperar 5 segundos entre las recargas para que se agote el tiempo de espera para cerrar completamente la conexión HTTP y que pase a ser atendida por otro servidor.
Pruebas a realizar:
cliente:~# ab -n 2000 -c 10 http://193.147.87.47/index.html cliente:~# ab -n 2000 -c 50 http://193.147.87.47/index.html cliente:~# ab -n 250 -c 10 http://193.147.87.47/sleep.php cliente:~# ab -n 250 -c 30 http://193.147.87.47/sleep.php
Los resultados deberían de ser mejores que con la prueba anterior con un servidor Apache único (al menos en el caso del script sleep.php)
apache1:~# tail /var/log/apache2/error.log apache2:~# tail /var/log/apache2/error.log apache1:~# tail /var/log/apache2/access.log apache2:~# tail /var/log/apache2/access.log
Comprobar el contenido del fichero PHP /var/www/html/sesion.php
disponible en las máquinas apache1 [10.10.10.11] y apache2 [10.10.10.22].
Se puede verificar, accediendo desde la máquina cliente a la URL http://193.147.87.47/sesion.php
[en una ventana de navegación privada nueva] y recargándola varias veces, que el funcionamiento de las cookies de sesión cuando actúa el balanceo de carga no es el correcto.
SET_COOKIE
donde se establece el nombre y el valor de la Cookie)
COOKIE
de la cabecera de la petición HTTP) serán enviadas únicamente el servidor que estableció esa Cookie, ”desactivando” en ese caso el reparto de carga que realizaría el balanceador
Para solucionarlo es necesario configurar HAProxy para que haga el seguimiento de las cookies de sesión. De tal modo que no se aplique el balanceo de carga, asignado el mismo servidor real que estableció una cookie determinada en un parámetro SET_COOKIE
de una HTTP response
.
balanceador:/etc/haproxy/# service haproxy stop
balanceador:~# nano /etc/haproxy/haproxy.cfg
Contenido a incluir: (añadidos marcados con <- aqui)
global daemon maxconn 256 user haproxy group haproxy defaults mode http log global timeout connect 10000ms timeout client 50000ms timeout server 50000ms frontend web_cda bind 193.147.87.47:80 mode http stats enable stats auth cda:cda default_backend servidores_cda backend servidores_cda balance roundrobin cookie PHPSESSID prefix # <- aqui server uno 10.10.10.11:80 cookie ZIPI maxconn 128 # <- aqui server dos 10.10.10.22:80 cookie ZAPE maxconn 128 # <- aqui
El parámetro cookie especifica el nombre de la cookie que se usa como identificador único de la sesión del cliente (en el caso de aplicaciones web PHP se suele utilizar por defecto el nombre PHPSESSID)
ZIPI
y ZAPE
en el ejemplo)
prefix
SET_COOKIE
establece la Cookie de sesión, el cliente recibirá como valor de la Cookie el valor de la Cookie original precedido de la etiqueta del servidor que la haya establecido
[etiqueta servidor]~[cookie original]
[cookie original]
balanceador:/etc/haproxy/# service haproxy start
cliente:~# wireshark &
también es posible desde una pestaña de ”incógnito” de QupZilla
para forzar la creación
de una nueva sesión o eliminando las cookies de QupZilla
(menú Herramientas > Gestor de cookies > Eliminar todas
)
cliente:~# lynx -accept-all-cookies http://193.147.87.47/sesion.php
[control]+R
)
Verificar la estructura y valores de las cookies PHPSESSID intercambiadas
Entrega: MOOVI (práctica individual)
Fecha límite: hasta el domingo 21/11/2021