Photo by Sigmund on Unsplash

Módulos do Terraform — Porque você precisa aprender para ontem!

Os módulos são uma maneira de encapsular e reutilizar código Terraform (HCL) para criar recursos específicos. Vou destacar alguns benefícios específicos do uso de módulos, com exemplo real de mercado.

DevOps from Zero!💻
8 min readFeb 2, 2024

--

Pois é… quanto tempo que eu não escrevo por aqui haha! Confesso que estava com vontade de escrever, faz um tempão😆, mas nos últimos meses, com festas da virada de ano, assuntos pessoais, fiquei escasso de tempo livre. Mas dessa vez, é sério, bora aprender sobre módulos para que você possa começar 2024 com TUDO, por dentro das boas práticas do Terraform🏗 e sabendo módulos definitivamente. Os módulos Terraform são úteis para reaproveitamento de código (HCL), organização e simplicidade dentro de um contexto de Infraestrutura como Código (IaC). Basicamente, você

Eu vou usar um exemplo bem simples para esclarecer o uso de módulos, na própria AWS mesmo, afinal é a plataforma que eu tenho adotado e utilizado para labs de DevOps. Não vou passar por conceitos mais simples do Terraform… já postei muito conteúdo sobre Terraform, confere lá se você ainda precisa de mais entendimento da ferramenta, e NÃO DEIXE, de praticar hein?? É o máximo aprender fazendo com a mão na massa!

Tópicos

  • O que são módulos
  • Estrutura de diretórios
  • Como usar módulos
  • Caso de uso com AWS
  • Vantagens dos módulos

O que são módulos Terraform?

Os módulos são a principal forma de empacotar e reutilizar configurações de recursos com o Terraform, para garantir consistência e qualidade. É muito utilizado em ambientes produtivos, em grandes projetos, onde eles se tornam uma prática valiosa para organizar e gerenciar a configuração de infraestrutura de maneira eficiente.

Módulos Root

Toda estrutura do Terraform (HCL) possui um root module, cujo o mesmo é definido no principal diretório da configuração, ou seja, no diretório raíz do projeto, nomeado como .tf

Módulos Filho

Dado que toda configuração do Terraform possui um módulo raíz, e esses módulos podem invocar outros módulos para inclusão de novas configurações, e assim podemos classificar que, um módulo que foi chamado por outro módulo é justamente um módulo filho.

Estrutura de diretórios

O diretório principal (root-directory) só precisa conter os arquivos necessários para o seu projeto principal, veja abaixo como pode ser criado:

$ tree root-directory/
root-directory/
├── main.tf
└── module-example
├── main.tf
├── outputs.tf
└── variables.tf

2 directories, 4 files
  • module-example/: Este é o diretório do módulo que contém todos os arquivos específicos para o módulo da sua configuração.
  • main.tf: Arquivo principal do módulo, onde estão as definições dos recursos específicos do módulo.
  • variables.tf: Arquivo que declara as variáveis específicas do módulo.
  • outputs.tf: Arquivo que declara as saídas (stdout) específicas do módulo.
  • main.tf: É o arquivo principal que referencia e usa o módulo. Aqui você configura as instâncias específicas que deseja criar usando o módulo.

Como usar Módulos Terraform

  • Comece criando o diretório onde você armazenará seus módulos Terraform. Por exemplo, você pode criar um diretório chamado module-example.
  • Nesse diretório module-example, crie os arquivos necessário para uso, como main.tf , variables.tf e outputs.tf . Vamos ter essa visão da estrutura:
$ tree root-directory/
root-directory/
├── main.tf
└── module-example
├── main.tf
├── outputs.tf
└── variables.tf

2 directories, 4 files
  • main.tf: Este arquivo contém a definição dos recursos e configurações do módulo.
  • variables.tf: Este arquivo define as variáveis que o módulo espera.
  • outputs.tf: Este arquivo define as saídas que seu módulo retorna.
  • No seu arquivo de configuração principal do Terraform (por exemplo, main.tf), use a sintaxe module para instanciar e configurar os módulos criados anteriormente:
  5 module "example_ec2" {
6 source = "./module-example"
7 region = "us-east-1"
8 ami = "ami-0277155c3f0ab2930"
9 instance_type = "t3.micro"
10 }

Caso de uso com AWS EC2

Vamos exemplificar de forma mais simples possível o uso de módulos na plataforma da AWS usando o recurso de EC2 (instâncias de computação virtuais). Vamos executar os comandos do Terraform manualmente para aplicar as configurações.

  • terraform init: Inicialize o ambiente Terraform no diretório onde está o arquivo principal (main.tf).
$ terraform init

Initializing the backend...
Initializing modules...
- example_ec2 in module-example

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v5.35.0...
- Installed hashicorp/aws v5.35.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
  • terraform plan: Execute o comando de plan para visualizar o planejamento de estado da infraestrutura.
$ terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# module.example_ec2.aws_instance.example_instance will be created
+ resource "aws_instance" "example_instance" {
+ ami = "ami-0277155c3f0ab2930"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ host_resource_group_arn = (known after apply)
+ iam_instance_profile = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_lifecycle = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t2.micro"
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = (known after apply)
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ placement_partition_number = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ spot_instance_request_id = (known after apply)
+ subnet_id = "subnet-0123456789abcdef0"
+ tags_all = (known after apply)
+ tenancy = (known after apply)
+ user_data = (known after apply)
+ user_data_base64 = (known after apply)
+ user_data_replace_on_change = false
+ vpc_security_group_ids = (known after apply)
}

Plan: 1 to add, 0 to change, 0 to destroy.
  • terraform apply: Aplique as configurações para criar a instância virtual.
$ terraform apply --auto-approve

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# module.example_ec2.aws_instance.example_instance will be created
+ resource "aws_instance" "example_instance" {
+ ami = "ami-0277155c3f0ab2930"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ host_resource_group_arn = (known after apply)
+ iam_instance_profile = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_lifecycle = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t2.micro"
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = (known after apply)
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ placement_partition_number = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ spot_instance_request_id = (known after apply)
+ subnet_id = (known after apply)
+ tags_all = (known after apply)
+ tenancy = (known after apply)
+ user_data = (known after apply)
+ user_data_base64 = (known after apply)
+ user_data_replace_on_change = false
+ vpc_security_group_ids = (known after apply)
}

Plan: 1 to add, 0 to change, 0 to destroy.
module.example_ec2.aws_instance.example_instance: Creating...
module.example_ec2.aws_instance.example_instance: Still creating... [10s elapsed]
module.example_ec2.aws_instance.example_instance: Still creating... [20s elapsed]
module.example_ec2.aws_instance.example_instance: Still creating... [30s elapsed]
module.example_ec2.aws_instance.example_instance: Creation complete after 35s [id=i-0c74bf93b294c2faf]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Lembre-se de substituir os valores de amie instance_typepelos valores adequados de acordo com seu projeto. Este é apenas um exemplo básico de uso de módulos com AWS EC2.

Vantagens dos Módulos Terraform

É evidente o tanto que fica simples e mais organizada a nossa estrutura de código quando estamos lidando com módulos Terraform, temos agora um arquivo main.tf que é responsável por todo a estrutura, é neste arquivo que efetuamos as alterações dos valores que tínhamos especificado nas configurações da instância AWS EC2. Por mais simples que pareça esse exemplo, o uso de módulos pode trazer benefícios significativos em termos de organização, reutilização e manutenção do código.

  • Reutilização de Código: Com o módulo ( module-example) você pode encapsular a lógica para criar a instância EC2 em um único pacote que pode ser reutilizado em diferentes partes do seu código. Isso promove a consistência e evita a duplicação de código Terraform.
  • Abstração de Recursos: O módulo abstrai os detalhes específicos da criação da instância EC2, como a definição de recursos e configurações. Isso torna mais fácil para outros profissionais da equipe entenderem e usarem o módulo, sem precisar entender todos os detalhes técnicos, ou seja, as configurações que estão nos arquivos main.tf e variables.tf
  • Facilidade de Manutenção: Ao isolar a criação da instância EC2 em um módulo separado, qualquer alteração ou atualização nas configurações da instância pode ser feita no módulo, e essas alterações serão refletidas em todos os lugares onde o módulo é usado.
  • Promoção da Modularidade: O uso de módulos promove a modularidade do seu código Terraform, dividindo a infraestrutura em componentes menores e mais gerenciáveis. Isso facilita a construção e a manutenção de infraestruturas complexas, ou seja, aquea boa prática de mercado.
  • Compartilhamento e Colaboração: Os módulos podem ser compartilhados e reutilizados em toda a organização, promovendo a colaboração entre equipes e a padronização das práticas de infraestrutura como código.

Era essa a ideia do post de hoje, compartilhar um pouco sobre esse tópico que sabemos, o quão é relevante dentro do ciclo de DevOps, que envolve Infraestrutura como Código. Em ambientes produtivos, não se cria recursos soltos no código, isso não é boa prática de mercado, por isso é necessário esse conhecimento aprofundado de módulos, para obter tais vantagens mostradas acima e você também, ter mais visibilidade do ambiente e poder integrar sua esteira com CI/CD workflows. TMJ!

--

--

DevOps from Zero!💻

SRE/DevOps Engineer| Lifelong learner | Medium Creator | AWS/Azure certified☁️ | Hashicorp Ambassador | Containers | Tech | Community | Coffee