Mar 30, 2009

Balanceo de carga con LVS (I)

Vamos a continuar con el desarrollo del Sistema de Alta Disponibilidad y Balanceo de Carga que venimos realizando. El último capítulo que se trató fue el de la Alta Disponibilidad con Heartbeat.

LVS (Linux Virtual Server) es un proyecto destinado a implementar balanceadores de carga en sistemas de tipo GNU/Linux. LVS viene a ser un cluster de máquinas que de cara a los clientes aparecen como un único servidor.

Por lo tanto, dentro de la arquitectura que definimos en el primer artículo, cualquiera de los dos nodos frontales (HA1 o HA2) vendrían a ser los servidores virtuales, y los dos nodos traseros (LB1 y LB2), los servidores reales, los cuales estarían bajo el control del balanceador de carga (HA1 o HA2), también conocido como director.

Siguiendo el esquema de la arquitectura desarrollada, puede observase que cuando los clientes web realicen peticiones HTTP, el nodo activo (balanceador) repartirá dichas peticiones de forma equitativa a los nodos traseros (servidores reales). Éstos a su vez procesarán la petición y devolverán nuevamente la respuesta al balanceador, siendo este elemento en última instancia el que realmente retorne las consultas a los clientes.

De esta forma cada vez que llega una conexión TCP, el balanceador escoge a un servidor real basándose en un algoritmo de scheduling. LVS dispone de diversos algoritmos que trabajan en función de distintos parámetros: número de conexiones establecidas, tráfico máximo soportado por cada uno de los servidores reales, etc. Por lo tanto, el balanceador será capaz de gestionar todas las conexiones que esté reenviando.

El balanceador va a tener conocimiento en todo momento del inicio y finalización de las conexiones TCP o UDP, así como de los puertos y direcciones IP empleadas. Pero por contra, desconoce qué es lo que se hace en las capas superiores. Aquí entra en juego uno de los mayores problemas de los sistemas de balanceo, la persistencia.

Existen varios servicios que requieren que todas las conexiones abiertas por un cliente, tengan como destino el mismo servidor real. Éste es por ejemplo el caso de los protocolos HTTPS o FTP. Esta situación se conoce como persistencia de la sesión. La sesión se puede definir como el conjunto de conexiones TCP/UDP realizadas con el objetivo de mantener la correcta prestación de un determinado servicio.

Por lo tanto, LVS identificará las conexiones de cada uno de los clientes analizando las cabeceras de los protocolos IP, TCP y UDP, y aplicará métodos de persistencia basados en direcciones IP origen, con la finalidad de asegurar el correcto funcionamiento del servicio gestionado.
Existen tres tipos de topología LVS de cara al reenvío de peticiones: LVS-NAT, LVS-DR y LVS-TUN. En el caso del cluster que estamos desarrollando, seguiremos la LVS-NAT.

LVS-NAT

Cuando un paquete llega al balanceador, éste lo examina para ver si coincide con alguno de los servicios que tiene definidos en la tabla de reglas, y en caso afirmativo, reenvía la petición hacia alguno de los servidores reales basando su elección en algún algoritmo de planificación.

Para reenviar el paquete, el balanceador reescribirá la dirección IP destino por la del servidor real al que vaya dirigido el encapsulado (10.0.0.12 o 10.0.0.13). Esta nueva conexión será añadida a una tabla de sesiones y permanecerá en ella hasta que finalice o caduque su tiempo de vida.

Cuando el paquete vuelva de regreso hacia el balanceador, éste rescribirá su dirección origen para que sea transmitido con la dirección IP virtual del director (192.168.1.20).

Las principales ventajas de este tipo de esquema son su relativa facilidad, rapidez y escasos requerimientos hardware. Por contra, se pierde en escalabilidad y rendimiento.

LVS-DR

A través de este método, cuando un paquete llegue al balanceador, éste lo reenviará al servidor real que considere oportuno. Pero a diferencia del esquema anterior, no modificará la dirección IP destino del encapsulado, simplemente cambiará la dirección MAC destino para poder reenviar el paquete al servidor real. Y a su vez, el servidor real no retornará el paquete al balanceador, directamente se lo enviará al cliente a través del router de salida.

Como puede observarse en la imagen anterior, en este tipo de esquema todas las máquinas que conforman el cluster tienen la misma dirección IP virtual, pero únicamente responde a las peticiones ARP a dicha dirección IP virtual el interfaz del balanceador, con el objetivo de que el router de entrada sólo tenga conocimiento de la dirección MAC del director, y de esta forma poder enviarle siempre los paquetes entrantes.

LVS-DR es el método con mayor rendimiento, ya que como ha podido observarse enruta a nivel de enlace, y además, el flujo de datos de los clientes atraviesa al balanceador en un único sentido.

LVS-TUN

LVS-TUN es similar a LVS-DR, con la diferencia de que se pueden establecer sistemas de balanceo estando el director y los servidores reales en redes remotas. Para ello lo que se hace es establecer túneles entre el balanceador y los servidores reales, encapsulando los paquetes transmitidos a través de los túneles mediante tramas IPIP.

Este tipo de implementación permite crear sistemas de alta disponibilidad y balanceo de carga muchos más efectivos, sin tener que depender de la ubicación física de las máquinas.

A través de esta clase de infraestructura que vamos a desarrollar se optimizan los siguientes aspectos:

  • Rendimiento: tenemos una máquina que exclusivamente se encarga de repartir las peticiones, y varios servidores que atienden las peticiones que ecuánimemente les reparte el balanceador.
  • Escalabilidad: a medida que el sistema lo vaya requiriendo, se podrán ir añadiendo nuevas máquinas a la granja de servidores sin ningún tipo de problema.
  • Seguridad: por una parte, si se cae alguno de los nodos traseros el sistema seguirá funcionando correctamente debido a que el otro permanecerá levantado. Y por otra parte y en base al tipo de esquema empleado, puede verse que los dos nodos traseros (puntos más vulnerables para ser atacados) siempre estarán protegidos por el balanceador.

Mar 25, 2009

Sistema de particiones en Linux

Linux hace referencia a las particiones empleando una combinación de letras o números que conforman el siguiente esquema: /dev/xxyN.

El significado de cada uno de los elementos anteriores es el siguiente:
  • /dev/: nombre del directorio donde residirán todos los archivos de dispositivo.
  • xx: las dos primeras letras indican el tipo de dispositivo en el que residirá la partición. Normalmente se utiliza hd para discos IDE, sd para discos SCSI.
  • y: letra que indica el número de disco duro (por ejemplo /dev/hda hace referencia al primer disco duro IDE, y /dev/sdb al segundo disco duro SCSI).
  • N: número de partición.
Las particiones primarias o extendidas están numeradas del 1 al 4, y las particiones lógicas toman un número a partir del 5.

Por ejemplo, /dev/sda3 representa a la tercera partición primaria o extendida del primer disco duro SCSI, y /dev/hdb8 se corresponde con la cuarta partición lógica del segundo disco duro IDE.

Mar 17, 2009

Particiones de disco

Los discos duros desempeñan una sencilla función: almacenar los datos y ponerlos a disposición del usuario en cualquier momento.

Pero antes de poder emplearlo, es necesario darle un formato, o dicho de otra manera, construir en él un sistema de archivos (NTFS, ext2, ext3, etc.)

No todos los sistemas operativos soportan todos los formatos existentes, de ahí que hay que tener especial precaución a la hora de escoger el sistema de archivos en el que vayamos a instalar nuestro sistema operativo.

Cuando se empezaron a desarrollar los primeros sistemas de archivos, las personas no podían suponer que la capacidad de los discos aumentaría de una forma tan rápida. Esos sistemas de archivos tradicionales no estaban preparados para poder gestionar espacios superiores a un cierto límite. La solución consistió en dividir el disco físico en particiones, de tal forma que cada partición se pudiera acceder como si fuera un disco independiente.

Toda la información correspondiente a las posibles particiones de un disco se guarda en el primer sector de arranque del disco (los 512 primeros bytes), también conocido como MBR (Master Boot Record). El MBR está formado por código ejecutable y la tabla de particiones.

Cada una de las entradas de la tabla de particiones contiene información sobre los puntos de inicio y finalización de la partición, si la partición está marcada como activa y el tipo de partición.

La tabla de particiones se diseñó inicialmente para un máximo de cuatro particiones primarias, pero con el tiempo se vio que ese número era insuficiente, de ahí que surgieron las particiones extendidas.

Cada una de las cuatro posibles particiones primarias puede ser creada como extendida, y ésta a su vez puede contener infinitas particiones lógicas. Una entrada en la tabla de particiones marcada como partición extendida, contendrá un puntero que apuntará a otro sector del disco, el cual tendrá a su vez otra tabla con las particiones lógicas pertenecientes a esa partición extendida.

En la siguiente figura se muestra un disco duro dividido en dos particiones primarias, sda1 y sda2. La primera de ellas contiene un sistema operativo de tipo Windows y la segunda otro perteneciente a la familia Linux. A su vez, esta segunda partición primaria contiene tres particiones lógicas que conforman toda la estructura de ficheros del sistema Linux (/, /boot y swap).

Mar 8, 2009

Alta Disponibilidad con Heartbeat

Heartbeat es una aplicación de libre distribución disponible para los sistemas operativos de tipo Linux, FreeBSD y Solaris, que permite configurar sistemas de Alta Disponibilidad ofreciendo procesos de comunicación y monitorización de los nodos que conforman el cluster.

Continuando con el Sistema de Alta Disponibilidad y Balanceo de Carga que se está desarrollando (el último punto que se trató fue el cluster para base de datos), vamos a instalar Heartbeat en los dos nodos frontales (HA1 y HA2), configurando el nodo HA1 como activo y el nodo HA2 como pasivo.

Si recordamos el primer artículo que se desarrolló en donde se presentaba el esquema general del cluster, el sistema estaba formado por dos nodos frontales en donde sólo uno de ellos iba a estar activado (HA1), recibiendo las peticiones y balanceándolas a continuación a los dos nodos traseros. La máquina activa iba a tener dos direcciones IP virtuales configuradas (se denominan virtuales porque cuando HA1 falle, HA2 las asumirá), 192.168.1.20 y 10.0.0.20, y una serie de servicios levantados.


¿Cómo funciona todo esto? Es muy sencillo, el Heartbeat del nodo activo (HA1) enviará periódicamente "latidos" al nodo pasivo (HA2) para indicarle que sigue vivo. En caso de que el nodo pasivo no reciba los latidos, interpretará que el nodo HA1 está caído, y en consecuencia pasará a modo activo, levantando automáticamente las direcciones IP virtuales y arrancando los servicios gestionados.

Los latidos pueden ser enviados a través de cualquiera de los interfaces de red, y también como complemento y de forma redundante, a través de un cable serie.

Y con el objetivo de incrementar más aun la fiabilidad del sistema, vamos a instalar un watchdog software que se encargue de controlar a Hearbeat. Si Heartbeat se cae, el watchdog reiniciará la máquina transcurrido un minuto.

Vamos a comenzar instalando los paquetes watchdog y heartbeat en ambos nodos frontales.

~# aptitude install watchdog heartbeat

Heartbeat utiliza tres tipos de ficheros: authkeys (lugar donde se establece la contraseña compartida por los dos nodos), ha.cf (fichero de configuración de Heartbeat) y haresources (fichero donde se indica cuál será el nodo activo, así como los servicios a gestionar).

A continuación se muestra el contenido del fichero authkeys. Este archivo será idéntico en ambos nodos frontales y por seguridad, deberá tener exclusivamente permisos de lectura/escritura para el usuario root.

~# cat /etc/ha.d/authkeys
auth 1
1 md5 d2R5h4!

~# chmod 600 /etc/ha.d/authkeys

Este fichero contiene información que Heartbeat utiliza para autenticar a los miembros del cluster. La primera línea indica a Heartbeat qué clave debe utilizarse para firmar los paquetes salientes (latidos), ya que se pueden definir varias claves en el mismo archivo. La siguiente línea indica el algoritmo que se utilizará para firmar los paquetes (md5) y la propia clave privada con la que se realizará la firma (d2R5h4!).

El siguiente fichero que vamos a tratar va a ser ha.cf. Este archivo se encarga de listar los nodos del cluster (en este artículo cuando hablamos de cluster, nos estamos refiriendo al cluster de Alta Disponibilidad, es decir, los dos nodos frontales), la topología de comunicación y las características de la configuración que están habilitadas.

~# cat /etc/ha.d/ha.cf
# Archivo donde se escribirán los mensajes de debug
debugfile /var/log/ha-debug

# Archivo donde se escribirán el resto de mensajes
logfile /var/log/ha-log

# Facility a emplear por el syslog
logfacility local0

# Tiempo transcurrido entre el envío de cada uno de los latidos (segundos)
keepalive 2

# Tiempo transcurrido hasta declarar al nodo como caído (segundos)

deadtime 12

# Tiempo transcurrido antes de generar un warning (segundos)
warntime 6

# Tiempo transcurrido para comenzar a levantar los servicios (segundos)
initdead 18

# Puerto para la comunicacion UDP
udpport 694

# Interfaz utilizado para enviar los mesajes de broadcast
bcast eth0

# Interfaz y nodo al que enviar los latidos
ucast eth0 ha2

# Si el nodo se cae y se vuelve a recuperar, recuperara su rol original
auto_failback on

# Si el Heartbeat local no envía latidos en un minuto, reinicia la maquina
watchdog /dev/watchdog

# Maquinas que conforman el cluster
node ha1
node ha2

Este fichero será el mismo en ambos nodos, lo único que cambiará será la línea ucast eth0 haX, que en el caso del nodo HA1 será ucast eth0 ha2 (enviar los latidos al nodo HA2 a través del interfaz eth0) y para HA2 ucast eth0 ha1 (enviar los latidos al nodo HA1 a través del interfaz eth0).

Y ya para finalizar, el último fichero que habrá que configurar será haresources. Este archivo se utilizará para definir los recursos que Heartbeat deberá gestionar. Será el mismo para los dos nodos.

~# cat /etc/ha.d/haresources
ha1 IPaddr2::192.168.1.20 IPaddr2::10.0.0.20 mysql-ndb-mgm ldirectord::ldirectord.cf LVSSyncDaemonSwap::master mon

La línea de datos está formada por dos parámetros, el primero de ellos es el nombre o dirección IP de la máquina activa (HA1, recordar que definimos las direcciones IP asociadas al nombre de la máquina en el fichero /etc/hosts) y el segundo parámetro será la lista de recursos a gestionar. Es necesario establecer una tabulación a continuación del primer parámetro.

Dentro de la lista de recursos, Heartbeat levantará en la máquina activa las dos direcciones IP virtuales (192.168.1.20 y 10.0.0.20) y arrancará un grupo de servicios, como por ejemplo el demonio de administración del cluster MySQL (mysql-ndb-mgm). El resto de servicios serán detallados en los siguientes artículos. A su vez en la máquina pasiva, las dos direcciones IP virtuales no estarán configuradas y los servicios serán detenidos.

Los servicios definidos en haresources se lanzan de izquierda a derecha cuando Heratbeat los arranca (start), y los detiene de derecha a izquierda (stop).

Debido a que Hearbeat se encarga de la administración de dichos servicios (sus scripts de gestión residen en /etc/init.d/), habrá que eliminar todos los enlaces relacionados que se encuentren dentro del directorio /etc/rc[nivel_de_seguridad].d/. Vamos a eliminar en ambos nodos el enlace a mysql-ndb-mgm. El resto de enlaces de los otros servicios los iremos quitando a medida que vayamos viendo sus funciones en los siguientes artículos.

~# update-rc.d -f mysql-ndb-mgm remove

Cuando el sistema esté en funcionamiento (nodo HA1 activo y nodo HA2 pasivo), si hacemos la prueba de matar al demonio de Heartbeat en HA1 (~# pkill heartbeat), al visualizar el log de Heartbeat en el nodo HA2 podremos ver los siguientes mensajes:

root@ha2:~# >/var/log/ha-log ; tail -f /var/log/ha-log
WARN: node ha1: is dead
info: Dead node ha1 gave up resources.
info: Resources being acquired from ha1.
info: Link ha1:eth0 dead
....

Es decir, podremos apreciar cómo HA2 ha detectado la caída de HA1 y a continuación este último asumirá el rol de activo, levantando las dos direcciones IP virtuales y los servicios gestionados.

Para iniciar, detener o reiniciar Heartbeat se pueden emplear los siguientes comandos:

~# /etc/init.d/heartbeat start
~# /etc/init.d/heartbeat stop
~# /etc/init.d/heartbeat restart