Introdução a Terraform com Atlantis

O Atlantis é uma aplicação que, através de Pull Requests, permite fazer GitOps para Terraform.

Ele funciona ouvindo Webhooks de plataformas de Git como: Github, Gitlab ou do Bitbucket e retorna o output dos comandos terraform plan e terraform apply através de comentários.

De uma forma mais simples, o Atlantis atua como uma "ponte" entre o Terraform e a plataforma de Git, tornando os plans e applies muito mais colaborativos. Mas por quê? Infraestrutura como código é uma abordagem de automação de infraestrutura baseada em princípios de desenvolvimento de software, com reviews, testes, CI/CD.

Antes de iniciar

A partir do momento que o Atlantis é adotado, é ele quem define qual versão do Terraform está rodando e é ele quem conhece as secrets e keys dos provedores de cloud, serviços.

É sempre bom acompanhar as releases do projeto para ver se a versão mais recente do Terraform já possui suporte pelo Atlantis. E não necessariamente usar a versão mais recente do Atlantis exige atualizar seus projetos, por exemplo é possível usar a versão mais recente do Atlantis e para cada repositório/projeto usar uma versão diferente do Terraform.

Qualquer que seja a estrutura utilizada, o Atlantis vai rodar sem problemas. É possível utilizar:

  • Monorepo com vários projetos
  • Único repo com um único projeto
  • Monorepo com vários projetos e + módulos
  • Multirepo (basta ter um webhook para cada um deles)
  • É possível também utilizar Workspaces.

Configuração

Para subir o ambiente com Atlantis, vamos utilizar a AWS para hospeda-lo e o Terraform para criar toda a stack necessária para a utilização do Atlantis.

Utilizaremos o módulo oficial do Atlantis para Terraform, para ter mais informações sobre como o módulo funciona ou como personaliza-lo você pode acessar o link.

1- Módulo

Primeiramente precisamos ter configurado em nosso ambiente as chaves que tenham permissão suficientes na AWS para realização das seguintes ações:

  • Criação de Cluster ECS com Fargate
  • Acesso ao Route53 para criação de entradas DNS
  • EC2 para criação de target groups e ALB
  • ACM

Vamos lá, partiremos de um ponto onde entendemos que você irá utiliza-lo em sua infra existente no qual não será necessário criar infraestrutura de rede, como VPC, subnet, etc...

Em nosso arquivo main.tf será onde realizaremos a declaração do módulo Atlantis, teremos algumas definições

OBS: As subnets públicas e privadas precisam pertencer a mesma AZ para que a ALB seja criada e possua targets em sua configuração. Exemplo, uma subnet privada e uma publica na us-east-1a, outra privada e publica na us-east-1b e assim por diante.

# VPC 
vpc_id             = Id da VPC que utilizaremos
private_subnet_ids = Lista de IDS de subnets privadas
public_subnet_ids  = Lista de IDS de subnets publicas

# DNS
route53_zone_name = Domínio no R53 para criação das entradas

# Atlantis
atlantis_github_user       = Seu usuário do Github
atlantis_github_user_token = Um token para acesso ao Github
atlantis_repo_allowlist    = ["github.com/USER/*"]
atlantis_allowed_repo_names = Lista de nomes de repositórios

Para criar o token para o Github basta seguir a orientação do site oficial. Sabendo o que precisamos compor, segue abaixo a estrutura que deve ser aplicada:

module "atlantis" {
  source  = "terraform-aws-modules/atlantis/aws"
  version = "~> 3.0"

  name = "atlantis"

  # VPC
  vpc_id             = "vpc-faa24787"
  private_subnet_ids = ["subnet-448b4125","	subnet-2f3dfc0e"]
  public_subnet_ids  = ["subnet-448b4125","	subnet-2f3dfc0e"]
  ecs_service_assign_public_ip = true

  # DNS (without trailing dot)
  route53_zone_name = "thiago.click"

  # Atlantis
  atlantis_github_user       = "thiagoalexandria"
  atlantis_github_user_token = var.git_token
  atlantis_repo_allowlist    = ["github.com/thiagoalexandria/*"]
  atlantis_allowed_repo_names = ["terraform_atlantis"]

  allow_unauthenticated_access = true
  allow_github_webhooks        = true

  policies_arn = [
      "arn:aws:iam::aws:policy/AdministratorAccess",
      "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
  ]
}

Um ponto de atenção é que se atentem a configuração de policies_arn nela foi inseria uma politica de acesso total apenas para o LAB, é indicado que crie uma policy com restrição para que o ECS utilize com o Terraform, aplicando deny explicito para funções que você não quer que o terraform execute.

Webhook

Com a primeira parte pronta, vamos agora criar o bloco no Terraform para criar o nosso webhook de forma automática,dessa forma basta que configuremos da seguinte forma:

module "github_webhook"{
   source  = "terraform-aws-modules/atlantis/aws//modules/github-repository-webhook"
   version = "~> 3.0"

   github_owner = "thiagoalexandria"
   github_token = var.git_token

   atlantis_allowed_repo_names = module.atlantis.atlantis_allowed_repo_names

   webhook_url = module.atlantis.atlantis_url_events
   webhook_secret = module.atlantis.webhook_secret

}

Pronto, agora podemos rodar o nosso terraform plan e terraform apply para criar toda a stack necessária para o nosso ambiente Atlantis.

Utilização

Com tudo configurado, já estaremos prontos para utilizar o Atlantis em nossos repositórios configurados, o Atlantis vai intermediar dentro de pull/merge requests e nele nos retorna-rá o plan e poderemos realizar ou não o apply.

Quando abrirmos um pull request, teremos uma interação por parte do Atlantis da seguinte forma:

Dessa forma conseguimos expandir o output e ter uma visão completa do plan

Se estiver tudo de acordo, basta adicionar um comentário com o comando atlantis apply e todo o plan será aplicado conforme projeto:

Esse é o básico referente a utilização do Atlantis em pipelines com Terraform, o Atlantis é altamente personalizado no qual você é capaz de ajustar o workflow e adicionar outros steps para melhor se adaptar a sua utilização, como adicionar uma stage de terraform validade por exemplo.

Espero trazer outros assuntos sobre o Atlantis e como conseguimos personaliza-lo para diferentes casos de uso.

Comentários