* pache

* pache

Meu trabalho atual envolve tornar a infraestrutura que hospeda o produto muito mais escalonável e flexível. Um bom passo para ter flexibilidade na infraestrutura é ter algo bastante flexível na frente dela para conexões proxy e possivelmente fazer algo com elas. No momento, nosso provedor de infraestrutura lida com o balanceamento de carga e não podemos ajustar as coisas de forma alguma.

Aqui está como coloquei essa camada no lugar.

O que queríamos alcançar

Primeiro, queremos ser capazes de direcionar contas específicas (leia-se: subdomínios) para hosts específicos, se necessário. Pode ser porque eles são tão grandes que precisam ou porque queremos fazer um pequeno teste com eles para um recurso específico.

Então, também temos a necessidade de implementar uma atualização da infraestrutura de uma maneira suave: adicionar um novo host, rotear apenas algumas contas para ele e ver como ele se comporta.

Tudo isso é possível com muitos dos suspeitos usuais (HA-Proxy, Nginx), mas durante uma rápida conversa Jerome Petazzoni da Docker Inc. me disse algo na essência de:

“Porque não Hipache?”

Apache, para descolados

Existem 3 primos na comunidade francesa OpenSource que são conhecidos por serem assassinos. Um deles trabalha para a Docker Inc: Jerome. Lá ele faz toneladas de coisas, incluindo ser parte das pessoas que escrevem Hipache “Apache mas para descolados”.

Não é preciso dizer que confio em Jerome quando se trata desses tópicos. Li um pouco sobre o Hipache, incluindo um bom artigo escrito pelo principal autor e contribuidor do Hipache: Sam Alba. Você pode encontrar esse artigo no blog dot cloud: http://blog.dotcloud.com/under-the-hood-dotcloud-http-routing-layer .

Resumindo: o Hipache tem como objetivo ser rápido, confiável, capaz de agrupar e usar o Redis para controlar a configuração do endpoint. Redis significa que manter várias instâncias do Hipache em sincronia é muito fácil e muito rápido. Eu gostei dessa ideia.

Preparando

O Hipache, como o Docker, está em forte desenvolvimento. Provavelmente, a versão que você instalou em uma máquina não funcionará bem com os exemplos de configuração do branch master. Portanto, verifique a versão que seu npm instala e verifique a versão adequada da documentação relacionada a essa tag no repositório. Não fiz isso inicialmente e passei algumas horas tentando descobrir o que estava acontecendo.

Hipache funciona bem com HTTP e HTTPS, você só precisa passar os certificados SSL corretos. Por enquanto, tudo bem.

A configuração dos back-ends do Hipache acontece no Redis com conjuntos. O que significa que você pode fazer isso facilmente à mão ou, muito mais interessante, através de seu idioma favorito e de qualquer ferramenta de gerenciamento de infraestrutura que estiver usando.

Nginx, Unicorn

Nossa configuração em cada host envolve Nginx e Unicorn. O Nginx desempenha um papel de micro cache e serviços de ativos. Unicorn serve ao aplicativo Rails. Nossa configuração de implantação e unicórnio nos permite implantações com tempo de inatividade zero. Nada de especial aqui.

Até agora, as conexões SSL param no Nginx. Temos um pequeno bloco para lidar com o redirecionamento de HTTP para HTTPS com ele:

server {
listen
80;
client_max_body_size
4G;
return 301 https://$host$request_uri;
}

Assim que o Hipache estiver em vigor, as conexões HTTPS parariam com o Hipache. A configuração não cobre isso. E de fato, no momento, o Hipache é muito burro: insira HTTP ou HTTPS , envie HTTP . E é isso. Você não pode dizer ao Hipache “ei, o que vier no 80, você redireciona para 443”.
Se você pensar a respeito, isso faz sentido: por que confiar nas portas? Hipache é um balanceador de carga HTTP e proxy e é isso.

Olhei em volta e então me lembrei de uma curta resposta de Jerome:

“Verificamos os cabeçalhos para isso, no lado do aplicativo”

Como eu tinha certeza de quais cabeçalhos ele estava falando, pesquisei e ajustei um pequeno aplicativo Rack para ver os cabeçalhos HTTP .

require 'rack'

class HttpHeaders
def self.call(env)
headers
= env.select {|k,v| k.start_with? 'HTTP_'}
.collect {|pair| [pair[0].sub(/^HTTP_/, ''), pair[1]]}
.collect {|pair| pair.join(": ") << "<br>"}
.sort
[200, {'Content-Type' => 'text/html'}, headers]
end
end

Um pouco de config.ru com isso:

require 'rack'
require ‘./http_headers

use Rack::SSL

app
= Rack::Builder.new do
run
HttpHeaders
end

Rack::Server.start :app => app, :Port => 8082

Iniciei o aplicativo, adicionei o host como back-end no Redis / Hipache e voila:

# HTTP
X_FORWARDED_PORT
: 80
X_FORWARDED_PROTO
: http
X_FORWARDED_PROTOCOL
: http

# HTTPS
X_FORWARDED_PORT
: 443
X_FORWARDED_PROTO
: https
X_FORWARDED_PROTOCOL
: https

O primeiro é o que é exibido se eu me conectar ao host com HTTP , o segundo se for com HTTPS .

Eu sei que o middleware Rack seria facilmente capaz de pegar isso e responder rapidamente, sem envolver o resto do aplicativo. Conforme Rack vai, pelo menos 2 gemas já fazem isso: Rack-SSL e Rack-SSL-enforcer.

Um pouco de trabalho no config.ru :

require 'rubygems'
require 'rack'
require ‘./http_headers
require 'rack/ssl'

use Rack::SSL

app
= Rack::Builder.new do
use Rack::SSL
run
HttpHeaders
end

Rack::Server.start :app => app, :Port => 8082

E bem, funciona.

Então, no final, aqui está a configuração:

  1. Hipache com um redis slave, configuração HTTP e HTTPS apontando para um host HTTP
  2. Host HTTP (nginx) apenas conectando-se ao unicórnio por meio de um soquete
  3. instância unicórnio executando o aplicativo com um middleware de rack para solicitar HTTPS como origem

Aqui está o link para a página do github do Hipache: https://github.com/dotcloud/hipache e você pode encontrar uma entrevista com Jerome Petazzoni no tópico Docker ( http://blog.leanstack.io/how-docker-was- nascido ) que também contém trechos sobre Hipache.