BLOG | NGINX

Balanceamento de carga de uma infraestrutura dinâmica com NGINX, Chef e Consul

NGINX-Parte-de-F5-horiz-preto-tipo-RGB
Miniatura de Kevin Reedy
Kevin Reedy
Publicado em 22 de maio de 2017


Este post é uma adaptação de uma apresentação de Kevin Reedy, da Belly Card, no nginx.conf em outubro de 2014. Embora isso tenha acontecido há alguns anos, o conteúdo ainda é altamente relevante hoje. Você pode assistir a uma gravação da apresentação no YouTube .

Índice

0:00 INTRODUÇÃO
  visão geral
  Aviso de isenção de responsabilidade
1:16 O que é barriga?
  Pilha da barriga
1:44 Versão 0: A Idade das Trevas
2:04 Versão 1: Uma Nova Esperança
2:35 Versão 2: Página inicial e API separadas
  Palavra da moda do dia: Arquitetura Orientada a Serviços!
  Habilitar SOA
  NGINX substitui ELB
  Configuração de servidor upstream e virtual
  Resultados
4:43 Configuração com Chef
  Receitas
  Arquivos
  Modelos
  Livros de receitas
6:49 Exemplo: Chef para NGINX
  Instalação, configuração e ajuste
  Roteamento de tráfego da API
9:46 Exemplo de Chef do Mundo Real
10:08 Versão 2: Implantando aplicativos
10:40 Versão 3: SOA Todas as Coisas
  Então Heartbleed aconteceu
  SSL Todas as Coisas
12:25 Versão 4: Docker
  Benefícios
  Implantando contêineres
15:45 Estratégias de Implantação
17:43 Opções de descoberta de serviço
18:33 Arquitetura do Cônsul
19:30 Características do Cônsul
22:07 Modelo de Cônsul
  Comando para iniciar o modelo do Consul
  Configuração do NGINX com o modelo Consul
  Gerenciamento de configuração com modelo Consul
24:35 Usando o Chef para implantar o Consul
25:44 Dicas profissionais
  Chef Pesquisa Parcial
  DNS
  Evitando configuração obsoleta
30:35 Questões
36:31 Informações de contato

0:00 Introdução

Bom dia a todos. Meu nome é Kevin Reedy e trabalho para uma empresa chamada Belly Card, sediada em Chicago. Temos cerca de cem funcionários e vinte engenheiros. Hoje vou falar com vocês sobre como fazemos nosso balanceamento de carga, especificamente em uma infraestrutura dinâmica em constante mudança.

0:21 Visão geral

Então, primeiro vou falar sobre nossa pilha de infraestrutura ao longo do tempo, começando com a versão 0, que chamo de Idade das Trevas. Então, veremos como usamos o Chef para configurar o NGINX. Depois disso, falaremos sobre como mudamos disso [para] usar dados de algo chamado plataforma de descoberta de serviço Consul para configurar o NGINX. Se o tempo permitir, tenho algumas dicas profissionais sobre como configurar o NGINX, especialmente quando se trata de gerenciamento de configuração.

0:49 Aviso Legal

Então, embora eu vá falar com vocês sobre Chef e Consul, quero deixar um aviso de que nada nesta palestra é específico para eles. Chef, Puppet, Ansible, Salt, CFEngine e todos os outros são ótimos produtos e você deve usar um deles. Nós gostamos do Chef e tenho certeza que muitas outras pessoas também gostam.

O mesmo vale para a descoberta de serviços. Consul, etcd e ZooKeeper são ótimos, então use o que funciona para você.

1:16 O que é barriga?

O que é barriga? Basicamente, é um substituto digital para um cartão perfurado em uma cafeteria, onde você compra dez bebidas e ganha uma grátis. Colocamos um iPad na loja, os clientes escaneiam usando o telefone ou um cartão físico com um código QR, rastreamos seus pontos, damos as recompensas e, na verdade, criamos ferramentas de marketing em cima disso.

1:36 Pilha da barriga

Mas não estou aqui para falar sobre a barriga como empresa. Se você estiver interessado, basta acessar nosso site . Vou falar com você sobre nossa infraestrutura.

1:44 Versão 0: A Idade das Trevas

Então versão 0. Na época em que havia três desenvolvedores e antes de eu trabalhar lá, o Belly era um aplicativo Ruby on Rails monolítico, o que significava que cada chamada de API e parte do nosso site iam para um único aplicativo Rails. Ele era apoiado pelo MySQL, MongoDB e Memcached, e nós o implantamos no Heroku, que é um ótimo lugar para começar.

2:04 Versão 1: Uma Nova Esperança

Então versão 1 – Uma Nova Esperança. Decidimos que o Heroku não atenderia mais às nossas necessidades, então começamos a implementar algo chamado Capistrano, que é essencialmente "melhor que um script de shell" escrito em Ruby. Ajuda você a implementar coisas.

Tínhamos cerca de seis servidores no Amazon Web Services EC2. Esse era um número estático, mas nós o aumentávamos se soubéssemos que algo grande estava acontecendo e o diminuíamos se necessário. Na frente tínhamos o AWS Elastic Load Balancer.

2:35 Versão 2: Página inicial e API separadas

Então surgiu um projeto em que queríamos separar nossa home page do resto da API. Queríamos fazer isso para podermos avançar mais rápido com nossa home page e ter diferentes desenvolvedores trabalhando nela.

2:47 Palavra da moda do dia: Arquitetura Orientada a Serviços!

A grande palavra da moda na época – e ainda hoje – é arquitetura orientada a serviços.

2:50 Implementar SOA

Então, a versão 2 da nossa pilha foi para habilitar a arquitetura orientada a serviços. Nosso primeiro plano era separar a home page da API. Isso parece muito simples – temos apenas www.bellycard.com e api.bellycard.com .

Mas acabou sendo muito complexo e nada simples, porque alguns dos nossos aplicativos móveis foram escritos estaticamente para usar www.bellycard.com/api e /api‑assets . Nossos provedores de e-mail e todos os nossos links de clique que já haviam sido enviados por e-mail para as pessoas tinham /eo para “abertura de e-mail” e /ec para “clique de e-mail”. Nosso aplicativo do Facebook foi configurado para /facebook/callback .

3:28 NGINX substitui ELB

Isso significava que o AWS Elastic Load Balancer não nos dava mais a flexibilidade necessária para rotear esse tráfego para diferentes aplicativos. Então o NGINX veio para salvar o dia. Especificamente, poderíamos ter vários upstreams e reescrever regras para rotear o tráfego para nossos diferentes aplicativos.

3:44 Configuração de servidor upstream e virtual

Neste exemplo básico, definimos um bloco upstream com seis servidores para a API e um bloco com dois servidores para a página inicial.

Há também dois blocos de servidores [definindo servidores virtuais]. Em um deles, escutamos api.bellycard.com e roteamos todo esse tráfego para os servidores da API. Por outro lado, ouvimos em www.bellycard.com e encaminhamos as coisas de acordo.

4:02 Resultados

Isso funcionou muito bem. Isso permitiu que nossos desenvolvedores agissem rapidamente. Nosso pessoal de frontend estava trabalhando em um projeto e não estava sendo bloqueado por nossa API. Então, implantamos um terceiro serviço. Acredito que foi para integração com o Passbook da Apple. Depois, um quarto: removemos todas as nossas funcionalidades do Facebook. Nossa quinta tarefa era lidar com eventos de usuários em nosso site.

Então alguém decidiu que seria uma ótima ideia escrever isso em Node.js, então agora tínhamos cinco serviços distintos em duas linguagens. Eles são todos implantados de forma independente, sem muito gerenciamento de configuração, e estávamos editando o NGINX manualmente, o que tenho certeza de que muitas pessoas começam fazendo.

4:43 Configuração com Chef

Precisávamos de uma maneira melhor de dimensionar esse processo, então fizemos isso com o Chef.

Chef é um conjunto de gerenciamento de configuração. Ele é escrito em Ruby e você pode escrever seu gerenciamento de configuração em Ruby, o que é ótimo para desenvolvedores. learnchef.com é um recurso incrível para aprender sobre o Chef; ele pode lhe ensinar muito mais sobre o Chef do que eu em 45 minutos.

Mas vou repassar alguns conceitos básicos para que todos estejamos na mesma página.

5:17 Receitas

O primeiro tipo de bloco de construção no Chef é uma receita . O chef usa muitos nomes inteligentes, como faca como ferramenta e receita , e tudo está em um livro de receitas . Isso torna tudo divertido e fácil de entender e fornece uma ótima metáfora, mas também torna muito difícil pesquisar qualquer coisa no Google.

Então aqui está a receita mais básica que consegui pensar. Instale o pacote nginx e inicie e habilite o serviço nginx .

5:56 Arquivos

Você também pode ter recursos de arquivo. Por exemplo, quero escrever o conteúdo Hello World! no arquivo /usr/share/NGINX/html/index.html .

6:08 Modelos

Você também pode incorporar isso em um sistema de modelos. Aqui eu tenho algumas variáveis g e w para Hello e Kevin e posso passar essas variáveis para um arquivo de modelo, que está no formato ERB (um script de modelo Ruby).

Então, em vez de apenas escrever o conteúdo manualmente, podemos escrever um modelo para leitura e para quem cumprimentar.

6:19 Livros de receitas

O último grande bloco de construção é um livro de receitas, que é uma coleção de receitas, arquivos e modelos. Também recursos, provedores e bibliotecas, que são recursos mais complexos. Há vários livros de receitas de código aberto e outros em https://supermarket.getchef.com , incluindo alguns para NGINX, MySQL, Java, apt e yum , até mesmo para gerenciar seus arquivos ssh_known_hosts . Praticamente os principais elementos básicos do que você está tentando fazer no gerenciamento de configuração você já pode encontrar em um livro de receitas.

6:49 Exemplo: Chef para NGINX

Vamos passar por um exemplo muito rápido do NGINX com o Chef, onde vamos instalar o NGINX e configurá-lo alterando algumas variáveis. Usaremos o Chef para descobrir onde nosso aplicativo está sendo executado e, em seguida, configurar o NGINX para rotear o tráfego para nosso aplicativo.

7:14 Instalação, configuração e ajuste

Neste exemplo, a primeira coisa que é feita na configuração do Chef é ajustar os atributos do nó NGINX, depois instalar o nginx, encontrar os nós do aplicativo e gerar uma configuração do site.

Então, neste exemplo, a primeira coisa que fazemos é definir alguns atributos do nó. Para cada nó, você pode definir valores de atributo anexando um documento JSON. Usaremos um livro de receitas NGINX de terceiros que procura configurações desses atributos. Estamos definindo worker_connections para um determinado valor, a diretiva worker_rlimit_nofile , o tipo de evento que usaremos no NGINX e até mesmo client_max_body_size .

Depois disso, incluímos duas receitas do livro de receitas NGINX. O primeiro é o nginx::repo , que configura um repositório apt ou yum, dependendo do seu sistema operacional. Então [a receita nginx ] instala o NGINX. Você também pode instalar o NGINX a partir da fonte, mas usar pacotes é mais rápido.

Em seguida, aproveitamos os recursos de pesquisa do Chef. Ao executar o Chef, você pode executá-lo como um agente na máquina ou pode executá-lo no modo solo, que basicamente o executa como um script. Quando você tem um agente em uma máquina, você pode consultar o servidor Chef em busca de nós e outros atributos.

Aqui, pedimos ao Chef para nos dar uma lista de todos os nós que têm a API da receita anexada a eles. Depois disso, criamos um modelo de arquivo de site chamado /sites‑enabled/api . A fonte dele é o template [arquivo chamado api.erb que] vou mostrar a vocês a seguir. As variáveis que passamos são os nós que procuramos antes.

A última novidade aqui é uma instrução notifies para recarregar o serviço nginx . Isso diz que sempre que este modelo mudar, eu quero que você recarregue este serviço.

8:54 Roteamento de tráfego da API

Então nosso arquivo de modelo aqui é bem simples. Temos um upstream chamado api e no ERB iteramos sobre todos os servidores pelos quais passamos como uma variável, especificando o servidor pelo endereço IP e porta 8080. Nós até colocamos um comentário com o nome do servidor. Quando um operador estiver procurando o que está acontecendo com esse serviço, será um comentário interessante para ele.

Também definimos um bloco de servidor para escutar em api.bellycard.com . Eu apenas passo todo o tráfego para a API upstream.

9:46 Exemplo de Chef do Mundo Real

Também quero fornecer um exemplo do mundo real. Pode ser muito pequeno para vocês lerem, mas dá para ter uma ideia de quão complicadas suas receitas de Chef podem ficar. Este é o modelo e a receita reais de alguns dos nossos servidores de produção hoje.



10:08 Versão 2: Implantando aplicativos

Então, agora de volta à nossa pilha. Eu disse que tínhamos implantado cerca de cinco aplicativos e estava indo muito bem. Agora tínhamos uma maneira de rotear o tráfego para eles, então nossos desenvolvedores simplesmente se apropriaram disso e hoje temos cerca de 40 aplicativos Ruby implantados em nossos servidores usando o Chef. O tráfego é roteado de forma completamente dinâmica usando o NGINX.

Nossos desenvolvedores não precisam fazer nada além de editar uma receita para incluir o nome de seu novo serviço. Todo o tráfego é roteado pelo NGINX e configurado dinamicamente com o Chef.

10:40 Versão 3: SOA Todas as Coisas

Também tínhamos cerca de dez aplicativos JavaScript frontend que são apenas arquivos estáticos que implantamos no S3 com um CDN, [Amazon] CloudFront, na frente dele. Servimos index.html a partir do bucket S3, e o restante dos ativos estava no CloudFront. Também tivemos cerca de outros cinco aplicativos que os desenvolvedores simplesmente enviaram para o Heroku porque era algo único que eventualmente se tornou produção e ninguém foi realmente informado sobre isso.

11:10 Então aconteceu o Heartbleed

[Os cinco aplicativos no Heroku] estavam separados – completamente fora da nossa infraestrutura – até um lindo dia de abril, quando o bug Heartbleed foi anunciado. Muitas pessoas se esforçaram. Heartbleed era um bug no OpenSSL que permitia que as pessoas extraíssem suas chaves privadas.

Como usamos o Chef, conseguimos atualizar nossa infraestrutura OpenSSL em todos os nossos computadores assim que um patch ficou disponível. Acredito que ele foi implantado em cerca de 20 minutos em toda a nossa infraestrutura. No entanto, a AWS (e, portanto, a Heroku) levou cerca de 24 horas para corrigir seus Elastic Load Balancers.

Isso nos levou a mover todo o nosso balanceamento de carga e terminação SSL para o NGINX, independentemente de onde ele foi implantado — tanto no S3 quanto no Heroku. Você sofre uma pequena penalidade por fazer isso, mas pelo menos naquele dia de abril valeu a pena para nós.

11:57 SSL Todas as Coisas

Então a versão 3 da nossa pilha deixou de ser “SOA todas as coisas” para ser “SSL todas as coisas”. Todo o nosso tráfego para bellycard.com e seus subdomínios passa por nossos balanceadores de carga. Nossos ativos ainda são servidos pelo CloudFront em um domínio diferente para desempenho. Não queremos a sobrecarga do SSL e também somos apenas um único data center na Costa Leste.

12:25 Versão 4: Docker

Versão 4 – a palavra da moda sobre a qual todos estão falando este ano é Docker. Como o Docker estava na versão 0.5, nossos desenvolvedores estavam animados para começar a usá-lo.

12:38 Benefícios

Os motivos [para usar o Docker] são simples.

Simplifica muito a implantação de aplicativos. Não há receitas para escrever. Você não precisa se preocupar sobre como fará a compilação de ativos. Não importa se você está escrevendo seu aplicativo em Ruby quando outra pessoa está escrevendo seu aplicativo em Python.

Essencialmente, ele separa as responsabilidades de Desenvolvimento e Operações. Seus desenvolvedores podem se preocupar com o código, quais bibliotecas usar e até mesmo quais pacotes Linux instalar. As operações podem se preocupar com mais coisas, como: onde vou implantar isso? Como vou capturar o registro dele? Como posso monitorá-lo? Depois de resolver esses problemas e operações, todos os aplicativos funcionarão, independentemente do que estiver escrito.

Um bônus disso é que permite que nossos desenvolvedores criem facilmente serviços dependentes em seus próprios laptops. Como mencionei, temos cerca de 55 aplicativos diferentes, muitos dos quais agora estão em contêineres Docker.

Digamos que você esteja trabalhando em um novo serviço para enviar campanhas de e-mail. Ele depende do serviço de e-mail. Então, na sua máquina de desenvolvimento, você normalmente baixaria o código, executaria o bundle install , iniciaria em segundo plano e “ah, mas na verdade isso depende de outro serviço, o serviço do usuário”.

Esse serviço depende de algo mais e mais. Então, na verdade, o novo serviço de campanha de e-mail depende de cerca de cinco outros serviços, além do MySQL, Elasticsearch, Redis e a lista continua.

Com o Docker, podemos criar esses contêineres a partir das mesmas receitas do Chef que usamos na produção e fornecer aos nossos desenvolvedores contêineres que eles podem baixar extremamente rápido.

Isso acelera a implantação e o desenvolvimento.

14:23 Implantando contêineres

Então, na versão 4, deixamos de implantar nossos aplicativos usando o Chef e passamos a implantá-los em contêineres. Existem inúmeras soluções para fazer isso e tenho certeza de que haverá ainda mais.

O primeiro é CoreOS e Fleet. O CoreOS é um sistema operacional Linux simplificado que executa um mecanismo de descoberta de serviços chamado etcd . Fleet é uma maneira de você definir coisas como "Quero um contêiner rodando cinco vezes e não quero que ele rode nas mesmas máquinas que este outro serviço".

Há outro chamado Deis que é semelhante ao Heroku, pois tem uma interface Git Push. Há o Mesos do Apache e o Kubernetes do Google; Flynn é outro que foi lançado recentemente. Na verdade, escrevemos as nossas próprias porque, quando começamos esta viagem, a maioria dessas ferramentas não estava em um lugar onde pudéssemos usá-las.

O nosso se chama Jockey e tem funcionado muito bem porque nosso processo de implantação é extremamente opinativo. O que é ótimo sobre o Docker é que ele essencialmente fornece um conjunto de APIs comuns para conteinerização. Não precisamos nos preocupar com muitas coisas que teríamos se estivéssemos usando apenas os contêineres LXC do Linux.

Planejamos torná-lo de código aberto, mas, como mencionei, as implantações são muito opinativas e o que funciona para nós pode não funcionar para você.

15:45 Estratégias de Implantação

Nossa estratégia de implantação também mudou quando migramos para o Docker. Anteriormente, fazíamos implantações com tempo de inatividade zero, implantando uma nova versão do aplicativo no local. Isso significa que se tivéssemos esse serviço de fax do usuário em quatro máquinas, usaríamos o Chef para baixar a nova versão, instalá-la sobre [a versão antiga] e, então, enviar um sinal ao servidor web para recarregar. Unicorn é um ótimo mecanismo Ruby para fazer isso.

No entanto, os contêineres são imutáveis. Depois que você tiver um contêiner em execução, se quiser criar uma nova compilação, você deverá criar um novo contêiner. Você pode anexar a ele, executar comandos extras e salvá-lo, como faria no Git. Mas, na verdade, se você quiser aproveitar ao máximo o Docker, seu contêiner deve ser completamente imutável.

Então isso significa que tivemos que descobrir uma nova estratégia de implantação porque não conseguimos mais implantar no local. Existem alguns por aí. Azul-esverdeado é uma cor interessante. É aqui que, se você tiver um aplicativo em execução em quatro máquinas, você o instala em quatro novas máquinas e faz com que seu balanceador de carga aponte para as novas máquinas. Depois de ter certeza de que está realmente funcionando da maneira que você espera, você pode desmontar o seu azul, e o seu verde se tornará o azul. A Amazon tem algumas ferramentas realmente excelentes para fazer isso com a AWS.

Também há implantações “canary” onde eu implanto uma versão da nova máquina, monitoro-a e, se ela passar nas verificações de métricas e verificações de integridade, posso continuar a implantação.

A diferença com os contêineres aqui é que você vai realmente desmontá-los e criar novos, então você precisa de algum tipo de sistema para rastrear a localização de cada aplicativo em execução na sua infraestrutura.

Chef está realmente começando a se tornar uma ótima maneira de fazer isso. Há um livro de receitas que está sendo incorporado, chamado Chef Metal, que permite que você trate os contêineres como qualquer outro recurso que você faria na sua infraestrutura do Chef.

17:43 Opções de descoberta de serviço

Há também a descoberta de serviços. O ZooKeeper é uma ferramenta muito popular usada em todo o Hadoop. [O Airbnb] tem um ótimo produto chamado SmartStack que permite que você faça implantações e as acompanhe no ZooKeeper.

Mencionei o etcd , que é essencialmente um armazenamento de chave-valor distribuído com uma interface REST. Isso é ótimo em comparação ao ZooKeeper, que é mais uma biblioteca cliente Java, porque agora você pode se comunicar com o etcd a partir de qualquer um dos seus aplicativos. Muitas dessas coisas de plataforma como serviço de código aberto que mencionei anteriormente – como Deis e Flynn e até mesmo o Kubernetes do Google – usam etcd. Se você estiver usando o CoreOS, o etcd já está lá para você e integrado.

Outro que foi lançado, também baseado em REST, é chamado Consul . Ele foi lançado pelo pessoal da HashiCorp, que cria o Vagrant, o Packer e várias outras ferramentas incríveis. Na verdade, decidimos usar Consul.

18:33 Cônsul Arquitetura

Aqui está um diagrama dos princípios básicos do Consul. Você pode ver que há vários data centers, cada um com três servidores. No Data Center 1 também há clientes. O interessante é que entre seus agentes de servidor, você elegerá um agente primário e então todos os seus clientes estarão cientes não apenas de todos os servidores, mas também de todos os outros clientes. Eles então usam um protocolo de fofoca para se comunicar com todos os outros agentes.

Isso me lembra de um antigo comercial da AT&T onde você conta a dois amigos que contam a dois amigos e eles contam a dois amigos e a mensagem se espalha dessa forma por toda a sua rede de nós. [ Editor – Bem, quase: era um comercial do xampu Fabergé Organics . ] Isso é comparado ao etcd ou ZooKeeper, onde você basicamente tem apenas agentes de servidor e seus clientes se conectam a eles.

Com o jeito Consul de fazer as coisas, você realmente executaria um cliente Consul em praticamente todos os servidores, em todos os lugares onde implantamos o Docker e em todos os lugares onde executamos nossos balanceadores de carga. Então você sempre pode falar com essa API na porta 8500 do host local.

19:30 Cônsul Destaques

Assim como o etcd, [Consul] é um armazenamento de chave-valor distribuído. Você pode definir e obter chaves e elas manterão a linearização para que você possa ter certeza de que elas serão sempre consistentes. Há alguns problemas aí, mas a documentação sobre onde eles estão é fenomenal. No entanto, diferentemente do etcd, eles tratam a descoberta de serviços como um cidadão de primeira classe.

Em vez de apenas pares de chave-valor, você também pode registrar serviços, por exemplo, uma API. Ao registrar um serviço, você informa ao Consul em qual nó ele está sendo executado. Isso significa que quando implantamos um contêiner, também informamos ao Consul para registrar essa API de serviço neste host.

Além disso, o Consul distribuiu verificações de integridade, então agora você pode definir verificações de integridade no estilo Nagios diretamente na sua plataforma de descoberta de serviços. Ao decidir consultar o Consul, você pode solicitar uma lista de todos os locais onde o serviço de API está sendo executado. Você pode enviar um sinalizador para “todos” ou “somente aprovados” ou “somente não saudáveis”.

Ele também oferece suporte para vários data centers. Mencionei que você deveria executar o cliente Consul em todos os lugares. Ao iniciá-lo, você passa um parâmetro especificando o data center. Se você tiver um Data Center Leste e um Data Center Oeste, poderá consultar seu cliente Consul local sem precisar estar ciente do data center, solicitando um endereço ou algo assim.

Na verdade, usamos o data center como um limite para nossos ambientes de preparação e produção. Nossa configuração para um aplicativo em preparação pode dizer: “pergunte-me onde está MySQL.services.consul ”. Não importa se isso está sendo executado em um nó de preparação ou de produção, você obterá o valor correto sem precisar ter conhecimento de data center ou multiambiente.

A outra coisa ótima sobre ele (e também sobre o etcd) é que ele tem uma longa pesquisa em sua interface HTTP. Isso significa que você pode consultar e solicitar uma lista de todos os servidores que estão executando este serviço, mas também manter a conexão aberta por 60 segundos e ser notificado imediatamente se algo mudar. O tempo de votação pode chegar a até 10 minutos. Isso significa que você pode receber notificações instantâneas de quaisquer alterações em sua infraestrutura.

A outra coisa que já mencionei é que você pode desenvolver a capacidade de expandir seus agentes tendo clientes em todos os lugares. Isso é ótimo porque você sempre pode falar com o localhost.

A grande questão, porém, é: agora que tenho esses dados em uma plataforma de descoberta de serviços distribuída, como configuro o NGINX a partir dos dados?

22:07 Modelo de Cônsul

Felizmente, existe uma ferramenta chamada Consul Template . Ele foi lançado literalmente ontem, o que me fez mudar meus slides de hoje a partir de agora. Costumava ser chamado de “Consul HAProxy”, o que era um nome terrível porque não era específico do HAProxy.

O Consul Template oferece uma interface muito simples para criar modelos para assinar alterações em serviços, verificações de integridade desses serviços e até mesmo um armazenamento de chave-valor. Isso é para que você possa armazenar configurações como [o número de] trabalhadores NGINX dentro do armazenamento de chave-valor e regenerar sua configuração quando isso mudar.

A grande habilidade aqui é gerar arquivos a partir de modelos, o que parece muito com o que fazíamos com o Chef antes. A maior diferença aqui é que ele usa a linguagem de modelagem Golang, ao contrário do ERB, que é Ruby. Depois de alterar um arquivo, você pode opcionalmente chamar um comando sobre a alteração, por exemplo service nginx reload .

22:59 Comando para iniciar o modelo do Consul

Então aqui está um exemplo de execução do Consul Template na linha de comando. Você aponta para seu host Consul real, que neste caso é consul‑prod.example.com . Em um ambiente de produção real, eu sugeriria executar o Consul em todos os lugares e conectar-se ao localhost.

Em seguida, você passa um arquivo de modelo, que é um modelo Golang. No nosso caso, estamos passando /etc/consul‑templates/api . Em seguida, você passa qual arquivo realmente deseja gravar, então, no nosso caso, /etc/NGINX/sites‑enabled/api . Então um comando para chamar: service nginx reload .

23:32 Configuração NGINX com modelo Consul

O modelo do Consul é muito parecido com um slide que eu tinha antes, exceto que em vez de ERB é Golang. Então definimos dois upstreams aqui. Uma é chamada de API e a outra é chamada de página inicial . Temos uma declaração de intervalo para a API de serviço e há variáveis integradas para obter o IP e a porta onde o serviço está realmente sendo executado.

23:54 Gerenciamento de configuração com modelo Consul

O que é ótimo sobre o Consul Template e usá-lo dessa forma é que a convergência nas mudanças de serviço é rápida. Antes de implantar com o Docker, o Chef era executado a cada 5 ou 10 minutos, dependendo da máquina. Isso foi rápido o suficiente para nós porque estávamos nos destacando no local.

Agora que estamos construindo um sistema de implantação mais avançado, precisamos ter notificações dessas alterações em segundos, em vez de minutos. Na verdade, obtemos isso em milissegundos, em média, provavelmente cerca de 200 milissegundos.

Entretanto, o gerenciamento de configuração ainda é necessário para gerar modelos. Não podemos simplesmente substituir o Chef pelo Cônsul. Ainda precisamos descobrir como vamos implantar o Consul, o Consul Template e tudo mais.

24:35 Usando o Chef para implantar o Consul

Então, na verdade, estamos usando modelos do Chef para implantar nossos modelos do Consul, o que parece um pouco complicado. A primeira coisa que fazemos na nossa receita do Chef é consultar o nosso anfitrião do Cônsul para obter uma lista de todos os serviços. Em seguida, geramos um modelo Consul [com o modelo e as declarações de origem ] e passamos nosso certificado SSL e locais de chave e recarregamos consul‑template . [ Editor – O Sr. Reedy inicialmente se referiu a consul‑haproxy , que aparece na primeira declaração de notificação no slide. Ele então se corrigiu e esclareceu que o slide é anterior ao lançamento do Consul Template. ]

Também escrevemos um arquivo de configuração para o modelo do Consul e passamos [variáveis especificando] o host do Consul, a origem, o destino e o comando de recarga. Este é realmente o cerne de como estamos usando o Chef e o Consul juntos para obter atualizações instantâneas em nossas configurações NGINX.

25:44 Dicas profissionais

A seguir, tenho algumas dicas profissionais sobre a configuração do Chef, do Consul e do NGINX em geral.

25:52 Chef Busca Parcial

A primeira dica é que se você estiver usando a pesquisa do Chef para descobrir onde seus serviços estão sendo executados, você deve consultar a pesquisa parcial do Chef. O problema com a pesquisa do Chef é que ela faz uma cópia do nó inteiro, incluindo todos os atributos. Se você salvar muitas coisas nos atributos do seu nó, você terá que puxá-las pelo fio enquanto fala com seu servidor Chef, e também armazená-las na memória.

Se a pesquisa do Chef retornar centenas ou milhares de servidores, você poderá ver facilmente como pode ter ficado sem memória para sua receita atual. A pesquisa parcial permite que você retorne apenas as chaves que lhe interessam.

Por exemplo, primeiro tivemos

nós = pesquisa(:nó, 'receita:belly-api')

Essa pesquisa retorna cada informação sobre cada objeto. Isso inclui informações sobre espaço em disco, RAM, CPU e todos os aplicativos que escreveram seus próprios atributos de nó.

Em vez disso, podemos usar uma pesquisa parcial, onde criamos um novo hash chamado search_keys e fornecemos a ele uma lista de chaves com as quais nos importamos – neste caso, apenas o nome e o endereço IP. Em seguida, acessamos a API muito semelhante chamada partial_search e passamos o parâmetro adicional [ keys ].

26:53 DNS

A segunda coisa que nos incomodou quando mudamos para o balanceamento de carga no S3 e no Heroku é que o NGINX usa DNS para resolver os nomes de host nos blocos upstream somente na recarga da configuração. Isso significa que se você estiver configurando um servidor upstream para s3.amazonaws.com ou anything.herokuapp.com e ele mudar, seu balanceador de carga não saberá sobre o novo endereço IP até a próxima recarga.

A maneira como contornamos isso foi realmente fazer a resolução de DNS no Chef e então acionar a recarga do NGINX quando isso mudar. Isso levou a um segundo problema: [a ordem dos endereços em uma resposta DNS] nem sempre é a mesma, então certifique-se de classificar a resposta antes de escrevê-la em seu modelo.

27:36 Evitando configuração obsoleta

O outro problema quando você começa a implantar toneladas de serviços é que você quer evitar uma configuração obsoleta. [ Editor – O Sr. Reedy pausa a apresentação brevemente para responder a uma pergunta da audiência. ] No Apache, NGINX e outras coisas UNIX, um padrão de configuração comum é ter uma pasta conf.d e então carregar tudo dela. Então, se eu implantar os serviços A, B e C, eu crio service-a.conf , service-b.conf e service-c.conf .

Então decidi substituir o serviço B pelo D e agora tenho quatro configurações na pasta de configuração do NGINX, mas o serviço B não existe mais. Você pode acabar com conflitos em B versus D porque eles têm um nome de host semelhante.

Há duas maneiras de fazer isso [remover configurações obsoletas] no passado. Com modelos, você pode adicionar uma função :delete , mas isso se tornou meio complicado muito rápido. Basicamente, tínhamos uma lista de serviços antigos que sempre tentávamos excluir, caso existissem. Isso não foi realmente escalável.

Outra coisa que você pode fazer é renderizar todas as configurações do seu site em um único arquivo. Muitas pessoas se referiram a isso como “mover a idempotência para cima”. Basicamente, em vez de ter uma configuração NGINX que carrega de várias fontes, coloque tudo no seu nginx.conf .

Isso torna o processo um pouco complicado quando você está realmente efetuando login na caixa, mas espero que estejamos chegando ao ponto em que você não precise mais solucionar problemas de um arquivo de configuração ativo na produção. Se ainda estiver um pouco pesado nas suas receitas do Chef, o que fazemos é ter um nginx.conf que carrega uma série de sites diferentes. Por exemplo, um dos arquivos de configuração do nosso site lista cerca de 30 serviços, e então temos um para o Heroku, um para todos os serviços do S3, etc.

Então, se você renderizar todas as configurações do seu site em um único arquivo ou em uma pequena quantidade de arquivos, não precisará se preocupar em limpar tudo depois. Se, do ponto de vista do Chef, um serviço desaparece, o Chef simplesmente para de renderizá-lo no arquivo real.

30:35 Perguntas

P: Como o Consul tem funcionado para você até agora?

UM: Nós amamos o Consul, e o que eu realmente gosto nele em comparação com algo como o etcd é que há serviços que continuam sendo desenvolvidos em cima dele. Não preciso me preocupar com a descoberta de serviços. Na verdade, se você tem aplicativos legados e implanta (digamos) seus servidores MySQL usando o Consul, o Consul também fornece uma interface DNS.

Seu aplicativo não precisa estar ciente do Consul; ele pode simplesmente consultar “qual endereço obtenho de mysqldb.services.consul ?”. Neste caso, o Consul é o servidor DNS. Você configura sua infraestrutura de DNS para que, se o TLD [domínio de nível superior] terminar em .consul , a consulta seja roteada para o Consul.

Foi dimensionado muito bem para nós. Estamos executando cerca de 3 nós em produção para agentes de servidor e cerca de 60 clientes. Não tivemos nenhum problema. Eles continuam adicionando recursos e não quebram a compatibilidade com versões anteriores, então atualizar sempre foi ótimo.

P: Você usa o NGINX Plus?

UM: Nós não. Nós analisamos exatamente isso quando começamos a trabalhar com a Consul. Se não precisássemos de um sistema de modelos, seria ótimo porque poderíamos ter apenas um script que escuta essa longa pesquisa HTTP e então fala com a API NGINX em seu nome. O único problema é que você provavelmente também desejará um sistema de modelos caso o NGINX seja reiniciado. Ele recarregaria suas configurações upstream ali mesmo.

Há também algum trabalho que outras pessoas fizeram no NGINX Lua para consultar o Consul diretamente. Ainda não vi uma boa implementação, porque elas tendem a se enquadrar em uma de duas categorias. A primeira é que eles consultam o Consul em cada solicitação HTTP, o que é lento. A segunda é que eles carregam o arquivo no tempo de execução da configuração e você acaba com o mesmo problema que tem com o DNS. Então, a questão dos modelos é melhor por enquanto, mas eu não ficaria surpreso se víssemos uma maneira de fazer isso com o NGINX Lua no futuro.

P: Você se afastaria do Chef?

UM: Não há uma ótima maneira incorporada ao Consul para manter esses modelos, e já estamos implantando o NGINX com o Chef. Nossas receitas por aí têm centenas, se não milhares, de linhas neste momento para todas as outras coisas que estamos fazendo com o NGINX, incluindo registro, rastreamento e algum OAuth. Não vejo que iremos nos afastar do Chef em nossa infraestrutura e substituí-lo, mas é um ótimo aumento e uma boa maneira de obter notificações rápidas.

P: Quanto de overhead o Chef fornece?

UM: Como a maioria das nossas máquinas realiza uma única tarefa, nossa sobrecarga real de Chef é bem baixa. O uso de RAM é baixo enquanto está ocioso. Na verdade, ele fica em um temporizador e pode ser bifurcado. Outras pessoas também o executam em um cron se não se importam com a rapidez com que ele converge. Observamos um pequeno aumento na CPU em algumas de nossas receitas mais pesadas, mas nada que não possamos simplesmente implantar outro servidor para consertar.

P: O quanto você fez com o CloudFormation?

UM: Ainda não estamos usando o CloudFormation. Está no nosso radar, mas uma mudança que fizemos foi utilizar muito mais grupos de dimensionamento automático. A maneira como isso funcionará é que, quando uma instância surgir, ela terá dados de usuário que contêm sua lista de execução do Chef.

Uma nova máquina surgirá em um cluster com uma chave já baseada em sua imagem, para que ela possa se comunicar com nosso servidor Chef, registrar-se e obter os livros de receitas de que precisa. Isso resolve a maior parte do problema do CloudFormation para nós, porque não estamos usando muitas outras ferramentas da AWS que funcionariam junto com isso.

P: Como você lida com um servidor sendo destruído?

UM: Se um servidor desaparecer em um grupo de dimensionamento automático, você poderá usar o Amazon SNS [Simple Notification Service] para receber uma notificação sobre isso. Temos um serviço muito simples que escuta essas notificações e depois limpa o servidor Chef.

P: Você já usou o OpsWorks da AWS?

UM: Nós não temos. Temos usado o Chef hospedado desde o início e tem funcionado muito bem para nós. Não tenho certeza sobre isso, mas acredito que o OpsWorks é mais como o Chef Solo, onde você o usa apenas para provisionamento. Ainda executamos o Chef Agent em quase todas as nossas máquinas e usamos as mesmas receitas do Chef para gerar contêineres Docker para desenvolvimento.

36:31 Informações de contato


"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."