Balanceando carga de squid para squid
4 de Fevereiro de 2013, 0:00 - sem comentários aindaPrimeiro vou explicar o problema e motivação, assim partirei para prática demonstrando como resolvi a questão.
Motivação : Ambiente com 20.000 usuários necessitando de uma solução de proxy de acesso web centralizado.
Precisávamos de um ambiente “parrudo” o suficiente para suportar requisição de 20.000 usuários, sendo que esse ambiente deveria ser construído completamente com Software Livre. Challenge Accepted!
Sabíamos que apenas uma máquina não suportaria toda essa carga e tínhamos também que prover alta-disponibilidade, na modalidade ativo-ativo (pra ficar ainda mais emocionante).
Chegamos ao seguinte dilema, como balancearemos o tráfego? Uma vez que as soluções prontas são bem caras, comprar estava fora de cogitação. Mais desafio!
Primeiro pensamos em usar balanceamento via DNS, mas chegamos a conclusão que seria um problema, uma vez que o cache do cliente e aplicações poderia fazer um proxy ficar mais sobrecarregado do que o outro.
Dai veio a ideia, por que não usar o squid mesmo pra isso? O squid trabalha com esquema de comunicação entre proxies, usando o protocolo ICP (Internet Cache Protocol).O squid pode repassar a requisição http para que outro nó possa tratá-la e usando o parâmetro round-robin tudo fica bem mais legal e distribuído.
Depois de inúmeras pesquisas, muitos possíveis ambientes e retrabalho, chegamos a essa solução de arquitetura:
Na primeira camada, da esquerda pra direita, basicamente temos dois squid trabalhando como balanceadores da solução, eles recebem toda requisição e repassam a requisição para o que chamo aqui de proxies de acesso.
A segunda camada é responsável por fazer todo trabalho pesado do ambiente, uma vez que nessas máquinas rodam todas verificações de filtragem de conteúdo, antivírus, autenticação e afins.
Os balanceadores apenas são responsáveis por centralizar as requisições e repassar para camada posterior tratar. Isso parece fácil, porém deu um bocado de trabalho, pois não tinha documentação clara de como fazer isso, por conta disso escrevo esse artigo, afim de esclarecer alguns detalhes que tornarão a tarefa menos dolorosa.
Eu usei CentOS, por uma convenção não formal da empresa, mas acho que funcionará bem com qualquer distro. Vamos lá! Antes de tudo, instale um CentOS padrão, tune ele a seu gosto depois. Não trataremos disso aqui, muito menos do quesito hardening.
Eu usei a versão 3.1.10 do Squid, mas acho que pode ser usado qualquer versão, apenas mudando um parâmetro ou outro.
Antes de mais nada, vamos entender como funciona a hierarquização do Squid com o protoco ICP.
O Squid tem suporte a repasse de requisição para outros proxies que suportem o protocolo ICP*. Para essa configuração o squid tem um parâmetro chamado cache_peer, que, resumidamente, é responsável pela informação do proxy ao qual ele repassará a solicitação.
* Perceba que tenho noção do protocolo HTCP, mas não abordarei ele nesse artigo.
Vamos primeiro explicar como funciona configuração da primeira camada.
Balanceadores de carga
Os balanceadores de carga devem ter o seguinte conteúdo no squid:
cache_peer 10.2.3.21 parent 3128 3130 round-robin no-query name=squidpeer1 connect-timeout=5 connect-fail-limit=5
cache_peer 10.2.3.22 parent 3128 3130 round-robin no-query name=squidpeer2 connect-timeout=5 connect-fail-limit=5
cache_peer 10.2.3.23 parent 3128 3130 round-robin no-query name=squidpeer3 connect-timeout=5 connect-fail-limit=5
never_direct allow all
miss_access allow al
Segue a explicação detalhada:
cache_peer 10.2.3.21 parent 3128 3130 round-robin no-query name=squidpeer1 connect-timeout=5 connect-fail-limit=5
cache_peer <ip> <grau> <porta squid destino> <porta icp destino> <opções>
Perceba que basta informar o ip do proxy de destino, qual o grau de ligação entre deles, que nesse caso é parent, pois com o grau parente ele funcionará, resumidamente, em apenas uma via, ou seja, o filho sempre perguntará a seu pai, mas nunca o contrário, que para o balanceador de carga é a configuração perfeita.
As opções usadas tem são
round-robin
Essa opção tem o objetivo de enviar uma solicitação para cada nó, assim balanceando a carga de forma igualitária. Essa opção é indispensável para essa solução.
no-query
Essa opção é usada para evitar que o “filho” envie solicitações ICP para o servidor destino, pois não há necessidade de troca de cache ou verificar conteúdo, uma vez que entre os servidores da próxima camada existe uma configuração de troca de objetos do cache.
never_direct allow all
miss_access allow all
As opções acima afirmam que esse squid não deverá buscar nenhum dado na internet e sim utilizar seus servidores, configurados como parent, para essa tarefa.
Proxies de acesso
Esses servidores são responsáveis por receber requisições dos balanceadores de carga e retornar com o objeto solicitado, seja solicitando na internet ou no cache próprio ou de outros membros dessa camada, pois os ativos desse grupo são configurados para consultar se o objeto solicitado existe em seu próprio cache ou em algum outro servidor dessa camada, tudo via comunicação ICP, trocam informações afim de se manterem cientes de quais dados existem em cada cache. Assim evitando uso desnecessário da internet.
Segue abaixo a configuração necessária.
cache_peer 10.199.254.5 sibling 3128 3130 proxy-only
cache_peer 10.199.254.4 sibling 3128 3130 proxy-onlycache_peer_access 10.199.254.5 allow all
cache_peer_access 10.199.254.4 allow allacl balanceador src 10.2.3.19
http_access allow balanceadorfollow_x_forwarded_for allow all
Veja que aqui usamos um outro grau de hierarquia de cache, sibling é usado quando se deseja trocar cache de forma horizontal. Nesse caso são três proxies, configurados para trocar informações entre eles.
A opção nova do cache_peer, proxy-only , serve para que o objeto obtido de um outro membro do cache, não seja armazenado em outro. Assim evitamos dados duplicados, o que pode onerar o espaço disponível. Uma vez que nossa rede é Gigabit, velocidade de comunicação entre eles não é problema.
A opção cache_peer_access permite que um outro servidor proxy faça solicitações ICP para esse host. É possível especificar o que ele pode acessar, mas não é nosso caso.
O bloco abaixo, é responsável por permitir que os balanceadores façam requisições http para esse host:
acl balanceador src 10.2.3.19
http_access allow balanceador
Após configurarmos nosso ambiente, percebemos um problema. O fato de termos um ativo intermediário, fazia com quem as requisições para a segunda camada tivessem como ip de cliente o ip do balanceador, ao invés do cliente real, que solicita para o balanceador ao invés de diretamente a segunda camada.
Que foi resolvido com essa configuração:
follow_x_forwarded_for allow all
Esse parâmetro permite que seja usado o ip do cliente final, ao invés dos intermediários para tudo que tange o squid e os produtos que estejam ligados ao squid, tal como squidguard.
Após essa configuração especial, executamos os serviços e pronto.
Claro que faltam as outras configurações comuns do squid, mas não é o objetivo desse documento.
Eu já escrevi um post sobre tunning do Squid, talvez esteja um pouco velho, mas acredito que ainda sirva pra algo.
Fontes :
http://www.squid-cache.org/Doc/config/cache_peer
http://www.squid-cache.org/Doc/config/follow_x_forwarded_for