Entrada

Balanceo de carga en Docker Swarm

Implementación de balanceo de carga en Docker Swarm utilizando Nginx Proxy Manager

Balanceo de carga en Docker Swarm

Hoy continuamos trabajando en el Homelab, y esta vez el tema es: Balanceo de carga en Docker Swarm. Utilizaremos Nginx Proxy Manager, que ya tenemos desplegado en nuestro entorno de Docker Swarm, configurado posts anteriores.

Te dejo los enlaces a ambos posts por si quieres repasarlos:

Si bien contamos con un entorno de Docker Swarm, esto no garantiza directamente ya contar con el balanceo de carga. Para esto es necesario contar con un elemento intermedio que pueda recibir una solicitud de un nombre, por ejemplo host.mydomain.com y entregarla a los hosts que sirvan este contenido.

Implementación

Para este laboratorio desplegaré dos contenedores de nginx web a ambos nodos del Swarm. Cada nginx mostrará un contenido distinto para poder identificar a cual estamos accediendo. El diagrama se vería de la siguiente forma.

Haciendo esto, podriamos consultar el nombre nginx.home.cervant.net -que utilizaremos durante este laboratorio- y obtendríamos el contenido del nginx de swarm-01 o de swarm-02.

Es importante recordar que el registro DNS nginx.home.cervant.net debe apuntar a la IP de Nginx Proxy Manager, que funcionará como proxy y balanceador de carga.

Creación de Stack

Crearemos el archivo de stack para desplegar dos replicas de nginx.

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
version: "3.8"

services:
  nginx1:
    image: nginx:latest
    deploy:
      replicas: 1
      placement:
        constraints:
          - "node.role == manager"
      restart_policy:
        condition: on-failure
    ports:
      - target: 80
        published: 8081
        mode: host
    command: /bin/sh -c 'echo "NGINX 1" > /usr/share/nginx/html/index.html && nginx -g "daemon off;"'
    networks:
      - swarm-frontend

  nginx2:
    image: nginx:latest
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == worker]
      restart_policy:
        condition: on-failure
    ports:
      - target: 80
        published: 8081
        mode: host
    command: /bin/sh -c 'echo "NGINX 2" > /usr/share/nginx/html/index.html && nginx -g "daemon off;"'
    networks:
      - swarm-frontend


networks:
  swarm-frontend:
    external: true

Ahora si voy al Swarm Cluster Visualizer de Portainer, puedo ver que ambos contenedores están operativos y cada uno en un nodo distinto del Swarm.

Configuración Nginx Proxy Manager

Como hemos lanzado el stack de nginx exponiendo el puerto 8081, deberemos asegurarnos de dirigir el tráfico a este puerto. Las IP de mis nodos Swarm son 192.168.1.121 y 192.168.1.124, por lo que nginx deberá apuntar a.

  • 192.168.1.121:8081 (swarm-01)
  • 192.168.1.124:8081 (swarm-02)

Agregaremos un nuevo Proxy Host apuntando al nodo principal y luego en la pestaña Custom locations agregaremos el nodo secundario.

Si no recuerdas como agregar un Proxy Host puedes leer el post de Nginx Proxy Manager para el paso a paso.

Acá agregamos el nombre DNS que utilizaremos y la IP de swarm-01.

Agregaremos un Custom location apuntando a la raíz (/) con la IP de swarm-02

Finalmente nos aseguraremos de que haya un certificado SSL válido para nuestro subdominio.

Al hacer pruebas vemos que los nginx de ambos nodos responden al mismo DNS que se ha creado para el balanceo de carga.

Luego de muchas pruebas me he dado cuenta que más que Load Balancing, lo que Nginx realiza es un Failover. He forzado la detención del contenedor en swarm-01 y comencé a ver el contenido desde el contenedor de swarm-02. De todas formas cumple como alta disponibilidad.

Construye, automatiza, repite. ¡Nos vemos en el próximo post!

Esta entrada está licenciada bajo CC BY 4.0 por el autor.