Untitled 2020 08 24 0025 10

Agora vamos supor que você precise criar esse servidor com um conjunto de recursos muitas vezes. É aqui que os módulos são realmente úteis – você não quer repetir o mesmo código de configuração indefinidamente, quer?

Aqui está um exemplo que ilustra como nosso módulo “servidor” pode ser chamado.
Para chamar um módulo“significa usá-lo no arquivo de configuração.

Aqui, criamos 5 instâncias do “servidor” usando um único conjunto de configurações (no módulo):

module "server" {        count         = 5        source        = "./module_server"    some_variable = some_value}
Terraform suporta “contagem” para módulos a partir da versão 0.13

Organização do módulo: filho e raiz

Claro, você provavelmente desejaria criar mais de um módulo. Aqui estão alguns exemplos comuns:

  • uma rede como uma nuvem privada virtual (VPC)
  • hospedagem de conteúdo estático (ou seja, buckets)
  • um balanceador de carga e seus recursos relacionados
  • uma configuração de registro
  • ou qualquer outra coisa que você considere um componente lógico distinto da infraestrutura

Digamos que temos dois módulos diferentes: um módulo de “servidor” e um módulo de “rede”. O módulo chamado “rede” é onde definimos e configuramos nossa rede virtual e colocamos os servidores nela:

module "server" {    source        = "./module_server"    some_variable = some_value}module "network" {      source              = "./module_network"    some_other_variable = some_other_value}
Dois módulos filhos diferentes chamados no módulo raiz

Assim que tivermos alguns módulos personalizados, podemos nos referir a eles como módulos “filhos”. E o arquivo de configuração onde chamamos de módulos filhos está relacionado ao módulo raiz.

Untitled 2020 08 24 0025 11

Um módulo filho pode ser obtido de vários lugares:

  • caminhos locais
  • o Terraform Registry oficial – se você está familiarizado com outros registros como o Docker Registry, então você já entendeu a ideia
  • um repositório Git (personalizado ou GitHub / BitBucket)
  • um URL HTTP para um arquivo .zip com o módulo

Mas como você pode passar detalhes de recursos entre módulos?

Em nosso exemplo, os servidores devem ser criados em uma rede. Então, como podemos dizer ao módulo “servidor” para criar VMs em uma rede que foi criada em um módulo chamado “rede”?

Aqui é onde encapsulamento entra.

Encapsulamento de módulo

O encapsulamento no Terraform consiste em dois conceitos básicos: escopo do módulo e exposição explícita de recursos.

Escopo do Módulo

Todas as instâncias de recursos, nomes e, portanto, visibilidade de recursos são isolados no escopo de um módulo. Por exemplo, o módulo “A” não pode ver e não conhece os recursos do módulo “B” por padrão.

A visibilidade do recurso, às vezes chamada de isolamento de recurso, garante que os recursos terão nomes exclusivos dentro do namespace de um módulo. Por exemplo, com nossas 5 instâncias do módulo “servidor”:

module.server[0].resource_type.resource_namemodule.server[1].resource_type.resource_namemodule.server[2].resource_type.resource_name...
Endereços de recurso de módulo criados com o meta-argumento de contagem

Por outro lado, poderíamos criar duas instâncias do mesmo módulo com nomes diferentes:

module "server-alpha" {        source        = "./module_server"    some_variable = some_value}module "server-beta" {    source        = "./module_server"    some_variable = some_value}
Preste atenção ao argumento de origem – ele permanece o mesmo, é o mesmo módulo de origem

Nesse caso, a nomenclatura ou endereço dos recursos seria a seguinte:

module.server-alpha.resource_type.resource_namemodule.server-beta.resource_type.resource_name

Exposição explícita de recursos

Se você deseja acessar alguns detalhes para os recursos em outro módulo, você precisará configurar isso explicitamente.

Por padrão, nosso módulo “servidor” não conhece a rede que foi criada no módulo “rede”.

Untitled 2020 08 24 0025 13

Portanto, devemos declarar um output valor no módulo “rede” para exportar seu recurso, ou um atributo de um recurso, para outros módulos.

O módulo “servidor” deve declarar um variable para ser usado posteriormente como entrada:

Untitled 2020 09 01 2021 4
Os nomes output e variable pode ser diferente, mas sugiro usar os mesmos nomes para maior clareza.

Esta declaração explícita da saída é a maneira de expor algum recurso (ou informação sobre ele) fora – para o escopo do módulo ‘raiz’, portanto, para torná-lo disponível para outros módulos.

Em seguida, quando chamamos o módulo filho de “servidor” no módulo raiz, devemos atribuir a saída do módulo “rede” à variável do módulo “servidor”:

network_id = module.network.network_id
Preste atenção ao endereço de saída ‘network_id’ aqui – dizemos explicitamente onde ele reside

Aqui está a aparência do código final para chamar nossos módulos filhos:

module "server" {    count         = 5    source        = "./module_server"    some_variable = some_value    network_id    = module.network.network_id}module "network" {      source              = "./module_network"    some_other_variable = some_other_value}

Esta configuração de exemplo criaria 5 instâncias do mesmo servidor, com todos os recursos necessários, na rede que criamos como um módulo separado.

Empacotando

Agora você deve entender o que são módulos e o que eles fazem.

Se você está no início de sua jornada do Terraform, aqui estão algumas sugestões para as próximas etapas.

Eu encorajo você a fazer este breve tutorial da HashiCorp, os criadores do Terraform, sobre módulos: “Organizar configuração

Ademais, há um excelente guia de estudo abrangente que cobre tudo, desde conceitos básicos a avançados sobre o Terraform: “Guia de estudo – Certificação de Associado do Terraform

A estrutura de código modular torna sua configuração mais flexível e fácil de ser entendida por outras pessoas. Este último é especialmente útil para uma equipe.

Se você gostou do artigo, siga-me no Twitter (@vasylenko) onde ocasionalmente compartilho minhas descobertas e dicas sobre Terraform, AWS, Ansible e outras tecnologias relacionadas ao DevOps.