Criando infraestrutura como código utilizando Terragrunt e Atlantis na AWS

Este artigo será dividido em duas partes, no primeiro artigo vamos falar mais sobre o Terragrunt e Atlantis, sobre como estas ferramentas podem auxiliar a adoção de uma cultura DevOps na sua empresa, vamos mostrar os passos necessários para a sua instalação e integração com um repositório do Github, e na segunda parte deste artigo vamos demonstrar como podemos subir nossa infraestrutura na AWS utilizando o Terragrunt e o Atlantis, estas ferramentas irão facilitar muito o trabalho do time de Devops vantagens como o armazenamento do código em um único local, todas as mudanças na infraestrutura registradas através dos pull requests, o deployment de IaC  realizado à partir de um único local, restringir o Atlantis para que ele aplique as configurações apenas se o pull request tenha sido aprovado previamente, estas e outras vantagens podem ser obtidas através do uso destas ferramentas.

Atlantis

O Atantis é uma ferramenta para facilitar a adopção de um deployment automatizado, este processo visa a integração do seu repositório Git com a criação de pull requests, planejamento e aplicação da sua infraestrutura realizados por um servidor Atlantis. Com o Atlantis não há mais a necessidade de aplicar as configurações de Terraform localmente, todo o processo de deploy é realizado pelo servidor Atlantis. Geralmente este servidor fica em uma conta na nuvem, mas no nosso caso vamos utilizar a AWS com a inclusão de uma IAM Role com permissão de criação de recursos AWS para que ele aplique as configurações de infraestrutura como código.

Terragrunt

O Terragrunt é um “wrapper” do Terraform. Ele possui algumas funcionalidades adicionais ao Terraform, como por exemplo, ao rodar o comando terragrunt plan, por debaixo da aplicação ele está executando o terrraform plan, porém com alguns recursos adicionais.

Com o uso do Terragrunt é possível criarmos uma infraestrutura organizada por pastas, facilitando o seu entendimento e segregando o ambiente entre produção, dev, homolog, etc.

A ideia dos desenvolvedores do Terragrunt é adotar o método “DRY” “Don’t repeat yourself, ele ajuda a criar os arquivos de provider e backend baseados no arquivo raiz do Terragrunt.

Além disto ele incentiva a utilização de módulos, onde cada ambiente utilizaria parâmetros/variáveis distintas, mas sempre referenciando um modulo central, e ainda sim cada ambiente poderia referencias versões de módulos diferentes de acordo com a necessidade.

O Terragrunt também cria automaticamente a estrutura de state file remoto de acordo com a estrutura de pastas utilizadas, este trabalho é feito automaticamente toda vez que rodamos o “terragrunt apply”,

Para obter mais informações sobre o funcionamento do Terragrunt, acesse os links abaixo:

https://terragrunt.gruntwork.io/docs/#getting-started

https://terragrunt.gruntwork.io/docs/features/keep-your-terragrunt-architecture-dry/

Criação do servidor do Atlantis

Primeiro vamos configurar um servidor para rodar o Atlantis. Para isso, faremos o clone do repositório contendo alguns recursos existentes em nossa conta e em seguida iremos criar um novo branch. Neste branch vamos criar um bucket s3 e em seguida vamos realizar o push deste novo branch para o nosso repositório remoto no Github. Após iremos criar um pull request para que seja possível revisar o código a ser aplicado, assim o Atlantis irá realizar o plan automaticamente. Após a aprovação do pull request baseado no output do plan e da avaliação dos especialistas pode-se rodar o comando atlantis apply para que o Atlantis aplique de fato as alterações propostas pelo pull request.

Instalando o Terragrunt na sua máquina local

O Atlantis será configurado para rodar o terraform e o terragrunt, mas antes de realizar o push de um novo branch, podemos validar localmente se o nosso código não possui nenhum erro. Para que isso seja possível, vamos rodar o Terragrunt em uma máquina local, assim podemos validar quais serão as alterações antes mesmo de realizarmos o push para o repositório remoto e antes de abrir um novo pull pequest.

Caso não tenha ainda instalado o Terrafom, acesse o link abaixo para um guia sobre sua instalação:

https://learn.hashicorp.com/tutorials/terraform/install-cli

Abaixo os comandos utilizados para a instalação do Terragrunt em uma máquina Ubuntu:

wget https://github.com/gruntwork-io/terragrunt/releases/download/v0.35.4/terragrunt_linux_amd64

mv terragrunt_linux_amd64 terragrunt

chmod u+x terragrunt

sudo mv terragrunt /usr/local/bin/terragrunt

terragrunt –version

Para orientações de instalação em outros sistemas operacionais, acesse o link abaixo:

https://terragrunt.gruntwork.io/docs/getting-started/install/

Instalação do servidor Atlantis

Nesta demonstração vamos criar uma instancia EC2, para que seja possível instalar o servidor do Atlantis. Existem diversas formas de criar um servidor Atlantis. Neste exemplo vamos instalar o Docker e instalar o Atlantis juntamente com o Terragrunt.

Para obter mais informações sobre todas as formas de instalação basta acessar o link abaixo:

https://www.runatlantis.io/docs/deployment.html#architecture-overview

Para esse exemplo, vamos subir uma instancia Amazon Linux t2.micro na região do Norte da Virginia. No Link abaixo você pode consultar mais informações sobre como subir uma instancia Linux:

https://docs.aws.amazon.com/pt_br/AWSEC2/latest/UserGuide/EC2_GetStarted.html#ec2-connect-to-instance-linu

Utilizaremos a AMI Amazon Linux 2 AMI:

Como o servidor Atlantis irá receber os webhooks do GitHub, o servidor precisa estar em uma subnet pública.

  1. Selecionamos uma VPC existem com um Internet Gateway anexado.
  2. Selecionamos uma subnet publica, (verificar se a tabela de roteamento está configurada corretamente).
  3. Habilitamos o uso de um IP público.
  4. Precisamos configurar uma IAM Role, esta IAM role será utilizada pela instancia EC2 onde o servidor Atlantis será executado.

Obs. É através desta IAM Role que os recursos AWS serão criados, a instancia onde o Atlantis está rodando terá que ter permissão para criar todos os recursos descritos no código do Terraform.

Assim que a instancia estiver pronta vamos para o próximo passo que é a configuração do servidor Atlantis.

Configurando o Atlantis

Vamos acessar a instancia via SSH utilizando o Putty, para mais informações sobre como acessar a sua instancia Linux, por favor utilizar o link abaixo:

https://docs.aws.amazon.com/pt_br/AWSEC2/latest/UserGuide/AccessingInstances.html

Após acessar a instancia vamos executar os comandos para instalar o docker e o git:

echo nameserver 8.8.8.8 >> /etc/resolv.conf

sudo yum install docker -y

sudo chkconfig docker on

sudo yum install -y git

sudo service docker start

Em seguida iremos configurar o Dockerfile, primeiro vamos criar um diretório para armazenar o Dockerfile:

mkdir ~/dockerbuild

cd ~/dockerbuild

Vamos criar um arquivo com o nome Dockerfile, rode o comando abaixo para inserirmos o conteúdo do Dockerfile:

vi Dockerfile

Insira o script abaixo no arquivo Dockerfile:

 # Grab image to collect tools from

FROM lowess/terragrunt:0.12.31 as tools

 # Official atlantis image

FROM runatlantis/atlantis:v0.18.2

 # Install python3

RUN apk –no-cache add bash py-pip g++ python3 python3-dev build-base libffi-dev openssl-dev gnupg

Na sequência vamos rodar o build:

“sudo docker build -t atlantis:1.0 .”

Instalação do servidor realizada com sucesso.

Configurando a Integração do Atlantis com o GitHub

Faça um fork do repositório de exemplo que iremos utilizar para a criação de uma VPC. Logue na sua conta do GitHub e acesse o link https://github.com/fabiohs83/tf-lab-vpc-atlantis-model. Clique no ícone de fork conforme destacado abaixo:

Para configurar a integração entre o Atlantis e o GitHub, vamos executar o comando abaixo no servidor do Atlantis, substitua o X.X.X.X pelo IP público que o Atlantis está configurado:

docker run -p 80:4141 atlantis:1.0 server \

–gh-user fake \

–gh-token fake \

–repo-allowlist ‘github.com/your-org/*’ \

–atlantis-url=”http://X.X.X.X”

Na tela acima podemos ver que o serviço do Atlantis está em funcionamento.

Acesse o link abaixo no seu navegador:

http://X.X.X.X/github-app/setup

Lembrando que você deverá inserir o IP Público do servidor Atlantis ou o seu endpoint para poder acessar a tela de configuração abaixo:

Confira se o endereço IP exibido é o endereço correto, na sequência clique em Setup.

Você será redirecionado para a tela de Login do GitHub, e você irá criar uma aplicação, podemos customizar o nome dessa aplicação apenas para facilitar a identificação:

Ao clicar em “Create GitHub App”, irá aparecer a tela a seguir:

Anote as informações gh-app-id e gh-webhook-secret, vamos utilizar estes dados a seguir.

Na sequência clique no link em destaque conforme a imagem abaixo:

Seremos redirecionados para a tela abaixo, você poderá escolher se deseja liberar este app para acessar todos os seus repositórios ou apenas um. Neste exemplo escolhemos apenas um repositório:

Ao clicar em “Install”, irá aparecer a tela abaixo confirmando a instalação da aplicação do Atlantis no GitHub:

Cancele o comando que executamos anteriormente no servidor Atlantis e rode agora o comando abaixo substituindo os valores conforme parâmetros obtidos anteriormente:

docker run -p 80:4141 atlantis:1.0 server \

–gh-user=seu_username \

–gh-token=yyyyyyyyyyyyyyyyyyyyyyyyyyy \

–repo-allowlist=”github.com/seu_username/tf-lab-vpc-atlantis-model” \

–gh-webhook-secret=”xxxxxxxxxxxxxxxxxxxxxxxxxxxx” \

–atlantis-url=”https://x.x.x.x” \

–gh-app-id=XXXXXXX \

–gh-app-key-file=atlantis.pem

Observação: Você irá precisar gerar um token pessoal e inserir no parâmetro gh-token, para que você possa gerar o token acesse o guia abaixo:fdd

https://docs.github.com/pt/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token

Pronto, agora o servidor Atlantis está pronto uso, para facilitar nosso exemplo, estamos utilizando apenas uma instancia conectada em uma subnet publica para um ambiente em produção. O correto seria utilizar um cluster de servidores para ganhar mais resiliência. Acessando repositório oficial do Atlantis é possível utilizar um modulo em Terraform para criar um cluster utilizando AWS Fargate.

Este módulo possui diversos recursos de segurança. Além disto, o modulo também cria um certificado SSL, adicionando mais uma camada de segurança na comunicação, para consultar mais detalhes, acesse o link abaixo:

https://www.runatlantis.io/docs/deployment.html#deployment-2

Parte 2

Criando uma VPC com Terragrunt e Atlantis

 No blog anterior falamos um pouco sobre o as ferramentas Terragrunt e Atlantis, sobre suas funcionalidades e vantagens, neste segundo artigo vamos demostrar seu funcionamento através da criação de uma VPC na nuvem AWS.

Primeiro vamos clonar o repositório modelo, neste repositório temos uma estrutura de pastas prontas para a criação de uma VPC em uma conta AWS, primeiro vamos apenas ajustar os parâmetros do arquivo terragrunt.hcl é nele que configuramos o bucket s3 que ficará armazenado o state file do Terraform, além disto vamos ajustar os parâmetros nos arquivos region.hcl e account.hcl.

Faça um clone do repositório que foi realizado o fork anteriormente:

“git clone git@github.com:SEU_USUARIO/tf-lab-vpc-atlantis-model.git”

Através do seu editor configure os parâmetros no arquivo terragrunt.hcl:

BUCKET_NAME = O Terragrunt salva o state file em um bucket s3, informe aqui um bucket existente na sua conta AWS, ou simplesmente dê um nome, caso o bucket não exista o Terragrunt irá criar o bucket para você.

REGION_NAME = Informe qual a região em que o bucket está ou que deseja que ele seja criado.

PROFILE_NAME = Informe o nome do profile que você está utilizando, estas informações são obtidas através das configurações do AWS CLI, para obter mais informações acesse o link abaixo:

https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

Agora configure os parâmetros no arquivo account.hcl:

PROFILE_NAME = Informe o nome do profile que foi criado previamente.

File=account.hcl

Em seguida configure o parâmetro da região onde a VPC será criada no arquivo region.hcl:

REGION_NAME = Informe qual a região onde a VPC será criada, ex. “us-east-1”

Por fim salve os arquivos.

Agora vamos realizar o commit e o push destas alterações direto para a main branch do nosso repositório.

Obs. Os parâmetros que alteramos agora serão ajustados apenas uma vez, uma vez definida esta estrutura de pastas não precisamos mais realizar alterações.

Vamos executar o comando “git status”, para verificar as informações sobre quais documentos foram alterados, em seguida vamos rodar o comando “git add.”, este comando inclui os arquivos contendo nossas alterações para que possamos realizar o commit e por fim o push para o remote branch.

Em seguida vamos executar o comando ‘git commit -m “ajustes de parametros do terragrunt”’, este comando realiza o commit e inclui uma breve mensagem com a descrição do que está sendo alterado nos arquivos.

Depois vamos realizar o push para o repositório remoto através do comando “git push”.

 

 Executando o Terragrunt plan Localmente

Acesse a pasta account/region/us-east-1/vpc/ e rode o comando “terragrunt plan”, o comando irá interpretar os parâmetros que inserimos e irá criar ou atualizar o bucket informado com o state file do Terraform, além de baixar todas as dependências do provider AWS.

Repare que o comando executou com sucesso e somos informados de que não há mudanças a serem feitas, e de fato não há, o código que fizemos o fork possui apenas as estruturas de pastas e parâmetros para que o Terragrunt funcione corretamente.

Para que a VPC seja criada vamos utilizar a integração entre o Terraform/Terragrunt, em um processo de automatização e integração com o GitHub através de um pull request.

Repare também que após executar o “terragrunt plan” o Terragrunt irá criar os arquivos backend.tf e o provider.tf, estes são os arquivos com as referências do state file e as informações sobre o profile (account) e região em que este código de Terraform será aplicado.

Criação da VPC através do Atlantis

Acesse o arquivo main.tf localizado na pasta “tf-lab-vpc-atlantis-model/account/region/us-east-1/vpc”

Reparem que o bloco de criação da VPC está comentado:

Vamos criar um novo branch, chamado vpc-add, utilizando o comando “git checkout -b vpc-add”

Agora vamos remover os comentários do arquivo main.tf, e salvar as alterações:

Agora vamos incluir nossas alterações no branch vpc-add, mas primeiro vamos verificar o status através do comado “git status”

Execute o comando “git add .” e depois “git status” podemos visualizar o status dos arquivos que adicionamos:

Pronto agora o arquivo main.tf foi adicionado, vamos realizar o commit e por fim realizar o push para o repositório remoto.

Rode o comando ‘git commit -m “vpc creation”’

Em seguida vamos realizar o push:

Obs. Como este branch não existe remotamente, vamos precisar rodar o comando “git push –set-upstream origin vpc-add” ao invés de git push, para que o Git crie remotamente o novo branch, nos próximos “pushes” podemos utilizar apenas o comando “git push”.

Agora estamos prontos para realizar o nosso primeiro Pull Request!

Criando o nosso primeiro Pull Request

Acesse seu repositório https://github.com/seu_usuario/tf-lab-vpc-atlantis-model

Repare que o Github já identificou que houve um push de um novo branch (vpc-add) e ele já sugere para que você abra um pull request:

Ao clicar em “Create pull request”, você será direcionado para uma nova página, podemos ver inclusive as alterações que este pull request pretente realizar na branch “main”.

Na tela a seguir o GitHub irá notificar o servidor do Atlantis sobre um novo pull request, ele enviará uma notificação utilizando o webhook configurado, o Atlantis por sua vez irá realizar o plan e depois inserir dentro da sessão de comentários do pull request o resultado do plan.

Abaixo a tela do servidor Atlantis com os logs da execução do plan:

Agora podemos ver o resultado do plan dentro do pull request no GitHub:

Podemos ver que este pull request irá criar uma nova VPC com o range “10.10.0.0/16”, ela será criada de acordo com os arquivos de “profile” e “region” que foram previamente configurados.

A vantagem de utilizar o Terragrunt juntamente com o Atlantis é que caso tivéssemos alterado uma outra pasta dentro deste repositório, imagine que além da pasta VPC, tivéssemos criado uma outra pasta na mesma região com o nome de RDS, e criamos no mesmo pull request um banco de dados, o Atlantis e o Terragrunt iriam detectar automaticamente as duas alterações, e poderíamos rodar o comando “atlantis apply” e aplicaria simultaneamente a VPC e também o RDS.

Caso queira criar primeiro a VPC, você poderia utilizar apenas o comando “atlantis apply -d account/region/us-east-1/vpc”, conforme imagem abaixo:

Vamos inserir no comentário do pull request a mensagem “atlantis apply”, é através deste comando que o Atlantis irá de fato realizar o deploy da VPC.

Aqui temos o processo de apply em andamento:

Na tela abaixo podemos ver que o resultado foi a criação da VPC com sucesso!

Vamos agora realizar o merge contendo as alterações do branch vpc-add na main branch:

Merge realizado com sucesso, podemos seguir com exclusão do branch vpc-add:

Aqui temos a lista de VPC antes das alterações:

Após executar o comando atlantis apply:

Conclusão

 A integração entre o GitHub e o Atlantis aumenta significativamente o trabalho em equipe, não é mais necessário que você tenha uma permissão elevada para criar sua infraestrutura na nuvem, o perfil elevado ficaria apenas dentro de um grupo de instancias (rodando o servidor Atlantis) em uma de suas contas na AWS, o time de Devops precisaria apenas de acesso de escrita no bucket s3 para a leitura do “state file”, e de acesso leitura também para realizar o plan dos recursos.

Para criar recursos em contas diferentes basta apenas realizar o uso de IAM cross account roles, permitindo que uma contra centralizada tenha permissão para criação da sua infraestrutura em outras contas, para mais informações acesse o link abaixo:

https://terragrunt.gruntwork.io/docs/features/work-with-multiple-aws-accounts/

Além disto, todas as alterações passariam por peer-review, onde todos do time poderiam avaliar quais alterações seriam realizadas, seria possível também registrar todas as alterações que foram realizadas, facilitando o entendimento em um possível troubleshooting ou roll-back.

A configuração que realizamos aqui possui apenas uma pequena parcela das funcionalidades que podemos integrar ao Atlantis, é possível incluir scripts para análise do código a procura de credenciais AWS expostas no código, podemos também incluir funcionalidades como a exibição de uma previa de custos que uma determinada funcionalidade custaria através do pré-hooks como infracost, script de validação de arquivos README com terraform_docs, ou aplicações de validação de código em busca de brechas de segurança como terrascan, terraform_tfsec ou checkov.

Gostou da solução? Nós podemos ajudar!

Conheça nossos conteúdos gratuitos, direcionados aos assuntos de sua preferência!

Enviar

Receba nosso conteúdo

Gostaria de receber de forma gratuita mais conteúdos sobre este ou outros assuntos? Preencha o formulário abaixo e receba nosso conteúdo gratuito!

Parabéns!

Você receberá nosso conteúdo em breve!

Atenção

Tivemos um problema com seu formulário, tente novamente.