Integração Contínua / Entrega Contínua — Parte 4

Thalyson Rocha
9 min readDec 16, 2019

--

Neste artigo, será abordada uma das formas de fazer a entrega do sistema a um servidor de forma automática, através do Ansible.

Ansible é uma ferramenta escrita em python para automação de tarefas, seja no próprio servidor onde está sendo executado ou em servidores remotos, desde que tenha acesso autorizado. A ferramenta se comporta da seguinte forma:

  • São configurados os hosts (ou máquinas) que serão acessados para a execução das tarefas, e estes são organizados em grupos, chamados Inventories.
  • São desenvolvidos arquivos com uma série de instruções a executar nos hosts, chamados Playbooks.
  • Ao executar um Playbook, é especificado em quais hosts (Inventory) serão executadas as tarefas. O ansible se encarrega de fazer um acesso remoto ao host através de SSH e executa todas as tarefas descritas no Playbook.

Apesar de ser uma solução bem simples (basicamente uma coleção de scripts), o uso do ansible proporciona maior facilidade na execução de tarefas em lote, reutilização dos scripts de automação, além de já possuir algumas tarefas comuns prontas em seu repositório.

Além do ansible, vamos usar uma aplicação que facilita a organização, a configuração e a execução dos playbooks: AWX. O AWX é basicamente uma aplicação web que permite a visualização das ações do ansible, e se encarrega de se comunicar com a API deste para executar estas ações.

Instalação do AWX

Novamente, vamos alterar o arquivo docker-compose.yml para criar os containers necessários:

OBS.: Os containers usados neste compose foram gerados usando o processo de instalação descrito no github do projeto, que faz toda esta geração através do próprio ansible. Fique à vontade caso queira seguir o procedimento do projeto, o resultado será o mesmo.

Perceba que foi atribuido um IP estático para o container do gitlab. Este IP estático será necessário para os próximos passos.

Antes de continuar, precisamos fazer uma pequena alteração na rede do docker criada anteriormente. No terminal, digite:

docker network rm cicd
docker network create cicd --subnet 172.26.0.0/16 --gateway 172.0.0.1

O comando acima cria uma rede com seu endereço gateway fixo, para que os containers possam acessar o host.

Execute os containers (docker-compose up -d) e espere os serviços finalizarem seus processos. A primeira execução do serviço do awx pode demorar.

Com todos os serviços rodando, acesse o AWX em http://localhost:4080. Como descrito no compose, o usuário padrão é root e a senha é master.

Figura 1 — Tela de login AWX

Ao fazer login, você será direcionado ao dashboard da aplicação. A barra lateral permite a navegação, e há um gráfico com os status das execuções dos playbooks, assim como falhas em inventories ou projetos.

Figura 2 — Dashboard

Primeiramente, precisamos criar uma organização. Clique em Organizations. Nesta página é listada as organizações administradas neste servidor. Já existe uma organização chamada default, mas vamos criar a nossa. Clique no botão ➕ e crie uma organização chamada ‘Cicd’.

Figura 3 — Criação de Organização

Clique em Save. Com a organização criada, precisamos criar um projeto. Um projeto consiste em um repositório de algum sistema de versionamento (no caso, será nosso Gitlab). Neste repositório iremos armazenar e versionar nossos playbooks, e o AWX também lê estes playbooks diretamente do repositório para executá-los.

Antes de criar o projeto, precisamos conceder acesso ao AWX para o gitlab. Clique em Credentials e no botão ➕ novamente para adicionar uma credencial.

Figura 4 — Credenciais

O nome da credencial será ‘Chave_Gitlab’, em organização, selecione a organização criada anteriormente (Cicd), e em Credential Type, selecione a opção Source Control. Preencha com o nome de usuário e a senha que você configurou no gitlab. Perceba que também é possível usar uma chave SSH, mas para simplificar, usaremos usuário e senha mesmo.

Precisamos agora criar um repositório no gitlab, para guardar nossos playbooks. Acesse o gitlab em http://localhost:1080 e crie um novo repositório chamado ‘cicd’.

Figura 5 — Repositório Gitlab

Para testar o funcionamento do ansible, vamos criar o primeiro playbook: HelloWorld.yml

Este playbook instrui o ansible a acessar o host e criar um arquivo chamado teste com o conteúdo ‘hello world’. Faça o commit deste arquivo para o repositório que criamos. Agora podemos criar o projeto no AWX. Navegue até a aba Projects e clique no botão ➕ para criar o projeto. Configure o projeto conforme a imagem:

Figura 6 — Criando um projeto

Ao clicar em Save, o AWX já busca por playbooks em seu repositório, como pode ser visto na aba Jobs, um job (tarefa) é executado para esta busca.

Ok, configuramos a conexão com git e um playbook, agora precisamos fazer com que o AWX possa acessar a máquina alvo, que nesse caso, será sua própria máquina (host). Navegue até a aba Credentials novamente e clique no botão ➕. Configure a credencial de acordo com a imagem abaixo:

Figura 7 — Credencial do host

Novamente, perceba que é possível associar uma chave privada SSH, mas para simplificar o procedimento, vamos usar usuário e senha mesmo.

Obs.: O ansible usa conexão SSH para executar suas ações, logo, você precisa habilitar um servidor SSH em sua máquina. Este procedimento não entra no escopo deste artigo, configure o serviço e siga com os próximos passos 👍🏻

Salve as configurações e navegue até Inventories. Crie uma nova inventory e configure conforme a imagem:

Figura 8 — Inventory

Salve as configurações e clique em Hosts, ainda dentro do card do seu Inventory. Clique no botão ➕ e configure o novo host conforme a imagem:

Figura 9 — Novo Host

O campo Host Name é na verdade o endereço do host, que pode ser tanto um nome de domínio como www.google.com ou o IP, como foi usado na imagem. Salve as configurações.

Vamos criar agora um template. Template é por onde realmente executamos a playbook, e contém algumas configurações extras. Navegue até a aba Templates, clique no botão ➕ e crie um Job Template. Configure de acordo com a imagem:

Figura 10 — Criação de template

Navegue novamente até Templates, clique no 🚀 do template que você acabou de criar (Template Teste) e aprecie a vista 😎

Figura 11 — Arquivo teste

Como esperado, aí está o arquivo que o ansible devia criar 🎊🎉

Muito bem, agora precisamos de um servidor para executar nossa aplicação e precisamos também criar um novo playbook que vai enviar o código da aplicação para este servidor.

Para o servidor, vamos usar um novo container. Altere o docker-compose.yml conforme o modelo:

Perceba que na opção command do novo container já temos os comandos para fazer a instalação dos pacotes (npm i), buildar o projeto (npm run build) e executar a aplicação (node dist/index.js). Estes comandos serão executados toda vez que o container iniciar. Crie o container, apague o arquivo que ele vai gerar no volume, e pare o container (este procedimento só é feito na primeira execução)

docker-compose up -d projeto_maravilhoso (nome do seu projeto)
docker-compose stop projeto_maravilhoso
rm -rf ./app/*

Com isto, só falta o que realmente interessa: fazer a entrega ao servidor para que o código seja executado. Então vamos criar um playbook que faça isso. No repositório cicd, crie um novo playbook chamado Deploy.yml, conforme o exemplo:

Obs.: O campo ‘repo’ da task git é o endereço do gitlab relativo à máquina alvo, ou seja, deve ser um endereço IP acessível pelo alvo, no caso nossa máquina. Este é o motivo de ter sido atribuido um IP estático ao gitlab.

Tenha atenção também com o campo ‘dest’ da task git. O caminho escrito no trecho acima é o caminho para a pasta na minha máquina. Faça as alterações para refletir o caminho em sua máquina.

Neste playbook, temos duas ações a executar:

  1. Download dos arquivos da aplicação diretamente do gitlab para nosso servidor alvo.
  2. Enviar um comando para reiniciar o container responsável pelo build e execução da aplicação.

Perceba que incluí uma variável chamada ‘version’, que está entre chaves. Caso esta variável seja enviada, será usada. Caso não seja enviada, será usada uma padrão, que no caso é master. No campo version da task git, podem ser usados o nome da branch (que é o caso do valor padrão, master), uma tag (onde você pode versionar uma release, como v1.0.0) ou o hash de um commit.

Faça o commit e push para seu repositório. Navegue até a aba Projects no AWX e atualize o projeto Cicd para que a alteração que fizemos esteja disponível para usar. Clique no botão de atualizar conforme a imagem abaixo:

Figura 12 — Atualizar Projeto

Com o novo playbook disponível para uso, crie um novo template para que possamos executá-lo. Navegue até a pasta Templates e crie um novo Job Template, conforme a imagem abaixo:

Figura 13 — Template Deploy

Salve as configurações do template. Navegue até a aba de Templates novamente, clique no botão da vitória 🚀 e aproveite os frutos do seu trabalho bem feito 😎

Obs.: Caso haja algum problema, verifique as permissões. Tanto da pasta onde é feito o deploy da aplicação (app) quanto de acesso no repositório do git (acesso ao repositório deve estar público para baixar). Também fiz algumas alterações no projeto typescript, caso esteja usando ele, verifique as atualizações.

Se tudo der certo, você vai poder acessar a aplicação em http://localhost e será mostrado na tela:

Figura 14 — Hello world 1.0

Ansible funcionando! Vamos colocar agora a cereja do bolo!

Vamos fazer com que este procedimentos que fizemos no AWX seja feito automaticamente a cada mudança no repositório do gitlab. Para isto, acesse o jenkins em http://localhost:2080. Navegue até Manage Jenkins > Manage Plugins > Available. Procure o plugin ‘Ansible Tower’, marque e clique em Install without restart.

Figura 15 — Plugin Ansible Tower

Navegue até Manage Jenkins > Configure System e procure pelo tópico Ansible Tower. Configure conforme a imagem:

Figura 16 — Ansible Tower

No campo Credentials, clique em Add, e Jenkins Provider para adicionar uma nova credencial. Altere o usuário e senha para acesso no AWX.

Figura 17 — Credenciais AWX

Clique em Add para salvar a credencial. Selecione a credencial que você criou no campo Credentials e clique em Test Connection. Se tudo estiver funcionando, aparecerá uma mensagem de Sucesso. Clique em Save para salvar suas configurações.

Agora altere o arquivo Jenkinsfile do seu projeto, e adicione um novo stage, conforme o exemplo:

O campo towerServer faz referência ao nome da instalação do Ansible Tower que fizemos acima, no jenkins. O campo jobTemplate é o nome do template a ser executado, que está configurado no AWX. O campo inventory seleciona em qual inventory será executado este template. Você também pode passar variáveis para o template, usando um novo campo chamado ‘extraVars’.

Faça uma alteração no arquivo ‘package.json’. No campo version, altere para 1.0.1, para que você possa perceber a mudança quando for feita a próxima entrega.

Salve os arquivos, faça um commit e push em seu repositório do gitlab e se emocione com o processo todo funcionando automaticamente!

Se correu tudo certo, este deverá ser o resultado no dashboard do jenkins:

Figura 18 — Pipeline final

E com isto, acessando sua aplicação em http://localhost deve ser possível ver a mudança de versão em seu navegador.

Figura 19 — Hello world 1.0.1

E chegamos ao fim da jornada. Temos uma pipeline de CI/CD totalmente integrada, com testes, análise de qualidade e entrega automática.

Este é um fluxo bem simples, com ações relativamente básicas e baixa segurança. Em um ambiente de produção, existem algumas modificações que deveriam ser feitas, como o uso de chave privada SSH em qualquer acesso.

O ansible é uma ferramenta poderosa, assim como o gerenciador que foi usado no artigo, o AWX. Existem inúmeras outras coisas que podem ser feitas com ele, tudo isso depende de sua criatividade 👌

E é isso. Se você chegou até aqui, agradeço pela leitura e parabenizo pela perseverança!

Até a próxima! 😎

Links Úteis:

--

--