Balanceadores de carga para sistemas de orquestación

Los equilibradores de carga en los sistemas de orquestación (Kubernetes, Nomad y otros) tienen más requisitos que solo el equilibrio de carga. Primero, Load Balancer debería poder leer un directorio con una lista de servicios a los que se debe redirigir el tráfico (o, como opción, permitir que los servicios se registren para incluirlos en el tráfico). En segundo lugar, hazlo dinámicamente, porque Los sistemas de orquestación pueden en cualquier momento aumentar o disminuir el número de réplicas de servicios, o moverlas a otras direcciones en la red. Y en tercer lugar, hágalo sin detener el tráfico.

En la publicación de hoy, describiré trabajar con dos equilibradores de carga: Traefik y HAProxy. Estos equilibradores de carga tienen la capacidad de trabajar con una impresionante lista de herramientas de orquestación. Los ejemplos describirán cómo trabajar con el sistema de orquestación Nomad.

En la última publicación ya di un ejemplo de Balanceadores de carga: Fabio. Sus limitaciones: solo funciona con protocolos http / https y solo con Consul. A diferencia de Fabio, Load Balancers Traefik trabaja con una impresionante cantidad de sistemas diferentes. Aquí hay una lista parcial tomada del sitio del desarrollador: Docker, modo Swarm, Kubernetes, Marathon, Consul, Etcd, Rancher, Amazon ECS, ...

Continuaré con el ejemplo de la publicación anterior , en la que se crearon varias réplicas del servicio django.

Traefik se puede descargar del sitio del desarrollador como un archivo ejecutable para los sistemas operativos más comunes. Para integrarse con Nomad (en realidad con Consul) necesita crear un archivo de configuración:

[entryPoints] [entryPoints.http] address = ":5001" [web] address = ":8080" [consulCatalog] endpoint = "127.0.0.1:8500" domain = "consul.localhost" exposedByDefault = false prefix = "traefik" 

Y luego ejecute el comando con el archivo de configuración dado:

 traefik -c nomad/traefik.toml 

Después de eso, UI Traefik estará disponible en el puerto 8080, que aún no ha publicado ningún servicio. Hay varias formas de publicar servicios, que en última instancia hacen lo mismo: cargan datos de clave / valor en el sistema Traefik. Aprovecharemos la oportunidad para establecer pares clave / valor a través de etiquetas de servicio. Expandamos el archivo de configuración del servicio django con el parámetro tags:

 job "django-job" { datacenters = ["dc1"] type = "service" group "django-group" { count = 3 restart { attempts = 2 interval = "30m" delay = "15s" mode = "fail" } ephemeral_disk { size = 300 } task "django-job" { driver = "docker" config { image = "apapacy/tut-django:1.0.1" port_map { lb = 8000 } } resources { network { mbits = 10 port "lb" {} } } service { name = "django" tags = [ "traefik.enable=true", "traefik.frontend.entryPoints=http", "traefik.frontend.rule=Host:localhost;PathStrip:/test", "traefik.tags=exposed" ] port = "lb" check { name = "alive" type = "http" path = "/" interval = "10s" timeout = "2s" } } } } } 

En este ejemplo, el servicio se publicará en el host localhost y se montará en la ruta / test. Traefik ha desarrollado un sistema flexible y completo de reglas para configurar rutas, incluido el trabajo con expresiones regulares. La lista de parámetros para las reglas en la documentación del desarrollador.

Después de ejecutar el nomad job run nomad/django.conf se aplican nomad job run nomad/django.conf reglas y el tráfico del Load Balancer se dirigirá al servicio. En consecuencia, puede cambiar estos parámetros, implementar una nueva opción de servicio con el nomad job run nomad/django.conf , y todos los cambios se aplicarán sin molestas paradas de tráfico.

La desventaja de Traefik es que funciona con los protocolos de la familia http / https (por si acaso, noto que esta familia también incluye sockets web). Pero aún existe la posibilidad de que sea necesario trabajar con otros protocolos. Pasemos a la siguiente solución más amplia basada en HAProxy. Hace algún tiempo, HAProxy tenía problemas con la carga suave, lo que dificultaba su uso con los sistemas de orquestación (durante el reinicio, era necesario detener el movimiento de los paquetes a nivel de red). Ahora esto ya no es un problema.

Primero necesitas instalar haproxy en tu computadora. Aquí, la opción de instalar dentro del contenedor no funcionará. En haproxy, solo recientemente fue posible reiniciar el proceso en modo "soft", pero el contenedor docker todavía se detiene, ya que el segundo proceso en realidad comienza con haproxy, simplemente cambia en modo de espera, que no funciona con el docker y su principio "uno -container es un proceso ".

Para que funcione el haproxy, debe tener un archivo de configuración que contenga las reglas necesarias. Nomad (en realidad en Consul) utiliza un sistema de plantillas que puede generar configuraciones:

 global debug defaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 frontend http_front bind *:5001 stats uri /haproxy?stats default_backend http_back backend http_back balance roundrobin{{range service "django"}} server {{.Node}} {{.Address}}:{{.Port}} check{{end}} 

La palabra clave de range en este caso actúa como un iterador. Para los tres servicios "django", se generará el siguiente archivo de configuración:

 global debug defaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 frontend http_front bind *:5001 stats uri /haproxy?stats default_backend http_back backend http_back balance roundrobin server 228.195.86.224 127.0.0.1:21469 check server 228.195.86.224 127.0.0.1:25872 check server 228.195.86.224 127.0.0.1:25865 check 

La biblioteca https://github.com/hashicorp/consul-template se utiliza para iniciar el proceso de generación de acuerdo con la plantilla sobre la marcha. Desde el recurso del desarrollador, puede descargar el archivo ejecutable para todos los sistemas operativos comunes e iniciar el proceso en nombre de un usuario no autorizado con el comando:

 consul-template -template="haproxy/haproxy.cfg.tmpl:haproxy/haproxy.cfg:./haproxy/haproxy.reload.sh" 

El parámetro -template contiene parámetros separados por dos puntos 1) el nombre de la plantilla, 2) el nombre del archivo de configuración resultante 3) el comando que se ejecuta después de que se genera el archivo. El archivo se generará automáticamente si se cambian las variables incluidas en la plantilla (por ejemplo, se cambia la cantidad de réplicas del servicio django).

Después de iniciar el motor de plantillas que generará la primera configuración, puede ejecutar haproxy:

 haproxy -D -f haproxy/haproxy.cfg -p `pwd`/haproxy.pid 

Especificamos explícitamente el archivo pid para poder enviar una señal a la sobrecarga de haproxy "suave":

 haproxy -D -f ./haproxy/haproxy.cfg -p `pwd`/haproxy.pid -sf $(cat `pwd`/haproxy.pid) 

En este ejemplo, el servicio se publica en el puerto 5001. En el mismo puerto, puede ver las estadísticas de haproxy en la dirección /haproxy?stats .

ACTUALIZADO 02/24/2019 10:43 PM

Según el comentario de @ usego , se realizó un refinamiento adicional en la operación de haproxy en el contenedor acoplable, en particular de acuerdo con el fragmento de la documentación github.com/neo4j/docker-library-docs/tree/master/haproxy#reloading-config

Recargando config

Si usó un montaje de enlace para la configuración y ha editado su archivo haproxy.cfg, puede usar la función de recarga elegante de HAProxy enviando un SIGHUP al contenedor:

$ docker kill -s HUP my-running-haproxy

El script de punto de entrada en la imagen verifica la ejecución del comando haproxy y lo reemplaza con haproxy-systemd-wrapper de HAProxy upstream que se encarga del manejo de la señal para realizar la recarga elegante. Debajo del capó, esto usa la opción -sf de haproxy, por lo que "hay dos ventanas pequeñas de unos pocos milisegundos cada una donde es posible que se noten algunas fallas de conexión durante las cargas altas" (consulte Detener y reiniciar HAProxy).


Con este enfoque, la configuración se vuelve a cargar realmente, pero como resultado de la interrupción del proceso actual. Y esto significa que los servicios tendrán, aunque sean muy insignificantes, pero sin embargo un período de inaccesibilidad y algunos clientes pueden observar un mensaje de error. Pero a veces este no es el criterio principal de selección. Por lo tanto, daré además la configuración docker-compose.yml para iniciar haproxy en docker:

 version: '3' services: haproxy_lb: image: haproxy volumes: - ./haproxy:/usr/local/etc/haproxy network_mode: host 


El comando que sobrecargará la configuración de haproxy también cambiará:

 consul-template -template="haproxy/haproxy.cfg.tmpl:haproxy/haproxy.cfg:docker kill -s HUP $(docker-compose ps -q haproxy_lb)" 


Las ventajas de esta implementación incluyen la capacidad de trabajar sin instalar haproxy.

El código de muestra está disponible en el repositorio.

Enlaces utiles:

1.www.haproxy.com/blog/haproxy-and-consul-with-dns-for-service-discovery
2.m.mattmclaugh.com/traefik-and-consul-catalog-example-2c33fc1480c0
3.www.hashicorp.com/blog/load-balancing-strategies-for-consul

apapacy@gmail.com
24 de febrero de 2019

Source: https://habr.com/ru/post/441534/


All Articles