
[Trilha CI/CD]: Parte II — Criando um pipeline de IaC com GitLab para provisionar uma instância EC2 na AWS com Terraform
Opa, voltando com TUDO pessoal, hoje vamos dar sequência na nossa trilha de CI/CD com GitLab. Para quem está por dentro do meu último post, viu que eu escrevi sobre como você pode provisionar uma instância do GitLab (Self-managed) na AWS com Terraform e Ansible. Dessa vez, vamos ir além e usar o SaaS (Software como Serviço) do GitLab para brincar mais com a parte de pipelines. Seu café está no jeito? Prepara ele aí, que hoje você saí daqui sabendo muita coisa legal sobre pepilines e GitLab, bora nessa!? ☕️
A ideia para hoje é mostrar para vocês, uma forma bem simples de pipeline de CI/CD com GitLab para provisionar uma instância EC2 na AWS com Terraform, na verdade seria um pipeline de IaC (Infrastructure as Code). Não pretendo aqui hoje passar as boas práticas de pipeline ou de GitLab para vocês, estou estudando MUITO ainda e com o passar do tempo eu acredito que posso escrever mais sobre GitLab, mas por agora, vamos de basição mesmo, assim a gente tem uma noção de como usar um pipeline de IaC no nosso dia a dia.
É bem simples, mas já é um começo para você dar sequência e melhorar a esteira de CI/CD aí no seu laboratório/projeto/trabalho.
Parte I
No post anterior eu falei brevemente sobre GitLab, Terraform e Ansible, sugiro fortemente que você releia se ainda possui dúvidas e talz, claro, sinta-se a vontade para me chamar aqui também, estamos aqui para aprender juntos.
Lá eu também explico porque o GitLab é MUITO utilizado para CI/CD e porque você precisa conhecer sobre a abordagem de IaC que está cada vez mais forte.
Agora você que está chegando… ainda não leu? Segue o post abaixo! 🚀
Comunidade…
A parte boa de TUDO isso, é que temos amigos na comunidade que se importam com as pessoas, que abraçam o movimento e sempre ajudam, sugiro fortemente que você também acesse o blog do querido Rafael Gomes a.k.a Gomex, ele foi um dos pioneiros em escrever sobre pipelines de CI/CD, as boas práticas, etapas e ferramentas ideais para você usar no dia a dia.
Não poderia deixar de citar outra pessoa que ajuda demais também na comunidade, um tempo atrás o Jeferson Fernando a.k.a Badtux fez algumas lives MUITO legais no YouTube para impulsionar o pessoal a tirar a certificação do GitLab (GitLab Certified Associate). Vale demais assistir e pensar já na certificação do GitLab, que é muito reconhecida pelo mercado.
Café no jeito? Cadeira ajustada? Bora nessa e já desejo uma belíssima leitura!
Stack
Para o nosso hands-on de hoje, você precisa seguir com a seguinte stack:
- Ter o Terraform instalado na sua maquineta/instância/VirtualBOX.
- Ter o Git instalado na sua maquineta/instância/VirtualBOX.
- Ter uma maquineta com LINUX (Ubuntu/CentOS).
- Ter uma conta free tier na AWS.
- Não precisa ter conhecimento prévio de IaC (vamos aprender…)
- Possuir uma conta no GitLab para que possamos criar um projeto.
Conceitos
Antes de partir logo para o nosso queridíssimo GitLab, tenho que direcionar você para alguns conceitos que são extremamente relevantes que envolve todo o ciclo de uma pipeline de CI/CD.
- Integração contínua (CI): é a prática de integrar as alterações de código com a maior regularidade possível. O processo de CI é um pré-requisito para entrega contínua (CD).
- Entrega contínua (CD): é um conjunto de práticas em que as alterações de código são implantadas automaticamente em um ambiente de aceitação. O CD inclui procedimentos cruciais para garantir que o software seja testado adequadamente antes da implantação e fornece uma maneira de reverter as alterações, se necessário.
- Pipelines: é um processo automatizado de execução de comandos através de uma ferramenta de CI/CD, como o próprio GitLab. A ideia por trás do pipeline é executar uma esteira de DevOps de forma automática e contínua, integrando as alterações de código com a maior regularidade possível ao longo do desenvolvimento do aplicativo/infraestrutura.
- SaaS: Software como Serviço (SaaS), permite você se conectar e usar serviços baseados em nuvem pela internet. Como exemplos temos, Gmail, GitLab, Slack). Todas as operações e tarefas de manutenção e dados dos aplicativos são tratados pelo provedor de serviços.
- Controle de versão: é a prática de rastrear e gerenciar alterações em um documento. É um sistema que registra alterações em um arquivo ou conjunto de arquivos ao longo do tempo para que você possa recuperar versões específicas posteriormente. O mais usado no mundo hoje GIT.
- DevOps: é uma cultura que segue a premissa da colaboração, comunicação e o mindset da automação. Vai além da implementação de um conjunto de tecnologias e exige uma mudança completa na cultura e nos processos.
O DevOps exige engenheiros que atuam em pequenos componentes (em vez de um recurso inteiro), diminuindo as entregas para evitar erros.
GitLab
Iniciando aqui pelo GitLab, onde precisamos fazer algumas ações para que tudo fique bem ajustado, vamos ser bem diretos para que o post não fique muito extenso. Primeiro de tudo temos que criar nosso projeto no GitLab, para isso, vamos na documentação do GitLab, é a melhor forma de se aprender uma tecnologia, eu poderia tirar os prints aqui das telas mostrando os passos mas isso deixaria o artigo enorme e não “treinava” você a se virar na documentação…
- Criando seu projeto do zero
Para criar seu projeto do zero, você deve seguir os passos conforme mostrado abaixo seguindo o link mencionado, você precisa adicionar um nome para seu projeto, uma breve descrição e um README.md.

- Adicionando sua chave SSH ao GitLab
Precisamos adicionar a chave SSH (public key) para que possamos nos conectar no repositório localmente:

- Clonando seu repositório
Feito a parte de ajustes da sua chave de SSH, está na hora de você clonar seu repositório na sua maquineta para que você possa trabalhar localmente dentro do seu projeto.

- Adicionando as variáveis
Um ponto super importante nesse processo todo são as variáveis que o GitLab usará para se conectar no provider da AWS com o Terraform. Para isso usaremos a figura abaixo como exemplo, onde você poderá adicionar as suas variáveis. Veja esse link para ajustar as suas variáveis. Usaremos as as seguintes variáveis:
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY

Terraform
Para este exemplo de hoje, eu vou usar um projeto bem simples com Terraform, que nesse caso é provisionar uma EC2 na AWS, claro, vamos adotar algumas boas práticas, como uso de variáveis e separar tudo em vários arquivos “.tf”. Eu poderia vir aqui e subir um monte de recursos na AWS usando o pipeline de CI/CD, mas não ficaria bem legal aqui porque deixaria o artigo extremamente grande, o ideial seria usar o Youtube (confesso que já pensei em migrar pra lá) 😝
Hora de definir nossos arquivos “.tf”. Por boas práticas do Terraform, sempre é bom criar vários arquivos (.tf) para que fique mais organizado o diretório de trabalho e os serviços que você está provisionando e sempre que possível, use módulos no Terraform (locais ou de produtos como AWS, Azure, GCP), para que você evite código duplicado, configuração complexa de arquivos (.tf) e limites de reusabilidade, os módulos existem justamente para sanar estes tipos de problemas.
Abaixo vou declarar nossos arquivos (.tf) que usaremos nesse projeto, alguns arquivos eu tenho adicionado variáveis, uma boa prática também e outros não, justamente para mostrar como ficam alguns arquivos com variáveis. Se você tiver dúvidas na criação das credenciais do Terraform, veja esse outro artigo que eu escrevi no passado, lá está bem exemplificado.
O arquivo de variables.tf que vamos usar para declarar as variáveis do Terraform:
No arquivo provider.tf, vamos declarar o bloco de versões, o próprio provider e o resource que será usado para criar a instância na AWS.
Partindo para o Pipeline
Chegamos na parte principal aqui do post onde teremos que codar o pipeline que usaremos para este nosso exemplo de hoje. Para que vocês possam entender de forma legal, como funciona cada etapa de um pipeline eu deixei aqui abaixo, uma parte da documentação onde é mostrado algumas etapas de forma bem simples mesmo, ele usa comandos mais básicos e explica os stages, maneiro demais também que ele mostra o diagrama de um arquivo simples do .gitlab-ci.yml. Veja esse link:

Bom, basicamente precisamos criar o arquivo oculto .gitlab-ci.yml
para que o GitLab entenda que estamos lidando com o CI/CD. É nesse arquivo que declaramos como o nosso pipeline vai se comportar. Vamos entender melhor nosso pipeline antes de prosseguirmos para a execução do mesmo. Aqui abaixo o modelo de pipeline que estaremos usando para nosso exemplo:
Como é um exemplo bem simples esse pipeline, veja que usei poucos recursos e está sendo utilizado apenas 3 stages. Abaixo eu exemplifico melhor:
- Image: a palavra image é o nome da imagem do Docker utilizado para executar os jobs de CI/CD. Ele puxa essas imagens do Docker Hub (Registry).
- Entrypoint: basicamente ele especifica um comando que sempre será executado quando determinado container for iniciado. Veja abaixo um exemplo de entrypoint no GitLab CI/CD:
- Stages: definem quando executar os trabalhos. Por exemplo, stages que executam testes após estágios que compilam o código. Por boas práticas, um pipeline típico pode consistir em quatro stages, executados na seguinte ordem:
A
build
stage, with a job calledcompile
.
Atest
stage, with two jobs calledtest1
andtest2
.
Astaging
stage, with a job calleddeploy-to-stage
.
Aproduction
stage, with a job calleddeploy-to-prod
.
- before_scripts: substitui um conjunto de comandos que são executados antes do trabalho.
- cache: lista de arquivos que devem ser armazenados em cache entre execuções subsequentes.
Os stages dessa pipeline definem como o Terraform vai executar os comandos de init
, plan
, apply
ao longo da esteira estabelecida, ou seja, é através de cada stage que eu digo para o GitLab que determinado comando só será executado somente, se, houver um branch neste caso, no primeiro stage.
Para o segundo stage, eu uso o comando terraform plan
que vai executar um plano da infraestrutura somente se houver um merge request criado, ou seja, é nesse momento do merge request que o time pode validar se está correto o plano da infraestrutura com o Terraform. Caso esteja correto, deverá ocorrer uma aprovação do merge request e em seguida o merge de fato, isso chamará o terceiro stage da pipeline.
Para esse terceiro stage, o comando terraform apply
será executado, ou seja, com tudo analisado no merge request e aprovado, eu posso aplicar as mudanças na infraestrutura e isso o GitLab cuida pra mim. Veja abaixo que ele está configurado com o parâmetro only
para a branch main do meu repositório (que é a branch principal do projeto).
Executando o GitLab CI/CD Pipeline
Nesse momento, depois de tudo revisado podemos partir para a execução e verificar na prática como tudo isso se comporta. Para isso vamos direto no terminal e executar alguns comandos, afinal eu preciso subir os arquivos criados para o nosso repositório no SaaS (GitLab repository).
- Para isso crie um nova branch via Git CLI (eu já tenho criada a dev):
$ git checkout -b dev
- Vamos verificar através do comando
$ git status
o que precisa ser adicionado no SaaS do GitLab (o que tem de alterações):
$ git status
- Feito isso, vamos adicionar o que foi modificado:
$ git add .
- Agora sim, nosso
commit
:
$ git commit -m "adding new files to GitLab"
- Por fim, podemos executar o comando abaixo para subir os arquivos:
$ git push origin dev
Nesse momento ele já deve triggar nosso pipeline no GitLab:

Veja que ele executou alguns comandos do Terraform:

Aqui nesse print, podemos visualizar de forma mais nítida que nosso pipeline passou com sucesso (verifique o mais recente):

Agora que passamos pelo primeiro estágio da pipeline, vamos criar um merge request para que ele possa aplicar o comando $ terraform plan
Para isso, volte no terminal e pegue a URL que ele mostra na saída padrão:
$ git push origin dev
Enumerating objects: 31, done.
Counting objects: 100% (31/31), done.
Delta compression using up to 8 threads
Compressing objects: 100% (30/30), done.
Writing objects: 100% (31/31), 5.72 KiB | 532.00 KiB/s, done.
Total 31 (delta 15), reused 3 (delta 0)
remote:
remote: To create a merge request for dev, visit:
remote: https://gitlab.com/amaurybsouza/devops03/-/merge_requests/new?merge_request%5Bsource_branch%5D=dev
remote:
To gitlab.com:amauryborgesouza/devops03.git
* [new branch] dev -> dev
Aqui podemos já criar o merge request:

Veja que o comando terraform plan
foi executado com sucesso, mostrando que ele criará a instância EC2 na AWS:

Estamos partindo para o fim, visto que temos agora nosso merge request criado, estando correto, podemos aprovar, é nesse ponto que ele aciona novamente o terceiro stage do pipeline:

Aprovei aqui o merge e ele está executando o pipeline, veja acima que ele está passando pelos 3 stages do pipeline.

O comando terraform apply
foi efetuado com sucesso… o GitLab entende que eu aprovei o merge request e logo o pipeline aplicou na branch main do projeto, ou seja, estando correto a minha infraestrutura como código (IaC) ele triggou o stage final e aplicou o apply
:

O que podemos tirar de conclusão diante de todo esse processo? Podemos observar que existe agora um processo automatizado em forma de esteira, desde o desenvolvimento da minha infraestrutura como código, até o apply
com o Terraform, tudo gerenciado através do pipeline de CI/CD do GitLab.
Agora a cada alteração no código da minha infraestrutura na AWS, o Git detecta isso e automaticamente ele aciona o pipeline que cuida da parte dos comandos do Terraform, por stages, e assim eu tenho um processo mais automatizado de pipeline de IaC. Isso que exemplifiquei está bem simples pessoal, aqui caberia MUITAS melhorias, tanto do código do Terraform quanto da parte do GitLab.
Acredito que tenha agregado pelo menos alguns centavos de conhecimento para vocês, eu estou pensando de trazer algo mais avançado nos próximos posts, então fica ligado que vem coisa boa por aí, talvez uma pequena abordagem de GitOps!? 😄
Referências
Tenho que citar que usei fontes externas para me ajudar nas pesquisas e nos conceitos aqui mostrados. Fiz uma pesquisa em torno dos artigos do Rafael Gomes a.k.a Gomex, também assisti as lives do Youtube do canal do Jeferson Fernando a.k.a Badtux, acessei o site da CNCF e do GitLab para me basear em torno da documentação e verifiquei parte do artigo do Marcelo Cavalcante Rocha.
Agredecimentos
Começo hoje citando uma frase muito legal, mencionada por Isaac Newton em uma carta… “Se pude enxergar mais longe, foi porque me apoiei em ombros de gigantes”. Obrigado demais toda a comunidade, amigos do Twitter, leitores do Medium, ao grande parceiro Marc Pires e a galera que sempre fortalece no LinkedIn. Vocês são feras demais!!
Finalizando…
Isso seria o que eu tinha em mente para hoje sobre pipelines, como essa é a segunda parte da nossa trilha, pode esperar que vem mais, vamos ficar ninja em CI/CD com GitLab, brincar com algumas pepilines mais avançadas e quem sabe até começar uma abordagem de GitOps.
E aí, o que você achou? Gostou? Manda aquele clap sensacional! Não curtiu, acha que precisa melhorar o conteúdo? Deixe sua sugestão também. TMJ!