Terraform #parte6 – Utilizando módulos com outros módulos

Terraform #parte6 – Utilizando módulos com outros módulos

Em meio ao caos que o Corona Vírus tem causado em todo o globo, chegamos ao último post da nossa série de postagens sobre Terraform.

Caso tenha perdido os 5 primeiros posts desta série, recomendo ler para entaão retornar neste ponto:

#parte1   #parte2   #parte3   #parte4  #parte5

Hands-On

De cara já vamos iniciar o post com um preview de como nossa infraestrutura deverá rodar ao final deste post:

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 (detalhes foram explicados no post 5) e outro repositório chamado gcp-subnetworks.

Faça o clone dos repositórios.

Repositório gcp-networks.

$ 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:

https://gitlab.com/rd-public/4linux/blog-blog-tf-modules/gcp-networks
https://gitlab.com/rd-public/4linux/blog-blog-tf-modules/gcp-subnetworks

É isso aí galera!

Finalizamos aqui nossa série de posts sobre Terraform, agradeço por terem me acompanhado até aqui! Espero que tenham gostado e aproveitado para tirar algumas dúvidas iniciais de como utilizar Terraform e que isso possa servir para estimulá-los à usar essa poderosa ferramenta.

Qualquer dúvida ou sugestão, por favor, me contatem pelo Linkedin.

Sucesso na jornada que irão percorrer para construir sua infraestrutura como código.

Grande abraço!

Anterior Terraform #parte5 - Versionando a sua infraestrutura
Próxima Terraform é a nova oferta de cursos da 4Linux!

About author

Você pode gostar também

Desenvolvimento

Migrations para aplicações PHP com Phinx

Em tempos que se fala tanto de DevOps quero te mostrar como utilizar o Phinx para efetuar alterações no seu banco de dados à medida que a sua aplicação evolui,

DevOps

Minio — Tenha seu próprio S3 Storage

Minio é um storage de objetos, de alta performance e distribuído. A grande vantagem de usá-lo, reside em sua total compatibilidade com o Amazon S3. Neste artigo explico como subir

DevOps

Conhecendo os Anti Padrões DevOps (Anti-patterns)

Introdução Um dos maiores problemas que (acredito eu!) deve afeta grande parte das equipe de desenvolvedores de software, não é “como transformar uma ideia em um bom sistema”, mas sim