menu

Deploy Contínuo de um Site Estático no AWS com SnapCI

Implementar uma pipeline de entrega não precisa ser uma tarefa difícil e neste artigo mostraremos como usar o SnapCI, desenvolvido pela ThoughtWorks, para fazer deploy de um site estático na nuvem usando o Amazon Web Services (AWS).

No livro "Devops na Prática" eu mostro como configurar uma pipeline de entrega para uma aplicação web Java não-trivial. Um dos objetivos do livro é mostrar como aplicar os princípios de DevOps e entrega contínua na prática, porém tivemos que escolher quais ferramentas e bibliotecas usar nos exemplos. Este artigo é uma extensão do conteúdo para mostrar que podemos aplicar as mesmas práticas usando outras ferramentas, mesmo quando a aplicação é completamente diferente.

Como parte do lançamento do livro, construímos um site estático para agregar informações, depoimentos e servir como página de marketing do livro.

Site estático do livro Devops na Prática

O código-fonte do site está hospedado no Github e o ambiente de produção roda na nuvem da Amazon, usando os serviços S3, CloudFront e Route 53.

Entrega Contínua ou Deploy Contínuo?

Essa é uma pergunta que ouço frequentemente. Nesse post, Jez Humble descreve a diferença. Deploy contínuo é a prática de ir para produção de forma automatizada sempre que um novo commit passar com sucesso pela pipeline de entrega, sem nenhum passo manual. Entrega contínua é a prática onde todo commit que passa pela pipeline de entrega pode potencialmente ir para produção, porém o momento de fazer o deploy é uma decisão do negócio.

Para entender melhor a diferença, considere duas empresas com modelos de negócio diferentes: a primeira vende seu software como um serviço (no modelo SaaS) enquanto que a segunda distribui software e cobra pelas licenças dependendo de quantas cópias são instaladas.

Enquanto a primeira empresa pode decidir fazer deploy contínuo, colocando em produção sempre as mudanças mais recentes, a segunda empresa pode preferir um ciclo de entrega mais cadenciado, uma vez que cada nova versão exige a distribuição e reinstalação do software em todos os seus clientes.

Ambos os modelos exigem uma mudança de paradigma: qualquer commit pode ser escolhido para ir para produção. Isso exige disciplina e automação e é aqui que as práticas de DevOps podem ajudar. Em particular, é preciso criar uma pipeline de entrega que modela o processo de release do software de forma automatizada. Todo commit que passar com sucesso por todos os estágios da pipeline pode ir para produção.

SnapCI

O SnapCI é um serviço desenvolvido e oferecido pela ThoughtWorks Studios, a divisão de produtos da ThoughtWorks. Ele te ajuda a evoluir um processo de integração contínua para entrega contínua, com suporte nativo à criação de pipelines de entrega.

O SnapCI integra diretamente com o Github e suporta aplicações escritas em diversas plataformas – Ruby, Java, JavaScript, Rails, Node.JS ou Python – usando diversos tipos de banco de dados – Sqlite3, PostgreSQL, MySQL, Redis, CouchDB e MongoDB. Além disso, o SnapCI suporta diferentes opções para fazer o deploy no seu ambiente de produção no Heroku ou AWS. Leia a documentação para saber mais detalhes das plataformas e ambientes de produção suportados.

O Ambiente de Produção

O ambiente de produção no AWS é relativamente simples. Usamos o S3 (ou Simple Storage Service) para armazenar todos os arquivos estáticos: HTML, CSS, Javascript, imagens, etc. O S3 atua como um sistema de arquivos altamente resiliente, onde cada objeto é replicado para aumentar sua durabilidade em casos de desastre.

Existem dois conceitos básicos no S3: buckets e objetos. Um bucket funciona como um nome único que pode ser identificado globalmente. Dentro do bucket você cria objetos que podem ser diretórios ou arquivos. Tanto o bucket quanto os objetos possuem configurações de segurança que definem quem pode acessá-los.

Apesar do S3 poder ser usado isoladamente para hospedar um site estático, nosso ambiente de produção utiliza o CloudFront que funciona como uma rede de distribuição de conteúdo, ou CDN.

Uma CDN é composta de diversos nós espalhados pelo mundo que funcionam como um cache do conteúdo original, que neste caso está hospedado no S3. Quando um usuário tenta acessar alguma URL, ele é roteado para um nó que está geograficamente mais perto, oferencendo uma conexão mais rápida para o conteúdo desejado.

Por fim, usamos o Route 53 para configurar o DNS do site. Com a integração entre os serviços do AWS, podemos usar o Route 53 para redirecionar as URLs de acesso ao site ( www.devopsnapratica.com.br e devopsnapratica.com.br) para nossa CDN no CloudFront.

Ambiente de Produção no AWS

A Amazon possui um tutorial bem documentado de como configurar um ambiente de produção parecido para hospedagem de um site estático.

Criando a Pipeline de Entrega

Podemos então criar a pipeline de entrega no SnapCI. O SnapCI integra diretamente com o Github, portanto a primeira vez que você acessar o SnapCI, ele irá te redirecionar para o Github e pedir que você autorize o acesso aos seus repositórios.

Uma vez que estiver logado no SnapCI, basta clicar no botão + Add project conforme mostrado abaixo:

Criando o projeto no SnapCI

Para criar o projeto, você precisa escolher o repositório do GitHub desejado. No nosso caso, clicamos no botão + Add do repositório devops-book-site. Você não verá este projeto na sua listagem a não ser que tenha criado um fork na sua conta do GitHub.

Escolha o repositório do GitHub para o qual você deseja criar a pipeline de entrega

O SnapCI tenta detectar o tipo da aplicação para pré-configurar uma pipeline com estágios padrão. Por exemplo, caso seja uma aplicação Rails ele irá criar um estágio chamado FASTFEEDBACK que executa o Bundler e algumas tarefas do Rake para rodar seus testes automatizados.

No nosso caso, o site estático não terá nenhum estágio pré-configurado, porém o SnapCI detecta que temos um arquivo Gemfile e nos permite escolher qual versão do Ruby usar para executar o Bundler. Deixaremos a versão do Ruby no padrão 1.9.3 e não temos necessidade de usar nenhum banco de dados. Por fim, precisamos criar um estágio para fazer o deploy do site no AWS, clicando no botão + ADD NEW:

Criando o estágio de deploy na nossa pipeline de entrega

O SnapCI irá oferecer diversos de estágio para você escolher – Rake, RSpec, Capybara, etc. No nosso caso, queremos um estágio customizado, por isso escolhemos o tipo Custom Stage. Na próxima tela, precisamos nomear o estágio e definir as tarefas que serão executadas:

Definindo as tarefas do estágio de deploy

A primeira tarefa roda o Bundler para instalar as gems necessárias. Estamos usando a gem s3_website para fazer o deploy para o AWS, pois ela gerencia o upload dos arquivos para o bucket no S3 e sabe configurar a distribuição CDN do CloudFront a cada deploy. Além disso, ela suporta a compactação de recursos estáticos usando GZIP e a configuração de opções de cache para melhorar a performance do site estático.

A segunda tarefa roda o comando s3_website push com as opções --headless para que a ferramenta não precise de nenhuma interação com o usuário e --site. para dizer quais arquivos pertencem ao site estático. Uma vez configuradas as tarefas precisamos definir algumas variáveis de ambiente clicando na aba.

Configurando variáveis de ambiente para o deploy

Por questões de segurança, você não deve colocar nenhuma informação secreta em texto puro no repositório do Github. Se você fizer isso, qualquer pessoa pode usar suas credenciais do AWS para subir vários servidores que você terá que pagar quando chegar a conta da Amazon no final do mês. Por isso optamos por definir essas informações como variáveis de ambiente que estarão disponíveis em tempo de execução sem estarem salvas no repositório de código. Para entender como elas são usadas, você pode olhar o arquivo de configuração s3_website.yml:

​s3_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
s3_secret: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
s3_bucket: <%= ENV['S3_BUCKET'] %>
...

Ao clicar no botão OK, seu projeto será criado. Em alguns instantes, o SnapCI irá executar seu primeiro build:

Execução do primeiro build do projeto

Enquanto o build estiver executando, você pode clicar no estágio para ver o log de progresso em tempo real. Ao final da execução, você terá um log completo de todos os comandos que foram executados e suas respectivas saídas:

Deploy executado com sucesso

Sucesso! Configuramos uma pipeline de entrega simples com um único estágio que faz deploy de um site estático para o AWS toda vez que um novo commit é feito no Github. Para aplicações mais complexas, sua pipeline provavelmente irá envolver mais de um estágio de teste antes de ir para produção. Conforme novos commits são realizados, o SnapCI guardará um histórico de execuções da sua pipeline de entrega, permitindo a rastreabilidade desde um commit até o deploy em produção:

Histórico de execuções da pipeline de entrega

Conclusão

Neste artigo mostramos como configurar uma pipeline de entrega simples para fazer deploy contínuo de um site estático para o AWS usando o SnapCI. O código do site está disponível no Github, caso queira saber mais detalhes do uso das ferramentas.

Apesar do nosso exemplo ser simples, ele mostra o quão fácil é configurar uma pipeline de entrega usando o SnapCI. O SnapCI possui diversas outras funcionalidades que não foram abordadas no artigo, como: promoção de artefatos, pipeline com múltiplos estágios, estágios com gatilhos manuais, suporte à pipelines de integração para branches no Github, deploy para o Heroku, e muito mais. Explore a página de documentação para mais detalhes e mantenha-se informado sobre as últimas novidades no blog do SnapCI.

Para entender melhor os conceitos e práticas apresentados neste artigo ou para ver um exemplo mais completo e elaborado, leia o livro Devops na Prática. O site estático discutido neste artigo está no ar em http://www.devopsnapratica.com.br/ e possui mais informações sobre o conteúdo do livro.