Entrega Contínua no Radar Parlamentar

Português, Brasil

Implantar qualquer software não é tarefa das fáceis. Ao utilizar um framework como o Django, tudo são flores no ambiente de desenvolvimento: é muito fácil iniciar o desenvolvimento de sua aplicação. Mas quando se trata de por em produção, mais componentes aparecem. No caso do Radar Parlamentar temos pelo menos os seguintes componentes para implantar:

  • A aplicação do Radar em si (um projeto Django).
  • Bibliotecas Python de apoio à aplicação.
  • O NGinx, servidor web.
  • O Uwsgi para fazer a ponte entre o Radar e o NGinx.
  • O PostgreSQL, o banco de dados.
  • O Celery, um servidor de mensageria, para a execução de tarefas assíncronas.
  • Edição do crontab, para execução das tarefas periódicas do Radar.

Uau! Quanta coisa! O grande problema é que uma vez que alguém consegue instalar tudo isso, é muito difícil que outra pessoa (ou até a mesma) consegui re-implantar tudo isso certinho em outro servidor. E na história do Radar já tivemos que fazer algumas migrações de servidores. Além disso, a arquitetura está sempre evoluindo. Além dos componentes acima listados, estamos começando a trabalhar com o Elastic Search, que em breve irá para produção. Então para evitar problemas, é bom haver um modo de ensaiar a instalação do novo componente em um ambiente muito similar ao ambiente de produção.

Outro problema relacionado no Radar é que apenas dois membros da comunidade possuem acesso ao servidor de produção. Assim era comum que a versão em produção ficasse defasada da versão do repositório. Várias contribuições entregues ao repositório por outros colaboradores ficavam "congeladas", sem ir à produção por um bom tempo até que um dos dois membros tivesse um tempinho para atualizar a produção.

Todos esses problemas levaram o projeto Radar Parlamentar a almejar a implementação de um fluxo de entrega contínua [1]. A ideia de entrega contínua é que cada entrega no repositório que passe por uma bateria de testes automatizados deva ser automaticamente implantada em produção! Ou seja, fez commit, já tá em produção! Para ser franco, outra motivação bem forte foi a vontade de implementar na prática, para uma aplicação real, as técnicas de implantação automatizada estudadas no meu mestrado [2].

Bom, vamos ao que rolou!

Utilizamos o Chef [3] como linguagem para produzir os scripts de implantação. Você pode considerar o Chef como uma espécie de evolução do Shell Script para automatizar tarefas em servidores remotos. Em um script Chef (chamado de "receita") você pode usar a linguagem Ruby e mais alguns construtos especiais do Chef para efetuar tarefas como executar comandos remotos, enviar arquivos, iniciar serviços, editar o crontab, criar uma base de dados, etc. Os construtos da linguagem Chef fornecem como vantagem independência de plataforma e idempotência nas ações executadas. Segue um exemplo de trecho da receita Chef que instala o Radar:

cron "dump-db" do
  action :create
  minute '0'
  hour '4'
  weekday '1'
  user user
  command 'source ~/.profile; source dump-radar.sh >> #{log_folder}/radar-cron.log 2>>&1'
end

A idemporência nesse caso está no fato de que caso essa entrada já exista no Cron, o Chef não vai criar duas entradas iguais. A idempotência é muito importante quando a execução do script falha por algum motivo espúrio, de modo que podemos prosseguir simplesmente re-executando a mesma receita. A receita completa está aqui.

Ao criar um novo ambiente (de preferência uma máquina virtual), o primeiro passo é instalar o Chef e executar a receita de instalação do Jenkins, que é o servidor de integração contínua que utilizamos. Essa receita reutiliza uma receita da comunidade para instalar o Jenkins. Isso é uma coisa legal do Chef, há várias receitas prontas para se instalar serviços e plataformas conhecidas, como Jenkins, Tomcat, PostgreSQL, etc. Mas a nossa receita também faz o trabalho de configurar o Jenkins com dois jobs:

  • job build radar: A cada commit, baixa o código do Radar e executa os testes automatizados. Se os testes passarem, dispara o próximo job (deploy radar).
  • job deploy radar: Executa a receita de implantação do Radar. É nessa hora que são instaladas as dependências do Radar, como bancos de dados, servidores web, servidor de mensageria, configuração do crontab, etc.

A figura abaixo mostra a instância do Jenkins configurada com os jobs descritos acima.

 

O arranjo dos componentes instalados pode ser visualizado na diagrama abaixo.

 

 

Mas e para desenvolver essa receita? Não podemos ficar testando as receitas Chef em produção! Vai que a gente faz alguma besteira e não consegue consertar o servidor! Para isso usamos dois caminhos:

  • Utilizar o Vagrant [4], uma ferramenta muito legal para criar máquinas virtuais em seu próprio computador, e automatizar a execução das receitas Chef nessas máquinas virtuais locais.
  • Utilizar o EC2 da Amazon AWS [5] para criar máquinas virtuais, nas quais eu executava a receita Chef.

Embora a primeira abordagem tenha a vantagem da gratuidade, eu utilizei mais a segunda opção, já que em meu laptop todo o processo de criação da VM e de execução das receitas acabava ficando bem lento.

Agora no estado atual das coisas, podemos dizer que o Radar implementa um fluxo de entrega contínua, pois cada entrega no repositório que passe pelos testes automatizados dispara a execução do script de implantação do Radar em produção. Mas ainda há alguns desafios a superar:

  • Análise estática de código para obtenção de métricas como a cobertura de código. Iniciamos com a abordagem de utilizar o SonarQube [6] para isso, mas estamos com problemas para que o Chef instale adequadamente o Sonar. Tentamos também usar o Coveralls, mas também não deu muito certo.
  • Executar periodicamente as importações de dados da Câmara dos Deputados para o Radar (esse tá quase lá!).
  • Implantar o Elastic Search para ser utilizado na busca textual do filtro temático de votações.
  • Implantar o Varnish para melhorar o cache do sistema.

Se você tem interesse em aprender ou aprimorar habilidades DevOps de implantação automatizada, venha bater um papo e contribuir com o Radar! Por a mão na massa em um caso real é sem dúvida a melhor forma de aprender!

[1] Jez Humble e David Farley. Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation (2010).
[2] Leonardo Leite. Implantação automatizada de composições de serviços web de grande escala (2014).
[3] https://www.chef.io/chef/
[4] https://www.vagrantup.com/
[5] http://aws.amazon.com/pt/ec2/
[6] http://www.sonarqube.org/
[7] https://coveralls.io/

PS: repositório com os scripts de implantação do Radar: https://github.com/radar-parlamentar/implantacao.

 

Não há comentários.

Comentar