Introdução
Reutilizar código é uma das principais premissas das boas práticas de programação. Código duplicado ou triplicado significa trabalho duplicado ou triplicado respectivamente. Sair caçando as modificações em várias linhas ou até em vários arquivos além de não ser produtivo é uma prática certa para ocasionar erros por ter esquecido alguma coisa ou por ter alterado algo onde não devia. No mundo de DevOps não é diferente, scripts precisam ser bem estruturados para que a manutenção seja rápida e eficaz.
O Terraform
Terraform é uma ferramenta para construir, modificar e versionar infraestrutura de modo seguro e eficaz. Com o Terraform nós podemos administrar os mais comuns e populares serviços de nuvens como AWS, Azure, Google Cloud, entre outros.
O Terraform utiliza scrips em arquivos .tf para gerar um plano de execução descrevendo o que fará para atingir o estado desejado e, em seguida, executa-o para construir a infraestrutura descrita. Conforme modificamos os arquivos o Terraform pode determinar o que mudou e criar planos de execução para criar, modificar ou excluir serviços que serão aplicados.
A infraestrutura que o Terraform pode gerenciar inclui componentes de baixo nível, como instâncias de computação, armazenamento e rede, além de componentes de alto nível, como entradas DNS, recursos SaaS, etc.
Módulos do Terraform
Uma das forma de reaproveitarmos código com o Terraform é utilizando o conceito de módulos.
Um módulo é um contêiner para ser utilizado por pelos recursos do Terraform. Um mesmo recurso pode utilizar vários módulos, diminuindo muito a quantidade de linhas de scripts do projeto.
Para um bom reaproveitamento de código, uma estrutura do Terraform deve possuir pelo menos um módulo, conhecido como módulo raiz, que consiste nos recursos definidos nos arquivos .tf no diretório principal de trabalho. Um módulo pode chamar outros módulos, o que permite incluir os recursos do módulo filho para uma configuração incremental e concisa.
Os módulos também podem ser chamados várias vezes na mesma configuração ou em configurações separadas, permitindo que as configurações de recursos sejam empacotadas e reutilizadas várias vezes.
Estrutura de diretórios
Vamos iniciar nosso exemplo configurando a estrutura de diretórios e arquivos que vamos utilizar.
- Terraform: diretório raiz da nossa aplicação;
- Envs: onde vão ficar os diretórios de cada ambiente, neste caso, vamos usar como exemplo os três padrões (desenvolvimento, homologação e produção);
- Services: aqui vamos colocar os diretórios de cada serviço/projeto que será criado, neste caso, vamos criar um S3 Bucket e um redirecionamento usando o Route53 para um projeto (my-website).
Em cada um destes diretórios temos os arquivos main.tf e vars.tf, padrões do Terraform.
Vamos agora analisar os arquivos main.tf dentro do diretório development em ./terraform/envs/development/
provider "aws" {
region = "us-east-1"
}
module "my-website" {
source = "../../services/my-website"
bucket_name = "${var.environment}.dominio.com.br"
url_redirect = "${var.environment}.dominio.com.br."
zone_id = "${var.route53_zone_id}"
}
./terraform/envs/development/main.tf no GitHub
Como mostrado acima, temos o provider especificando que estamos trabalhando com a infraestrutura da AWS e um módulo. Este módulo consiste em um container de informações necessárias para subir o nosso projeto my-website.
A propriedade source dentro do módulo my-website indica onde estas informações serão executadas, neste caso, estas informações serão executadas no ./terraform/services/my-website/main.tf.
resource "aws_s3_bucket" "s3_website" {
bucket = "${var.bucket_name}"
acl = "private"
region = "us-east-1"
website {
index_document = "index.html"
}
}
resource "aws_route53_record" "meu_redirecionamento" {
zone_id = "${var.zone_id}"
name = "${var.url_redirect}"
type = "A"
alias {
name = "${aws_s3_bucket.s3_website.website_domain}"
zone_id = "${aws_s3_bucket.s3_website.hosted_zone_id}"
evaluate_target_health = true
}
}
./terraform/services/my-website/main.tf
Notamos aqui que definimos as variáveis em que vamos utilizar no arquivo vars.tf dentro do diretório development ./terraform/envs/development/vars.tf. Dentro do arquivo vars.tf em ./terraform/services/my-website/vars.tf apenas declaramos as variáveis para serem utilizadas pelo resouce dentro do arquivo main.tf no mesmo diretório.
Com isto podemos utilizar os módulos para reaproveitar os resouces. Cada um dos ambientes (desenvolvimento, homologação e produção) utilizam o mesmo resource para ser executado pelo Terraform. Mas cada um dos ambientes precisa ser executado separadamente.
Depois disto, é só entrar no diretório ./terraform/envs/development e executar no terminal o comando para o Terraform criar os módulos com base nos arquivos:
terraform init

Executar o comando para o plano de execução:
terraform plan

Aqui vemos que ele criará 2 recursos dentro do nosso ambiente de desenvolvimento, o S3 e o Route53 para redirecionamento.
E na sequencia, se estiver tudo certo, executar:
terraform apply
Após validar as implementações em desenvolvimento é só fazer o mesmo nos demais ambientes. Com isto nós temos o mesmo resource para todos os ambientes coordenados pelos módulos.
Conclusão
Claro que este exemplo é bem simples, suficiente apenas para iniciar a modularização e o reaproveitamento do código com o Terraform. Ainda é possível evoluir bastante para reaproveitar ainda mais os scripts, mas com isto já conseguimos ter uma ideia de como utilizar os módulos para reaproveitar os resources em mais de um ambiente.
Os fontes podem ser encontrados no meu GitHub.
Referências
- Terraform Doc.: https://www.terraform.io/docs/index.html
A estrutura de diretórios ficou show, Danilo.
E no pipeline você pode usar a mesma branch, já que os ambientes estão separados em diretórios diferentes.
Os módulos do terraform facilita muito no dia a dia.
Parabéns!!
CurtirCurtido por 1 pessoa