Terraform | Utilizando módulos com outros módulos

Terraform | Utilizando módulos com outros módulos

Utilizando módulos com outros módulos

Primeira coisa que devemos fazer é destruir toda sua infraestrutura (caso ainda não tenha feito) com o comando:

$ terraform destroy -auto-approve

Crie um novo repositório chamado gcp-networks no GitLab e outro repositório chamado gcp-subnetworks.

Faça o clone dos repositórios.

$ git clone git@gitlab.com:rd-public/blog-blog-tf-modules/4linux/gcp-networks.git

Você receberá mensagem para cada um dos repositórios que está clonando um repositório em branco.

Entre no diretório do gcp-networks e vamos iniciar a criação deste módulo com algumas coisas novas, como o arquivo outputs.tf que será explicado em breve.

Crie o arquivo main.tf:

resource "google_compute_network" "this" {
  name                    = var.name
  description             = var.description
  auto_create_subnetworks = var.auto_create_subnetworks
}

Arquivo variables.tf

variable "name" {
  description = "Nome para sua rede"
  type        = string
}

variable "description"  {
  description = "Descrição para sua rede"
  type        = string
}

variable "auto_create_subnetworks" {
  description = "Redes devem criar automaticamente subredes?"
  type        = bool
  default     = true
}

Arquivo outputs.tf

output "gateway_ipv4" {
  value = google_compute_network.this.gateway_ipv4
}

output "self_link" {
  value = google_compute_network.this.self_link
}

O arquivo outputs é responsável por basicamente imprimir no seu terminal a saída do recurso criado, porém ele também é o ponto de ligação quando você precisa fazer o vínculo de um módulo com outro módulo, que é o nosso caso pra ligar instâncias com as redes.

Antes de enviarmos o código para o repositório devemos fazer um teste local para verificar se ele está funcionando corretamente e para isso precisamos primeiro fazer uma outra alteração em nosso módulo que gerencia as instâncias.

Vá até seu módulo que gerencia instâncias e abra o arquivo main.tf alterando para:

resource "google_compute_instance" "this" {
  count        = var.amount

  name         = format("%s-%d", var.name, count.index)
  machine_type = var.machine_type
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = var.image
    }
  }

  network_interface {
    network = var.network
  }
}

Altere o arquivo variables.tf adicionando no fim do arquivo mais um bloco para a variável de rede:

variable "network" {
  description = "Qual rede deseja utilizar"
  type        = string
  default     = "default"
}

Abra o arquivo instances.tf (que consome os módulos), adicione a rede e faça o apontamento do módulo de instâncias também para local:

# Instâncias Linux
module "network-linux" {
  source = "./tf-modules/gcp-networks"

  name        = "network-linux"
  description = "Rede para o grupo de máquinas linux"
}

module "instances" {
  source = "./tf-modules/gcp-instances"

  amount  = 2
  name    = "linux-vm-1"
  network = module.network-linux.self_link
}

# Instâncias Web
module "network-web" {
  source = "./tf-modules/gcp-networks"

  name        = "network-web"
  description = "Rede para o grupo de máquinas web"
}

module "group-web" {
  source = "./tf-modules/gcp-instances"

  amount  = 3
  name    = "linux-web"
  image   = "centos-cloud/centos-8"
  network = module.network-web.self_link
}

# Instâncias Gitlab
module "network-gitlab" {
  source = "./tf-modules/gcp-networks"

  name        = "network-gitlab"
  description = "Rede para o grupo de máquinas gitlab"
}

module "group-gitlab" {
  source = "./tf-modules/gcp-instances"

  amount  = 2
  name    = "linux-gitlab"
  image   = "centos-cloud/centos-7"
  network = module.network-gitlab.self_link
}

Faça a inicialização dos módulos:

$ terraform init

Com a seguinte saída:

Initializing modules...
- group-gitlab in ../../tf-modules/gcp-instances
- group-web in ../../tf-modules/gcp-instances
- instances in ../../tf-modules/gcp-instances
- network-gitlab in ../../tf-modules/gcp-networks
- network-linux in ../../tf-modules/gcp-networks
- network-web in ../../tf-modules/gcp-networks

Initializing the backend...
......
......
......
......

Faça o plano de execução e verifique a criação das redes:

......
......
......
......
  # module.network-gitlab.google_compute_network.this will be created
  + resource "google_compute_network" "this" {
      + auto_create_subnetworks         = false
      + delete_default_routes_on_create = false
      + description                     = "Rede para o grupo de máquinas gitlab"
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + ipv4_range                      = (known after apply)
      + name                            = "network-gitlab"
      + project                         = (known after apply)
      + routing_mode                    = (known after apply)
      + self_link                       = (known after apply)
    }

  # module.network-linux.google_compute_network.this will be created
  + resource "google_compute_network" "this" {
      + auto_create_subnetworks         = false
      + delete_default_routes_on_create = false
      + description                     = "Rede para o grupo de máquinas linux"
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + ipv4_range                      = (known after apply)
      + name                            = "network-linux"
      + project                         = (known after apply)
      + routing_mode                    = (known after apply)
      + self_link                       = (known after apply)
    }

  # module.network-web.google_compute_network.this will be created
  + resource "google_compute_network" "this" {
      + auto_create_subnetworks         = false
      + delete_default_routes_on_create = false
      + description                     = "Rede para o grupo de máquinas web"
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + ipv4_range                      = (known after apply)
      + name                            = "network-web"
      + project                         = (known after apply)
      + routing_mode                    = (known after apply)
      + self_link                       = (known after apply)
    }

Plan: 10 to add, 0 to change, 0 to destroy.

Crie esta infraestrutura:

$ terraform apply -auto-approve

Com a saída:

......
......
......
......
......
module.group-web.google_compute_instance.this[1]: Still creating... [10s elapsed]
module.group-web.google_compute_instance.this[0]: Still creating... [10s elapsed]
module.group-web.google_compute_instance.this[2]: Creation complete after 10s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-web-2]
module.group-web.google_compute_instance.this[0]: Creation complete after 10s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-web-0]
module.group-gitlab.google_compute_instance.this[0]: Still creating... [10s elapsed]
module.group-gitlab.google_compute_instance.this[1]: Still creating... [10s elapsed]
module.group-web.google_compute_instance.this[1]: Creation complete after 10s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-web-1]
module.group-gitlab.google_compute_instance.this[1]: Creation complete after 11s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-gitlab-1]
module.group-gitlab.google_compute_instance.this[0]: Creation complete after 11s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-gitlab-0]

Apply complete! Resources: 10 added, 0 changed, 3 destroyed.

Okay, tudo funcionando, hora de versionarmos nossos módulos. Primeiro vamos versionar o módulo de instâncias:

Adicione os dois arquivos que foram modificados.

$ git add main.tf variables.tf

Faça o commit das alterações.

$ git commit -m 'Adição de rede para o modulo'

Envie para o repositório:

$ git push origin master

Crie uma nova tag:

$ git tag -a v1.1 -m 'Adição de rede'

Envie a tag para o repositório:

$ git push --tags

Vamos para o módulo de rede e fazer o versionamento.

Adicione os 3 arquivos.

$ git add main.tf variables.tf outputs.tf

Faça o commit:

$ git commit -m 'Envio de módulo'

Envie para o repositório:

$ git push origin master

Crie a primeira tag:

$ git tag -a v1.0 -m 'Versão 1.0 do módulo'

Envie a tag para o repositório:

$ git push --tags

Perfeito! todos os módulos versionados, agora é hora de novamente alterar o arquivo instances.tf para suportar o novo código.

Arquivo instances.tf:


# Instâncias Linux
module "network-linux" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-linux"
  description = "Rede para o grupo de máquinas linux"
}

module "instances" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1"

  amount  = 2
  name    = "linux-vm-1"
  network = module.network-linux.self_link
}

# Instâncias Web
module "network-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-web"
  description = "Rede para o grupo de máquinas web"
}

module "group-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1"

  amount  = 3
  name    = "linux-web"
  image   = "centos-cloud/centos-8"
  network = module.network-web.self_link
}

# Instâncias Gitlab
module "network-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-gitlab"
  description = "Rede para o grupo de máquinas gitlab"
}

module "group-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1"

  amount  = 2
  name    = "linux-gitlab"
  image   = "centos-cloud/centos-7"
  network = module.network-gitlab.self_link
}

Faça a inicialização do Terraform para buscar o novo código:

$ terraform init

Com o resultado:

Initializing modules...
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1 for group-gitlab...
- group-gitlab in .terraform/modules/group-gitlab
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1 for group-web...
- group-web in .terraform/modules/group-web
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1 for instances...
- instances in .terraform/modules/instances
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0 for network-gitlab...
- network-gitlab in .terraform/modules/network-gitlab
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0 for network-linux...
- network-linux in .terraform/modules/network-linux
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0 for network-web...
- network-web in .terraform/modules/network-web
......
......
......
......
......

Verifique no seu painel do GCP todas instâncias criadas assim como todas redes que foram criadas.

Estas redes estão com o atributo para criar automaticamente subredes. Estas subredes são criadas automaticamente pelo nosso atributo auto_create_subnetworks = var.auto_create_subnetworks onde nossa variável está setada como true.

Nós não queremos que seja gerada automaticamente mas sim gerenciada por nós e pra isso precisamos alterar este atributo na nossa chamada e passar ela para false, mas este atributo podemos agora setar na chamada de nosso módulo e faremos isso em breve.

Por fim, nosso último módulo que irá gerenciar subredes.

Crie um diretório chamado gcp-subnetworks e dentro deste diretório:

Crie um arquivo chamado main.tf com o seguinte conteúdo:

resource "google_compute_subnetwork" "this" {
  name          = var.name
  ip_cidr_range = var.ip_cidr_range
  region        = var.region
  network       = var.network
}

Arquivo variables.tf

variable "name" {
  type        = string
  description = "Nome para a subrede"
}

variable "ip_cidr_range" {
  type        = string
  description = "IP CIDR"
}

variable "region" {
  type        = string
  description = "Nome da região que será utilizada"
  default     = "us-central1"
}

variable "network" {
  type        = string
  description = "Nome da rede que será conectada com esta subrede"
}

Arquivo outputs.tf

output "creation_timestamp" {
  value = google_compute_subnetwork.this.creation_timestamp
}

output "gateway_address" {
  value = google_compute_subnetwork.this.gateway_address
}

output "self_link" {
  value = google_compute_subnetwork.this.self_link
}

Também devemos criar uma nova versão do nosso módulo que gerencia as instâncias para que passe a suportar as subredes:

Altere o arquivo main.tf e altere o bloco de network de:

network_interface {
  network = var.network
}

para:

network_interface {
  network    = var.network
  subnetwork = var.subnetwork
}

Altere também o arquivo variables.tf com um novo bloco no fim do arquivo:

variable "subnetwork" {
  description = "Qual subrede deseja utilizar"
  type        = string
}

Altere o arquivo do instances.tf mais uma vez para fazer o teste local com o novo módulo.

# Instâncias Linux
module "network-linux" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-linux"
  description = "Rede para o grupo de máquinas linux"
}

module "subnetwork-linux" {
  source = "./tf-modules/gcp-subnetworks"

  name          = "subnetwork-linux"
  ip_cidr_range = "10.10.1.0/24"
  network       = module.network-linux.self_link
}

module "instances" {
  source = "./tf-modules/gcp-instances"

  amount     = 2
  name       = "linux-vm-1"
  network    = module.network-linux.self_link
  subnetwork = module.subnetwork-linux.self_link
}

# Instâncias Web
module "network-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-web"
  description = "Rede para o grupo de máquinas web"
}

module "subnetwork-web" {
  source = "./tf-modules/gcp-subnetworks"

  name          = "subnetwork-web"
  ip_cidr_range = "10.10.2.0/24"
  network       = module.network-web.self_link
}

module "group-web" {
  source = "./tf-modules/gcp-instances"

  amount     = 3
  name       = "linux-web"
  image      = "centos-cloud/centos-8"
  network    = module.network-web.self_link
  subnetwork = module.subnetwork-web.self_link
}

# Instâncias Gitlab
module "network-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-gitlab"
  description = "Rede para o grupo de máquinas gitlab"
}

module "subnetwork-gitlab" {
  source = "./tf-modules/gcp-subnetworks"

  name          = "subnetwork-gitlab"
  ip_cidr_range = "10.10.3.0/24"
  network       = module.network-gitlab.self_link
}

module "group-gitlab" {
  source = "./tf-modules/gcp-instances"

  amount     = 2
  name       = "linux-gitlab"
  image      = "centos-cloud/centos-7"
  network    = module.network-gitlab.self_link
  subnetwork = module.subnetwork-gitlab.self_link
}

Funcionando? então devemos enviar nosso módulo de instâncias com suas devidas modificações para serem versionadas.

$ git add .

Faça o commit:

$ git commit -m 'Suporte a subredes'

Envie para o repositório:

$ git push origin master

Crie a tag:

$ git tag -a v1.2 -m 'Suporte a subredes'

Envie a tag para o repositório:

$ git push --tags

Agora no novo novo módulo gcp-subnetworks faça o processo de envio de código e crie a tag (processo já é conhecido, certo?)

Finalmente altere o arquivo instances.tf para a versão final.

# Instâncias Linux
module "network-linux" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-linux"
  description = "Rede para o grupo de máquinas linux"
}

module "subnetwork-linux" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-subnetworks.git?ref=v1.0"

  name          = "subnetwork-linux"
  ip_cidr_range = "10.10.1.0/24"
  network       = module.network-linux.self_link
}

module "instances" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.2"

  amount     = 2
  name       = "linux-vm-1"
  network    = module.network-linux.self_link
  subnetwork = module.subnetwork-linux.self_link
}

# Instâncias Web
module "network-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-web"
  description = "Rede para o grupo de máquinas web"
}

module "subnetwork-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-subnetworks.git?ref=v1.0"

  name          = "subnetwork-web"
  ip_cidr_range = "10.10.2.0/24"
  network       = module.network-web.self_link
}

module "group-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.2"

  amount     = 3
  name       = "linux-web"
  image      = "centos-cloud/centos-8"
  network    = module.network-web.self_link
  subnetwork = module.subnetwork-web.self_link
}

# Instâncias Gitlab
module "network-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-gitlab"
  description = "Rede para o grupo de máquinas gitlab"
}

module "subnetwork-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-subnetworks.git?ref=v1.0"

  name          = "subnetwork-gitlab"
  ip_cidr_range = "10.10.3.0/24"
  network       = module.network-gitlab.self_link
}

module "group-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.2"

  amount     = 2
  name       = "linux-gitlab"
  image      = "centos-cloud/centos-7"
  network    = module.network-gitlab.self_link
  subnetwork = module.subnetwork-gitlab.self_link
}

Estes módulos estão disponíveis em: