Balanceadores de carga para sistemas de orquestração

Os balanceadores de carga em sistemas de orquestração (Kubernetes, Nomad e outros) têm mais requisitos do que apenas balanceamento de carga. Primeiro, o Load Balancer deve poder ler um diretório com uma lista de serviços para os quais o tráfego deve ser redirecionado (ou, como opção, permitir que os serviços se registrem para incluí-los no tráfego). Em segundo lugar, faça-o dinamicamente, porque Os sistemas de orquestração podem a qualquer momento aumentar ou diminuir o número de réplicas de serviço ou movê-las para outros endereços na rede. E terceiro, faça isso sem parar o tráfego.

No post de hoje, descreverei o trabalho com dois balanceadores de carga - Traefik e HAProxy. Esses balanceadores de carga têm a capacidade de trabalhar com uma lista impressionante de ferramentas de orquestração. Os exemplos descreverão como trabalhar com o sistema de orquestração Nomad.

No último post eu já dei um exemplo de Load Balancers - Fabio. Suas limitações: funciona apenas com protocolos http / https e funciona apenas com o Consul. Ao contrário do Fabio, o Load Balancers Traefik trabalha com um número impressionante de sistemas diferentes. Aqui está uma lista parcial do site do desenvolvedor: Docker, Swarm mode, Kubernetes, Marathon, Consul, Etcd, Rancher, Amazon ECS, ...

Vou continuar o exemplo da postagem anterior , na qual várias réplicas do serviço django foram criadas.

O Traefik pode ser baixado do site do desenvolvedor como um arquivo executável para os sistemas operacionais mais comuns. Para se integrar ao Nomad (na verdade, ao Consul), você precisa criar um arquivo de configuração:

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

E, em seguida, execute o comando com o arquivo de configuração fornecido:

 traefik -c nomad/traefik.toml 

Depois disso, o UI Traefik estará disponível na porta 8080, que ainda não publicou nenhum serviço. Existem várias maneiras de publicar serviços, que acabam fazendo a mesma coisa - eles carregam dados de chave / valor no sistema Traefik. Aproveitaremos a oportunidade para definir pares de chave / valor por meio de etiquetas de serviço. Vamos expandir o arquivo de configuração do serviço django com o 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" } } } } } 

Neste exemplo, o serviço será publicado no host localhost e montado na rota / test. A Traefik desenvolveu um sistema flexível e completo de regras para configurar rotas, incluindo o trabalho com expressões regulares. A lista de parâmetros para as regras na documentação do desenvolvedor.

Depois de executar o nomad job run nomad/django.conf regras são aplicadas e o tráfego do Load Balancer será direcionado para o serviço. Assim, você pode alterar esses parâmetros, implantar uma nova opção de serviço com o nomad job run nomad/django.conf e todas as alterações serão aplicadas sem interromper o tráfego de forma irritante.

A desvantagem do Traefik é que ele trabalha com os protocolos da família http / https (apenas no caso, note que essa família também inclui soquetes da web). Mas ainda existe a possibilidade de que seja necessário trabalhar com outros protocolos. Então, vamos para a próxima solução mais ampla, baseada no HAProxy. Há algum tempo, o HAProxy apresentava problemas com o carregamento suave, o que dificultava o uso com sistemas de orquestração (durante a reinicialização, era necessário interromper o movimento de pacotes no nível da rede). Agora isso não é mais um problema.

Primeiro você precisa instalar o haproxy no seu computador. Aqui, a opção de instalar dentro do contêiner não funcionará. No haproxy, apenas recentemente tornou-se possível reiniciar o processo no modo "soft", mas o contêiner do docker ainda para, já que o segundo processo realmente começa com o haproxy, apenas muda no modo de espera - o que não funciona com o docker e seu princípio "one" -container é um processo ".

Para que o haproxy funcione, você deve ter um arquivo de configuração que contenha as regras necessárias. O Nomad (atualmente no Consul) usa um sistema de modelos que pode gerar configurações:

 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}} 

A palavra-chave range nesse caso atua como um iterador. Para os três serviços “django”, o seguinte arquivo de configuração será gerado:

 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 

A biblioteca https://github.com/hashicorp/consul-template é usada para iniciar o processo de geração de acordo com o modelo em tempo real. No recurso do desenvolvedor, você pode baixar o arquivo executável para todos os sistemas operacionais comuns e iniciar o processo em nome de um usuário não autorizado com o comando:

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

O parâmetro -template contém parâmetros separados por dois pontos 1) o nome do modelo, 2) o nome do arquivo de configuração resultante 3) o comando que é executado após a geração do arquivo. O arquivo será gerado automaticamente se as variáveis ​​incluídas no modelo forem alteradas (por exemplo, o número de réplicas do serviço django é alterado).

Após iniciar o mecanismo de modelo que irá gerar a primeira configuração, você pode executar o haproxy:

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

Especificamos explicitamente o arquivo pid para poder enviar um sinal para a sobrecarga haproxy "soft":

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

Neste exemplo, o serviço é publicado na porta 5001. Na mesma porta, você pode visualizar as estatísticas do próprio haproxy no endereço /haproxy?stats .

ATUALIZADO 24/02/2019 10:43

De acordo com o comentário de @ usego , um refinamento adicional foi feito para a operação do haproxy no contêiner do docker, em particular de acordo com o fragmento da documentação github.com/neo4j/docker-library-docs/tree/master/haproxy#reloading-config

Recarregando a configuração

Se você usou uma montagem de ligação para a configuração e editou o arquivo haproxy.cfg, pode usar o recurso de recarga normal do HAProxy enviando um SIGHUP para o contêiner:

$ docker kill -s HUP my-running-haproxy

O script do ponto de entrada na imagem verifica a execução do comando haproxy e o substitui pelo haproxy-systemd-wrapper do HAProxy upstream, que cuida da manipulação do sinal para fazer a recarga normal. Sob o capô, isso usa a opção -sf de haproxy, de modo que "existem duas pequenas janelas de alguns milissegundos cada uma nas quais é possível que algumas falhas de conexão sejam notadas durante altas cargas" (consulte Parando e reiniciando o HAProxy).


Com essa abordagem, a configuração é realmente recarregada, mas como resultado da interrupção do processo atual. E isso significa que os serviços terão, embora muito insignificantes, mas, no entanto, um período de inacessibilidade e alguns clientes poderão observar uma mensagem de erro. Mas, às vezes, esse não é o principal critério de seleção. Portanto, darei, além disso, a configuração do docker-compose.yml para iniciar o haproxy no docker:

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


O comando que sobrecarregará a configuração haproxy também será alterado:

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


As vantagens desta implementação incluem a capacidade de trabalhar sem instalar o haproxy.

O código de amostra está disponível no repositório.

Links úteis:

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 fevereiro de 2019

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


All Articles