Como usar o DNS para descoberta de serviços com NGINX e NGINX Plus

NGINX | 27 de abril de 2016

[Editor – Esta publicação foi atualizada para fazer referência à API do NGINX Plus, que substitui e torna obsoleto o módulo separado de configuração dinâmica mencionado na versão original da publicação.]

Uma das grandes vantagens de uma arquitetura de microsserviços é a rapidez e a facilidade com que você pode escalar instâncias de serviço. Com várias instâncias de serviço, você precisa de um balanceador de carga e de uma forma de informá-lo rapidamente sobre alterações no conjunto de instâncias de serviço disponíveis. Isso é conhecido como descoberta de serviços. NGINX Plus oferece duas opções de integração com sistemas de descoberta de serviços: a API do NGINX Plus e a nova resolução do Sistema de Nomes de Domínio (DNS). Esta publicação do blog se concentra na segunda opção.

Ao escalar instâncias de serviço (que chamaremos de backends neste post) adicionando ou removendo máquinas virtuais (VMs) ou contêineres, a configuração do balanceador de carga deve ser alterada para refletir cada mudança no conjunto de backends. O escalonamento pode ocorrer várias vezes por dia, por hora ou até mesmo por minuto, dependendo da aplicação. Devido à alta frequência das alterações de configuração, elas precisam ser automatizadas, e uma das maneiras de fazer isso é por meio da descoberta de serviços via DNS.

Muitas plataformas nas quais você executa suas aplicações atualmente, como o Kubernetes, oferecem suporte à descoberta de serviços por meio de DNS. Ao final desta publicação, disponibilizamos links para artigos que explicam como integrar o NGINX Plus a plataformas populares e ferramentas de descoberta de serviços que usam DNS.

Uma breve revisão dos principais recursos de DNS

Antes de explicarmos como configurar a descoberta de serviços via DNS, vamos dar uma rápida olhada em alguns recursos do protocolo DNS que são particularmente relevantes ou úteis.

Tempo de vida

Para evitar que os clientes DNS usem informações desatualizadas, os registros DNS incluem o campo de tempo de vida (TTL) para definir por quanto tempo os clientes podem considerar o registro válido. Para estar em conformidade com os padrões DNS, os clientes devem consultar o servidor DNS para obter uma atualização quando o TTL de um registro expirar. Por padrão, o NGINX Plus respeita o TTL, mas também oferece um controle mais granular sobre o “tempo de vida” de um registro – você pode configurar o NGINX Plus para ignorar os TTLs e atualizar os registros em uma frequência especificada. (Abordaremos mais adiante neste post como o NGINX Open Source lida com o TTL.)

DNS sobre TCP

Por padrão, clientes e servidores DNS se comunicam por UDP, mas, se um nome de domínio for resolvido para um grande número de endereços IP de backend, talvez a resposta completa não caiba em um único datagrama UDP, cujo limite é de 512 bytes. O uso de TCP em vez de UDP resolve esse problema: quando o conjunto completo de registros não cabe em um datagrama, o servidor define um sinalizador de truncamento na resposta, indicando ao cliente que ele deve mudar para TCP para obter todos os registros. O DNS sobre TCP é compatível com o NGINX versão 1.9.11 e posteriores e com o NGINX Plus R9 e posteriores. Para obter mais detalhes, consulte Balanceamento de carga do tráfego DNS com o NGINX e o NGINX Plus em nosso blog.

SRV Registros

O DNS resolve nomes de host em endereços IP, mas e quanto aos números de porta? Há alguns casos – por exemplo, ao fazer o balanceamento de carga de contêineres Docker – em que não é possível usar números de porta conhecidos, pois eles são atribuídos dinamicamente. O DNS tem um tipo especial de registro – o registro de serviço (SRV) – que inclui números de porta e alguns outros parâmetros. A partir da versão R9, o NGINX Plus oferece suporte a registros SRV (e, portanto, pode extrair deles as informações de porta).

Editor – Para ter uma visão geral de todos os novos recursos do NGINX Plus R9, consulte Announcing NGINX Plus R9 em nosso blog.

Métodos de descoberta de serviços com DNS para NGINX e NGINX Plus

Agora, mostraremos cinco maneiras de usar o DNS para descoberta de serviços no NGINX e no NGINX Plus, em ordem crescente de sofisticação. As três primeiras estão disponíveis tanto no NGINX quanto no NGINX Plus, e as duas últimas, apenas no NGINX Plus.

Nesta análise dos métodos de descoberta de serviços, vamos supor que temos um servidor de nomes autoritativo para a zona example.com, com o endereço IP 10.0.0.2. Há três servidores de backend que correspondem ao nome de domínio backends.example.com, conforme mostrado na saída a seguir do utilitário nslookup. Nos quatro primeiros métodos que abordaremos, o NGINX e o NGINX Plus solicitam registros A padrão ao DNS; no último método, o NGINX Plus solicita registros SRV.

$ nslookup backends.example.com 10.0.0.2Server:		10.0.0.2
Address:	10.0.0.2#53

Name:	backends.example.com
Address: 10.0.0.11
Name:	backends.example.com
Address: 10.0.0.10
Name:	backends.example.com
Address: 10.0.0.12

Como usar o DNS para descoberta de serviços com o NGINX

Começaremos mostrando as três maneiras de usar o DNS com o NGINX Open Source (como mencionamos acima, você também pode usá-las com o NGINX Plus).

Usando o nome de domínio na diretiva proxy_pass Directive

A maneira mais simples de definir o grupo de servidores upstream (backends) é especificar um nome de domínio como parâmetro da diretiva proxy_pass:

server {    location / {
        proxy_pass http://backends.example.com:8080;
    }
}

Quando o NGINX é iniciado ou recarrega sua configuração, ele consulta um servidor DNS para resolver backends.example.com. O servidor DNS retorna a lista dos três backends mencionados acima, e o NGINX usa o algoritmo Round Robin padrão para balancear as solicitações entre eles. O NGINX seleciona o servidor DNS no arquivo de configuração do sistema operacional /etc/resolv.conf.

Este método é a maneira menos flexível de realizar a descoberta de serviços e apresenta as seguintes desvantagens adicionais:

  • Se não for possível resolver o nome de domínio, o NGINX não conseguirá iniciar nem recarregar sua configuração.
  • O NGINX armazena os registros DNS em cache até a próxima reinicialização ou recarga da configuração, ignorando os valores de TTL dos registros.
  • Não podemos especificar outro algoritmo de balanceamento de carga, nem configurar verificações passivas de integridade ou outros recursos definidos por parâmetros da diretiva server, que descreveremos na próxima seção.

Como usar um nome de domínio em um grupo de servidores upstream

Para aproveitar as opções de balanceamento de carga oferecidas pelo NGINX, você pode definir o grupo de servidores upstream no bloco de configuração upstream. Porém, em vez de identificar servidores individuais pelo endereço IP, use o nome de domínio como parâmetro da diretiva server.

Assim como no primeiro método, backends.example.com é resolvido em três servidores de backend quando o NGINX é iniciado ou recarrega sua configuração. Mas agora podemos definir um algoritmo de balanceamento de carga mais sofisticado, o de Menor número de conexões, e usar o parâmetro max_fails para habilitar verificações passivas de integridade, especificando que o NGINX marque um servidor como indisponível quando três solicitações consecutivas falharem.

upstream backends {    least_conn;

    server backends.example.com:8080 max_fails=3;
}

server {
    location / {
        proxy_pass http://backends;
    }
}

Embora esse método nos permita escolher o algoritmo de balanceamento de carga e configurar verificações de integridade, ele ainda apresenta as mesmas desvantagens do método anterior em relação à inicialização, ao recarregamento e ao TTL.

Definindo o nome de domínio em uma variável

Este método é uma variação do primeiro, mas nos permite controlar a frequência com que o NGINX resolve novamente o nome de domínio:

resolver 10.0.0.2 valid=10s;
server {
    location / {
        set $backend_servers backends.example.com;
        proxy_pass http://$backend_servers:8080;
    }
}

Ao usar uma variável para especificar o nome de domínio na diretiva proxy_pass, o NGINX resolve novamente o nome de domínio quando o TTL expira. É necessário incluir a diretiva resolver para especificar explicitamente o servidor de nomes (o NGINX não consulta o arquivo /etc/resolv.conf, como nos dois primeiros métodos). Ao incluir o parâmetro valid na diretiva resolver, você pode instruir o NGINX a ignorar o TTL e, em vez disso, resolver novamente os nomes em uma frequência especificada. Neste exemplo, instruímos o NGINX a resolver novamente os nomes a cada 10 segundos.

Observação: Para o balanceamento de carga TCP/UDP, este método de usar uma variável na diretiva proxy_pass é compatível com o NGINX 1.11.3 e versões posteriores e com o NGINX Plus R10 e versões posteriores.

Esse método elimina duas desvantagens do primeiro método: a operação de inicialização ou recarga do NGINX não falha quando o nome de domínio não pode ser resolvido, e podemos controlar a frequência com que o NGINX resolve o nome novamente. No entanto, como ele não usa um grupo upstream, não é possível especificar o algoritmo de balanceamento de carga nem outros parâmetros para a diretiva server (como fizemos no segundo método).

Como usar o DNS para descoberta de serviços com o NGINX Plus

Agora, veremos os dois métodos de descoberta de serviços com DNS que são exclusivos do NGINX Plus.

Como usar registros A com o NGINX Plus

Com o NGINX Plus, podemos resolver novamente os nomes DNS com a frequência que quisermos e sem as desvantagens mencionadas acima para os três primeiros métodos. Para usar esse recurso, precisamos:

  • Inclua a diretiva resolver para especificar o servidor de nomes, como no método anterior.
  • Inclua a diretiva zone no bloco de configuração upstream para alocar uma zona de memória compartilhada.
  • Adicione o parâmetro resolve à diretiva server em que usamos o nome de domínio.

Considere o seguinte exemplo:

resolver 10.0.0.2 valid=10s;
upstream backends {
    zone backends 64k;
    server backends.example.com:8080 resolve;
}

server {
    location / {
        proxy_pass http://backends;
    }
}

Por padrão, o NGINX Plus respeita o TTL e resolve novamente os nomes quando os registros expiram. Para que o NGINX Plus resolva novamente os nomes em uma frequência especificada, inclua o parâmetro valid na diretiva resolver.

No trecho, a cada 10 segundos, o NGINX Plus consulta o servidor de nomes em 10.0.0.2 para resolver backends.example.com. Se o nome não puder ser resolvido, o NGINX Plus não falhará, seja na inicialização, ao recarregar a configuração ou durante a execução. Em vez disso, o cliente verá a página de erro padrão 502.

Como usar registros SRV com o NGINX Plus

O NGINX Plus R9 e versões posteriores são compatíveis com registros DNS SRV. Isso permite que o NGINX Plus obtenha de um servidor de nomes não apenas endereços IP, mas também números de porta, pesos e prioridades. Isso é essencial em ambientes de microsserviços, nos quais os números de porta dos serviços costumam ser atribuídos dinamicamente.

Editor – Para ter uma visão geral de todos os novos recursos do NGINX Plus R9, consulte Announcing NGINX Plus R9 em nosso blog.

SRV são definidos por uma tripla composta pelo nome do serviço, pelo protocolo de comunicação com o serviço e pelo nome de domínio. Ao consultar o servidor de nomes, precisamos fornecer os três. Nosso servidor de nomes 10.0.0.2 tem três registros SRV com a tripla formada pelo nome do serviço http, pelo protocolo tcp e pelo nome de domínio backends.example.com, conforme mostrado nesta saída do utilitário nslookup:

$ nslookup -query=SRV _http._tcp.backends.example.com 10.0.0.2Server:		10.0.0.2
Address:	10.0.0.2#53

_http._tcp.backends.example.com	service = 0 2 8090 backend-0.example.com.
_http._tcp.backends.example.com	service = 0 1 8091 backend-1.example.com.
_http._tcp.backends.example.com	service = 10 1 8092 backend-2.example.com.

Quando consultamos o nome do host em cada registro SRV, obtemos seu endereço IP:

$ nslookup backend-0.example.com 10.0.0.2...
Name:	backend-0.example.com
Address: 10.0.0.10

$ nslookup backend-1.example.com 10.0.0.2
...
Name:	backend-1.example.com
Address: 10.0.0.11

$ nslookup backend-2.example.com 10.0.0.2
...
Name:	backend-2.example.com
Address: 10.0.0.12

Vamos analisar mais detalhadamente as informações do primeiro registro SRV retornado pelo primeiro comando nslookup:

_http._tcp.backends.example.com	service = 0 2 8090 backend-0.example.com.
  • _http._tcp. – O nome e o protocolo do registro SRV. Especificaremos isso como o valor do parâmetro service da diretiva server no arquivo de configuração do NGINX Plus (veja abaixo).
  • 0 – A prioridade. Quanto menor o valor, maior a prioridade. O NGINX Plus define os servidores com a prioridade mais alta como servidores primários e os demais como servidores de backup. Este registro tem o menor valor (a prioridade mais alta) entre todos os registros, portanto, o NGINX Plus define o backend correspondente como um servidor primário.
  • 2 – O peso. O NGINX Plus define o peso do backend com esse valor ao adicioná-lo ao grupo upstream (equivalente ao parâmetro weight da diretiva server).
  • 8090 – O número da porta. O NGINX Plus define a porta do backend com esse valor ao adicionar o backend ao grupo upstream.
  • backend‑0.example.com – O nome do host do servidor de backend. O NGINX Plus resolve esse nome e adiciona o backend correspondente ao grupo de upstreams. Se o nome for resolvido para vários registros, o NGINX Plus adicionará vários servidores.

Agora, vamos ver como configurar o NGINX Plus para usar registros SRV. Veja um exemplo de arquivo de configuração:

resolver 10.0.0.2 valid=10s;

upstream backends {
    zone backends 64k;
    server backends.example.com service=_http._tcp resolve;
}

server {
    location / {
        proxy_pass http://backends;
    }
}

Usando o parâmetro service da diretiva server, especificamos o nome e o protocolo dos registros SRV que desejamos resolver. No nosso caso, eles são _http e _tcp, respectivamente. Exceto pelo parâmetro service e pelo fato de não especificarmos uma porta, a configuração é igual à do exemplo da seção anterior.

Com base nos valores retornados pelo primeiro comando nslookup desta seção, o NGINX Plus é configurado com três servidores de backend:

  • 10.0.0.10 – Servidor primário com porta 8090 e peso 2.
  • 10.0.0.11 – Servidor primário com a porta 8091 e peso 1.
  • 10.0.0.12 – Servidor de backup com porta 8092 e peso 1.

Se configurarmos o monitoramento de atividades em tempo real no NGINX Plus, poderemos visualizar esses back-ends no painel integrado:

O painel de monitoramento de atividades em tempo real, que mostra como o NGINX Plus distribui as solicitações de acordo com os pesos atribuídos aos servidores upstream em seus registros DNS SRV, pode ser usado para monitorar o NGINX em uma arquitetura de microsserviços com o NGINX como balanceador de carga

Observe como as solicitações são distribuídas de acordo com os pesos especificados. O servidor 10.0.0.11:8091 (com peso 1) recebe um terço das solicitações, enquanto o servidor 10.0.0.10:8090 (com peso 2) recebe dois terços. Como servidor de backup, o servidor 10.0.0.12:8092 não recebe nenhuma solicitação, a menos que os outros dois servidores estejam indisponíveis.

Ressalvas

Ao usar o DNS para descoberta de serviços com o NGINX Plus, há alguns aspectos que devem ser considerados:

  • O servidor DNS precisa ter alta disponibilidade ou contar com um servidor de backup. Se o servidor DNS ficar indisponível, o NGINX Plus deixará de receber atualizações. Ele manterá os backends existentes na configuração (a menos que você o reinicie ou recarregue a configuração), ignorando os valores de TTL dos registros correspondentes.
  • Você pode especificar vários servidores de nomes com a diretiva resolver, para que, se um deles estiver indisponível, o NGINX Plus tente os demais.
  • Conforme mencionado na introdução, uma alternativa ao DNS para descoberta de serviços com o NGINX Plus é a NGINX Plus API, que permite fazer solicitações HTTP simples para adicionar ou remover servidores de um grupo upstream.

Exemplos

Se quiser conferir exemplos completos, consulte estas publicações do blog sobre a integração do NGINX e do NGINX Plus com plataformas de descoberta de serviços que usam DNS:

Atualizaremos esta lista à medida que publicarmos mais conteúdo sobre novas opções de integração no futuro.

Conclusão

A descoberta de serviços via DNS, totalmente disponível no NGINX Plus, oferece uma maneira simples de atualizar a configuração do balanceador de carga em um ambiente de microsserviços. O suporte a registros SRV na versão 9 e posteriores torna o NGINX Plus ainda mais poderoso, pois permite que ele obtenha não apenas os endereços IP, mas também os números das portas dos backends.

Pronto para experimentar a descoberta de serviços com DNS para o NGINX Plus, além de seus outros recursos avançados? Comece sua avaliação gratuita de 30 dias hoje mesmo ou entre em contato conosco para conversar sobre seus casos de uso.


Compartilhar

Publicações relacionadas no blog

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade
NGINX | 10/10/2024

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade

Descubra como o F5 NGINX One aprimora o gerenciamento e a observabilidade de ambientes híbridos e multicloud ao oferecer um console web centralizado baseado em SaaS, com insights em tempo real, conformidade automatizada e gerenciamento simplificado de configurações.

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa
NGINX | 17/06/2024

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa

Descubra como transformar uma definição de esquema OpenAPI em uma configuração NGINX totalmente funcional, operando como um API Gateway com a segurança de um Web Application Firewall e um Portal do Desenvolvedor, usando uma abordagem declarativa de API.

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor
NGINX | 14/07/2021

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor

Picos de tráfego e sobrecarga de servidores são preocupações sérias para varejistas online em qualquer época, mas especialmente durante a “Cyber Season” de compras de fim de ano. Detalhamos como você pode aproveitar as soluções de entrega de aplicações de nível de produção da NGINX para se preparar para aumentos repentinos de tráfego.

Distribuição segura de chaves privadas SSL com o NGINX
NGINX | 02/04/2019

Distribuição segura de chaves privadas SSL com o NGINX

Descrevemos três maneiras progressivamente mais seguras de proteger chaves privadas SSL ao configurar o NGINX para processar tráfego HTTPS: permitir acesso de leitura apenas ao usuário root, criptografar as chaves com senhas armazenadas separadamente e distribuir as senhas a partir de um repositório central.

Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX
NGINX | 24/05/2018

Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX

O módulo JavaScript do NGINX lançado com o NGINX Plus R15 oferece suporte a subsolicitações, possibilitando uma classe totalmente nova de casos de uso para o NGINX Plus. Este exemplo completo também usa a API do NGINX Plus e os módulos de chave-valor para converter solicitações de API dos clientes em solicitações separadas para as APIs dos microsserviços que compõem um aplicativo.

Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus
NGINX | 19/04/2016

Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus

Confira dicas para evitar o esgotamento de portas efêmeras com ajustes no kernel do Linux, conexões keepalive e conexões vinculadas dinamicamente a endereços IP locais.