Microordenadores - Desarrollos modernos para sistemas retro

Escalado horizontal resiliente en OpenBSD
18 de Noviembre de 2016

La disponibilidad y la velocidad de carga son muy importantes para el éxito de un sitio web. Aprende a configurar un sistema redundante y con balanceo de carga usando exclusivamente herramientas incluidas en la instalación base de OpenBSD.

Servidores web redundantes con balanceo de carga y failover

Hay dos tipos de escalado: horizontal y vertical. El horizontal es más barato porque la relación entre el gasto y el rendimiento sigue una proporción lineal.

Con este método podrás configurar un sistema redundante y con balanceo de carga para optimizar tu web y hacerla más estable usando exclusivamente herramientas incluidas en la instalación base de OpenBSD:

Aunque esta configuración funciona bien en OpenBSD 6, es posible que haya algunas incorrecciones, por lo que es más que recomendable leer las páginas de manual para conseguir la información más actualizada.

Cómo funciona

  1. Cuando se solicita la IP de www.tudominio.com, el servidor DNS devuelve varias direcciones IP.
  2. El navegador (la gran mayoría de ellos) usa una de ellas, y en caso de que no esté disponible, automáticamente usa la otra.
  3. Ambos servidores web tienen el servidor web (como Apache, Nginx o httpd) escuchando al puerto 8080, tanto para IPv6 como para IPv6.
  4. Dependiendo de la carga, relayd (escuchando en el puerto 80) redirige la petición al servidor más adecuado dependiendo de la carga, devolviendo la respuesta al cliente.

Configurar IPv6

La configuración depende del proveedor. En este caso usaré una dirección IPv6 con máscara de red /48. Este es mi archivo /etc/hostname.vio0:

inet 87.238.175.189 255.255.255.0
inet6 2a01:1b0:705:93cd::5e24 48
inet6 alias 2a01:1b0:705:93cd::57ee:afbd 128
!route add -inet6 default 2a01:1b0:705::1

El truco en esta configuración es configurar el alias IPv6 (con prefixlen 128). Necesitamos convertir la dirección IPv4 en IPv6 usando este prefijo para conseguir que funciona con relayd. Para hacer esto usa dc(1) para convertir cada número a hexadecimal:

$ dc
16o
87p
57
238p
EE
175p
AF
189p
BD

Estos números hexadecimales son los dos últimos bloques de la dirección alias IPv6: 2a01:1b0:705:93cd::57ee:afbd. No es necesario configurar el alias siempre que podamos asignarnos esta IP6.

Redundancia usando Round Robin DNS

Round Robin DNS es muy fácil de implementar, y consiste en asignar varias IPs a un mismo nombre de host. Aunque no es una solución perfecta, de alguna forma funciona, y siempre es mejor tener una IP extra cuando una falla a simplemente la que falla. Si el servidor rechaza la conexión, el navegador (al menos los más usados) intenta conectar a la otra IP asignada.

Para hacerlo funcionar asignamos dos IPs a las entradas @ y www de nuestro dominio:

www    IN  A     87.238.175.189
www    IN  A     89.188.9.34
@      IN  A     87.238.175.189
@      IN  A     89.188.9.34
www    IN	 AAAA  2a01:1b0:705:93cd::5e24 
www    IN  AAAA  2a01:1b0:7999:446:901e::63e2
@      IN  AAAA  2a01:1b0:705:93cd::5e24
@      IN  AAAA  2a01:1b0:7999:446:901e::63e2

Para distribuir la carga se baja el valor TTL (Time To Live) en la zona DNS a no menos de 180 segundos, ya que si se pone un valor más bajo algunos servidores lo ignoran.

De forma adicional, y si tu proveedor DNS (o lo alojas tú) es conveniente configurar DNS Failover.

Configurando los servidores web

Configura httpd(8) escuchando el puerto 8080 para IPv4 e IPv6:

server "www.servidordesdecero.com" {
        listen on * port 8080
        listen on :: port 8080
        root "/htdocs/servidordesdecero.com"
        log access servidordesdecero-access.log
        log error servidordesdecero-error.log
        log style combined
}

server "servidordesdecero.com" {
        listen on * port 8080
        listen on :: port 8080
        block return 301 "http://www.servidordesdecero.com$REQUEST_URI"
}

Configuración de relayd para balanceo de carga y servir las peticiones

La configuración es sencilla. Esto se debe hacer en los dos servidores, cambiando las variables:

ext_addr=87.238.175.189
ext_addr_ip6=2a01:1b0:705:93cd::5e24
ext_addr_ip6_alias=2a01:1b0:705:93cd::57ee:afbd

table <webhosts> { $webhost1 $webhost2 }

relay www {
        listen on $ext_addr port http 
        listen on $ext_addr_ip6 port http 
        listen on $ext_addr_ip6_alias port http 

        forward to <webhosts> port 8080 mode loadbalance check http "/" code 200 inet 
}

Observa la opción inet en la línea forward. De acuerdo a relayd.conf(5) en OpenBSD 6, si la dirección de destino solicitada es IPv6, los últimos 4 bytes o dos bloques serán usados para convertir esa dirección a IPv4. Esa es la razón por la que antes añadimos el alias IPv6.

En esta configuración es necesario añadir una página simple que devuelva un código 200 al cargar la IP de cada servidor, de forma que relayd pueda comprobar que el servidor web está funcionando. Una vez arrancados httpd y relayd en ambos servidores podemos comprobar si está funcionando usando relayctl(8):

$ doas relayctl monitor    
sync: imsg type 37 len 16 peerid 0 pid 55786
        timestamp: 1478031730, Tue Nov  1 21:22:10 2016
host_status: imsg type 36 len 48 peerid 0 pid 55786
        timestamp: 1478031730, Tue Nov  1 21:22:10 2016
        id: 1
        state: up
host_status: imsg type 36 len 48 peerid 0 pid 55786
        timestamp: 1478031730, Tue Nov  1 21:22:10 2016
        id: 2
        state: up

Sincronizando el contenido de los servidores usando rsync sobre ssh

Uso rsync para sincronizar los ficheros del servidor A al servidor B de esta forma:

#!/bin/sh
/usr/local/bin/rsync -czrpgoD --rsh="ssh -l webuser" /var/www/htdocs/ serverb:/var/www/htdocs/

Usando rsync sobre ssh no hay necesidad de usar el servidor rsyncd.


Contenido relacionado: