Balanceo de carga por DNS
Una manera sencilla de balancear la carga entre dos servidores que estén ofreciendo el mismo servicio es utilizar la resolución DNS. Utilizando entradas tipo A duplicadas en un servidor DNS es posible realizar de forma muy sencilla un balanceo de carga entre varios equipos, esto se conoce como DNS round robin. Según la Wikipedia, es una técnica de distribución de carga, balanceo de carga o tolerancia a fallos de aprovisionamiento múltiple y redundante de servidores de servicios IP, por ejemplo, servidores web o servidores FTP, mediante la gestión de nombres de dominio del sistema para hacer frente a las peticiones de los equipos cliente según un modelo estadístico adecuado.. Está definido en el RFC 1794.
Balanceo de caga DNS usando los registros A
Escenario de prueba
Vamos a montar tres máquinas:
nodo1: 10.1.1.101
nodo2: 10.1.1.102
dns: 10.1.1.103
Dos servidores web (nodo1 y nodo2) y un servidor DNS donde vamos a instalar un servidor bind9 donde tendremos definido la zona del dominio example.com
para balancear la carga entre los dos servidores web.
Configuración del servidor DNS
Vamos a utilizar el nombre www.example.com
para acceder al servidor web, por lo tanto vamos a configurar dos registros A para indicar la dirección ip de ese nombre, uno apuntará a la ip del nodo1 y el otro a la ip del nodo2. Veamos el fichero de configuración de la zona: /var/cache/bind/db.example.com
:
...
$ORIGIN example.com.
www IN A 10.1.1.101
www IN A 10.1.1.102
Prueba de funcionamiento
Podemos realizar una consulta para preguntar la ip de www.example.com
y veremos como nos ofrece las dos direcciones. El orden entre las respuestas va cambiando en las distintas peticiones:
dig @10.1.1.103 www.example.com
...
www.example.com. 86400 IN A 10.1.1.101
www.example.com. 86400 IN A 10.1.1.102
dig @10.1.1.103 www.example.com
...
www.example.com. 86400 IN A 10.1.1.102
www.example.com. 86400 IN A 10.1.1.101
Si accedemos desde un navegador web, podremos observar como se va intercalando el acceso (balanceando la carga) entre los dos nodos. Hemos configurado el ordenador desde el que estamos accediendo para que consulte a nuestro dns:
Para verlo de forma más gráfica, podemos acceder con curl
al fichero info.txt
del servidor que contiene le nombre del nodo:
while [ True ]; do curl http://www.example.com/info.txt && sleep 1 ; done
nodo1
nodo2
...
Con esta solución estamos balanceando la carga, pero no estamos consiguiendo una alta disponibilidad: en el momento que uno de los servidores web se apaga, las peticiones que vayan dirigido a él no obtendrán respuesta. Para ciertos servicios esto es un problema porque se quedarán esperando respuesta. Lo podemos ver haciendo un ping, después de apagar el nodo1:
ping www.example.com
PING www.example.com (10.1.1.102) 56(84) bytes of data.
64 bytes from nodo2.example.com (10.1.1.102): icmp_seq=1 ttl=64 time=0.275 ms
...
ping www.example.com
PING www.example.com (10.1.1.101) 56(84) bytes of data.
From ahsoka (10.1.1.1) icmp_seq=9 Destination Host Unreachable
Solucionemos este problema usando otra manera de balancear la carga por DNS:
Balanceo de caga DNS usando los registros NS
Una posible solución al problema que hemos indicado, es considerar el nombre del servicio www.example.com
como un nombre virtual, es decir será un alias (CNAME) de un nombre de un subdominio que estará delegado en dos servidores dns que instalaremos en los servidores que ofrecen el servicio (en nuestro caso en los servidores web).
El alias que vamos a configurar sería:
www.example.com IN CNAME www.http.example.com
Es decir cuando accedamos a www.example.com
estaremos accediendo a www
de un dominio delegado (a un subdominio) que será http.example.com
. Las zona de este subdominio delegado van a estar definidas en dos servidores DNS que instalaremos en nuestros nodos que ofrecen el servicio (nodo1 y nodo2). La delegación de del dominio se hará de la siguiente manera:
http.example.com IN NS nodo1.http.example.com
http.example.com IN NS nodo2.http.example.com
De esta forma al resolver el nombre www.example.com
, estaremos resolviendo el nombre www.http.example.com
, y para averiguar su ip el servidor dns tendrá que preguntar a uno de los servidores dns delegados. El servidor dns preguntará de forma alternativa a uno de los servidores dns delegados, y lo más importante, si un nodo se apaga y no puede devolver la respuesta, preguntará al otro, por lo que no tendremos cortes de servicio.
Veamos la configuración completa del servidor dns principal. El fichero /var/cache/bind/db.example.com
quedaría:
$ORIGIN example.com.
www IN CNAME www.http
http IN NS nodo1
http IN NS nodo2
Configuración de los servidores DNS delegados
Como hemos dicho en nodo1 y nodo2 tenemos que instalar un servidor DNS con autoridad para la zona http.example.com
. Para que sea más fácil de configurar vamos a instalar un servidor dnsmasq, y la configuración será la siguiente:
En el fichero /etc/dnsmasq.conf
de nodo1:
address=/www.http.example.com/10.1.1.101
En el fichero /etc/dnsmasq.conf
de nodo2:
address=/www.http.example.com/10.1.1.102
Además en los dos ficheros de configuración hemos configurado el parámetro local-ttl=0
para que no se guarde la respuesta en la cache del dns principal.
Prueba de funcionamiento
En este caso, el comportamiento depende del cliente:
- Algunos elegirán aleatóriamente qué servidor obtendrá la consulta.
- Otros simplemente harán round robin (primero le pregunta a nodo1, la siguiente pregunta va primero a nodo2,…)
- Y otros consultarán en el orden que se puso los servidores (por lo que un nodo recibirá todas las consultas).
Independientemente de como se comporte, lo importante es que si no hay respuesta de un servidor delegado, se probará a preguntar al otro.
En esta prueba comprobamos como en un primer momento está preguntando al servidor dns delegado del nodo2, cuando apagamos este nodo, las peticiones pasan al servidor dns del nodo1 y sigue accediendo al servicio. Volvemos a iniciar el nodo2, pero se sigue consultado al dns del nodo1. Cuando, finalmente, apagamos el nodo1, las consultas pasan a hacerse de nuevo al dns del nodo2. Veámoslo de manera más gráfica:
Conclusiones
En esta entrada del blog hemos visto dos maneras muy simples de balancear la carga entre servicios que corren en distintos nodos usando el DNS. Hemos visto que el balanceo de carga no conlleva la alta disponibilidad. En las próximas entradas quiero hacer una aproximación a la construcción de cluster en alta disponibilidad usando pacemaker y corosync. Finalmente cuando construyamos un cluster de alta disponibilidad activo-activo podremos usar algunas de estas técnicas de balanceo para acceder al cluster.
He desarrollado dos escenarios construido con vagrant y configurados con ansible para montar la infraestructura que hemos estudiado en esta entrada:
Leave a Comment
Your email address will not be published. Required fields are marked *