HAProxy: Configurando Balanceamento de Carga Inteligente com ACLs

O HAProxy, operando na camada de aplicação (camada 7), oferece recursos avançados de balanceamento de carga através de suas regras de Access Control List (ACL). Essas regras permitem a criação de sistemas de balanceamento de carga dinâmicos e inteligentes.

As ACLs no HAProxy servem a dois propósitos principais:

  • Validação de Requisições: Verificar se uma requisição do cliente atende aos critérios definidos. Requisições que não cumprem as regras são imediatamente descartadas.
  • Direcionamento Inteligente: Encaminhar requisições que satisfazem as regras ACL para servidores backend específicos, implementando assim o balanceamento de carga baseado em critérios definidos.

As regras ACL são comumente configuradas na seção frontend do HAProxy.

A sintaxe básica para definir uma ACL é:

acl nome_da_acl metodo [-i] [critério_de_correspondência]
  • acl: Palavra-chave que inicia a definição de uma regra ACL, seguida por um nome customizado para a regra.
  • metodo: Define o tipo de verificação a ser realizada. O HAProxy oferece diversos métodos, incluindo:
    • hdr_reg(host): Correspondência de domínio/hostname usando expressões regulares.
    • hdr_dom(host): Correspondência exata de domínio/hostname (sem regex).
    • hdr_beg(host): Correspondência de domínio/hostname que começa com um prefixo específico.
    • url_sub: Busca por uma substring dentro da URL da requisição.
    • url_dir: Verifica se a URL contém uma string específica como parte do caminho.
    • path_beg: Verifica se o caminho da URL começa com uma string específica.
    • path_end: Verifica se o caminho da URL termina com uma string específica.
    • E muitos outros.
  • -i: Indica que a correspondência deve ser insensível a maiúsculas e minúsculas.
  • critério_de_correspondência: O valor a ser comparado com a requisição (por exemplo, um nome de domínio, uma string na URL ou uma expressão regular).

Juntamente com as ACLs, o parâmetro use_backend é fundamental. Ele especifica qual cluster de servidores backend (backend) deve receber a requisição caso uma ACL seja satisfeita. O parâmetro default_backend define o destino padrão quando nenhuma ACL é acionada.

Exemplos de Regras ACL

A seguir, alguns exemplos práticos:

# Regra: www_policy. Corresponde a domínios que começam com 'www.z.cn' ou 'z.cn'.
   acl www_policy      hdr_reg(host)   -i      ^(www.z.cn|z.cn)
   # Regra: bbs_policy. Corresponde a domínios que terminam com 'bbs.z.cn'.
   acl bbs_policy      hdr_dom(host)   -i      bbs.z.cn
   # Regra: url_policy. Corresponde a requisições onde a URL contém 'buy_sid='.
   acl url_policy      url_sub         -i      buy_sid=

   # Direciona para o backend 'server_www' se 'www_policy' for satisfeita.
   use_backend server_www    if www_policy
   # Direciona para o backend 'server_app' se 'url_policy' for satisfeita.
   use_backend server_app    if url_policy
   # Direciona para o backend 'server_bbs' se 'bbs_policy' for satisfeita.
   use_backend server_bbs    if bbs_policy

   # Se nenhuma das regras acima for satisfeita, o tráfego vai para 'server_cache'.
   default_backend server_cache
   

Outro exemplo, demonstrando a combinação de regras:

# Regra: url_static. Corresponde a caminhos de URL que terminam com extensões de arquivos estáticos comuns.
   acl url_static      path_end        -i      .gif .png .jpg .css .js
   # Regra: host_www. Corresponde a domínios que começam com 'www'.
   acl host_www        hdr_beg(host)   -i      www
   # Regra: host_static. Corresponde a domínios que começam com 'img.', 'video.', 'download.', 'ftp.'.
   acl host_static     hdr_beg(host)   -i      img. video. download. ftp.

   # Direciona para o backend 'static' se ambas as regras 'host_static' e 'url_static' forem verdadeiras,
   # OU se ambas as regras 'host_www' e 'url_static' forem verdadeiras.
   use_backend static      if host_static || host_www url_static
   # Se 'host_www' for satisfeita (e a regra anterior não), direciona para o backend 'www'.
   use_backend www         if host_www
   # Caso contrário, o tráfego vai para o backend 'server_cache'.
   default_backend server_cache
   

A lógica if A || B C é interpretada como if (A and C) or (B and C).

Configuração de Exemplo

Este exemplo detalha a configuração de um HAProxy para gerenciar três hosts virtuais distintos, distribuindo o tráfego com base no nome do host.

Configuração do HAProxy


$ cat conf/haproxy.cfg
global
	maxconn		20000
	log			127.0.0.1 local0 info
	user		nobody
	group		nobody
	chroot		/usr/local/haproxy
	daemon
	pidfile		/usr/local/haproxy/logs/haproxy.pid
defaults
	mode			http
	retries			3
	timeout	connect	10s
	timeout	client	20s
	timeout	server	30s
	timeout	check	5s
frontend www
	bind			*:80
	mode			http
	log				global
	option			httplog
	option			forwardfor
	option			httpclose
	option			dontlognull
	# Regras para direcionar tráfego com base no host
	acl	acl_www		hdr_beg(host)	www.zb.com
	acl	acl_static	hdr_beg(host)	static.zb.com
	acl	acl_video	hdr_beg(host)	video.zb.com
	use_backend	backend_a	if	acl_www
	use_backend	backend_b	if	acl_static
	use_backend	backend_c	if	acl_video
	default_backend	backend_default

backend backend_default
	mode            http
	option		redispatch
	option		abortonclose
	balance		roundrobin
	cookie		SERVERID preserve
	option	httpchk	HEAD	/index.html
	server	web1	10.0.0.6:80	cookie	server1	weight	4	check	inter	2000	rise	2	fall	3
	server	web2	10.0.0.7:8000	cookie	server2	weight	6	check	inter	2000	rise	2	fall	3
	timeout connect 5s
	timeout server  5s
	retries         2

# Backends para diferentes tipos de conteúdo
backend backend_a
	mode            http
	option		redispatch
	option		abortonclose
	balance		roundrobin
	cookie		SERVERID preserve
	option	httpchk	HEAD	/index.html
	server	a1	10.0.0.6:81	cookie	server1	weight	6	check	inter	2000	rise	2	fall	3
	server	a2	10.0.0.7:81	cookie	server2	weight	6	check	inter	2000	rise	2	fall	3
backend backend_b
	mode            http
	option		redispatch
	option		abortonclose
	balance		roundrobin
	cookie		SERVERID preserve
	option	httpchk	HEAD	/index.html
	server	b1	10.0.0.6:82	cookie	server1	weight	6	check	inter	2000	rise	2	fall	3
	server	b2	10.0.0.7:82	cookie	server2	weight	6	check	inter	2000	rise	2	fall	3
backend backend_c
	mode            http
	option		redispatch
	option		abortonclose
	balance		roundrobin
	cookie		SERVERID preserve
	option	httpchk	HEAD	/index.html
	server	c1	10.0.0.6:83	cookie	server1	weight	6	check	inter	2000	rise	2	fall	3
	server	c2	10.0.0.7:83	cookie	server2	weight	6	check	inter	2000	rise	2	fall	3

# Interface de monitoramento
listen stats
	bind	0.0.0.0:9188
	mode	http
	log	127.0.0.1	local0	err
	stats	refresh	30s
	stats	uri	/status
	stats	realm	Admin Area
	stats	auth	admin:admin
	stats	hide-version
	stats	admin	if	TRUE
   

Configuração dos Servidores Nginx de Backend

Configuração de hosts virtuais em cada servidor Nginx para escutar em portas diferentes.


# Arquivo: /etc/nginx/nginx.conf (simplificado para o contexto)

# ... (configurações globais e de eventos) ...

http {
   # ... (configurações http) ...

   server {
       listen       80;
       server_name  _;
       root         /usr/share/nginx/html;
       # ... (configurações padrão) ...
   }

   # Hosts virtuais para os backends do HAProxy
   server {
       listen       81;
       server_name  _;
       charset utf-8;
       location / {
           index index.html index.htm;
           root /data/a;
       }
   }
   server {
       listen       82;
       server_name  _;
       charset utf-8;
       location / {
           index index.html index.htm;
           root /data/b;
       }
   }
   server {
       listen       83;
       server_name  _;
       charset utf-8;
       location / {
           index index.html index.htm;
           root /data/c;
       }
   }
}
   

Criação de Páginas de Teste

Criação de arquivos index.html distintos para cada diretório em ambos os servidores backend.

Servidor 10.0.0.6:


$ mkdir -p /data/{a,b,c}
$ echo "Conteúdo do Servidor 10.0.0.6 - Backend A" > /data/a/index.html
$ echo "Conteúdo do Servidor 10.0.0.6 - Backend B" > /data/b/index.html
$ echo "Conteúdo do Servidor 10.0.0.6 - Backend C" > /data/c/index.html

# Testar e reiniciar Nginx
$ nginx -t
$ systemctl restart nginx.service
   

Servidor 10.0.0.7:


$ mkdir -p /data/{a,b,c}
$ echo "Conteúdo do Servidor 10.0.0.7 - Backend A" > /data/a/index.html
$ echo "Conteúdo do Servidor 10.0.0.7 - Backend B" > /data/b/index.html
$ echo "Conteúdo do Servidor 10.0.0.7 - Backend C" > /data/c/index.html

# Testar e reiniciar Nginx
$ nginx -t
$ systemctl restart nginx.service
   

Acessando os Serviços

Para testar a configuração, utilize a interface de status do HAProxy:

http://10.0.0.5:9188/status

Configuração de DNS Local (Opcional)

Adicione as seguintes entradas ao arquivo hosts do seu cliente para facilitar o acesso via nomes de domínio:


10.0.0.5	www.zb.com
10.0.0.5	static.zb.com
10.0.0.5	video.zb.com
   

Agora, você pode acessar os serviços usando os nomes de domínio configurados.

Tags: haproxy ACL Balanceamento de Carga nginx backend

Publicado em 7-6 19:51