Criando módulos
Toda vez que você roda o comando terraform plan ou terraform apply, este diretório é basicamente um módulo. Módulos, podem chamar outros módulos e podem se conectar juntos quando necessário.
Módulos devem ser genéricos o suficiente para suportar parâmetros e uma das melhoras formas de aprender como utilizar eles é com módulos públicos, mas que não serão abordados aqui neste post.
Módulos públicos podem ser encontrados neste link e lá podem ser encontrados diversos módulos para diferentes Providers, como Google Cloud, AWS, Digital Ocean entre outros, portanto fica a dica: "antes de sair construindo módulos para o seu problema, procure primeiro no repositório público, pois certamente alguém deve ter passado pelo mesmo problema que você”.
Como estamos aprendendo alguns aspectos super básicos de Terraform, precisamos saber como construir um módulo e começarmos a evitar o control + c + v
em nossos códigos.
Primeiramente iremos criar um módulo para lidar com instâncias na plataforma do Google, porém, caso ainda tenha alguma infraestrutura rodando dos capítulos anteriores, faça a deleção primeiro.
Destrua toda sua infraestrutura com o comando:
$ terraform destroy -auto-approve
Agora crie um diretório chamado gcp-instances e dentro deste diretório iremos criar nosso primeiro módulo:
Crie um arquivo chamado de main.tf
com o seguinte conteúdo:
resource "google_compute_instance" "this" {
name = var.name
machine_type = var.machine_type
zone = var.zone
boot_disk {
initialize_params {
image = var.image
}
}
network_interface {
network = "default"
}
}
Este arquivo basicamente é o mesmo conteúdo que estávamos utilizando nos capítulos anteriores, porém estamos acrescentando variáveis (var.name
, por exemplo) que serão passadas (caso exista um valor default, este valor não é obrigatório) quando o usuário consumir seu módulo.
Crie um arquivo chamado de variables.tf
com o seguinte conteúdo:
variable "name" {
description = "Nome da instância"
type = string
}
variable "machine_type" {
description = "Tamanho da instância"
type = string
default = "f1-micro"
}
variable "zone" {
description = "Em qual zona sua instância irá ficar"
type = string
default = "us-central1-a"
}
variable "image" {
description = "Qual Sistema deseja utilizar"
type = string
default = "debian-cloud/debian-9"
}
O código acima é um bloco de declaração para variáveis e é basicamente composto de 3 atributos.
Description
: Descrição para ajudar o usuário que for consumir seu módulo do que este argumento faz.
Type
: o tipo da variável, pode ser bool
, string
, list
, map
, number
e etc.
Default
: se deseja que este atributo tenha já um valor já preenchido por padrão, assim não será necessário passar qualquer valor quando o módulo for utilizado.
Acredite ou não, um módulo pode ser super simples como nosso código acima, até módulos consumindo outros módulos, portanto a necessidade é de cada projeto.
Por fim, altere seu código do arquivo instance.tf
para o seguinte conteúdo:
module "instances" {
source = "./gcp-instances"
name = "linux-vm-1"
}
Aqui neste código vimos que o único atributo que devemos preencher com variável é a variável chamada "name”, caso deseja alterar o tamanho de sua máquina, seria possível sobrescrever o valor padrão, por exemplo:
module "instances" {
source = "./gcp-instances" # Utilizando ./ informamos que o módulo está em nosso diretório gcp-instances criado anteriormente
name = "linux-vm-1"
machine_type = "g1-small"
}
Toda vez que um módulo for adicionado ou alterado, deve-se rodar o comando terraform init
para que o Terraform faça o download deste módulo e possa ser utilizado.
Rode o comando de inicialização:
$ terraform init
Preste atenção no resultado:
Initializing modules...
- instances in gcp-instances
Initializing the backend...
......
......
......
......
Repare que estamos consumindo um módulo que acabamos de criar em um diretório local. Este módulo está em nossa máquina, ou seja, somente nós conseguimos consumir ele, e por este motivo que iremos ter mais um post falando sobre versionamento.
Faça o plano de execução:
$ terraform plan
Com o seguinte resultado:
......
......
......
......
+ create
Terraform will perform the following actions:
# module.instances.google_compute_instance.this will be created
+ resource "google_compute_instance" "this" {
+ can_ip_forward = false
+ cpu_platform = (known after apply)
+ deletion_protection = false
+ guest_accelerator = (known after apply)
+ id = (known after apply)
+ instance_id = (known after apply)
+ label_fingerprint = (known after apply)
+ machine_type = "f1-micro"
+ metadata_fingerprint = (known after apply)
+ min_cpu_platform = (known after apply)
......
......
......
......
Aplique sua infraestrutura:
$ terraform apply -auto-approve
Com o seguinte conteúdo:
module.instances.google_compute_instance.this: Creating...
module.instances.google_compute_instance.this: Still creating... [10s elapsed]
module.instances.google_compute_instance.this: Creation complete after 12s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-vm-1]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Com este módulo criado, apenas precisamos passar o valor do campo "name" para que seja criada uma máquina no GCP, mas e se precisarmos mais de uma máquina? devemos repetir o código? a resposta é sempre a mesma… depende!
Depende 1:
Se estas máquinas forem iguais em termos de parâmetros/atributos podemos passar apenas a quantidade de máquinas que queremos utilizar com o atributo chamado "count" no código de nosso módulo e depois informar no uso do módulo a quantidade que queremos utilizar.
Altere o seu arquivo main.tf
do módulo com o novo atributo:
resource "google_compute_instance" "this" {
count = var.amount
name = var.name
machine_type = var.machine_type
zone = var.zone
boot_disk {
initialize_params {
image = var.image
}
}
network_interface {
network = "default"
}
}
Adicione no arquivo variables.tf
apenas neste bloco de variáveis no final do seu arquivo.
variable "amount" {
description = "Quantidade de máquinas que deseja criar"
type = number
default = 1
}
Por fim altere o código que chama o módulo:
module "instances" {
source = "./gcp-instances"
name = "linux-vm-1"
}
Faça o plano de execução normalmente e depois faça o apply:
$ terraform apply -auto-approve
Com o seguinte resultado:
module.instances.google_compute_instance.this[0]: Creating...
module.instances.google_compute_instance.this[0]: Still creating... [10s elapsed]
module.instances.google_compute_instance.this[0]: Creation complete after 13s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-vm-1]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Como visto anteriormente, estamos deixando um valor default para a quantidade de instâncias que queremos utilizar, caso não seja utilizada o valor 1 será adotado.
Agora vamos para o outro caso.
Depende 2:
Caso os atributos para cada grupo de instâncias sejam diferentes, você terá que duplicar a chamada do módulo passando o que difere para este grupo novo, por exemplo:
module "instances" {
source = "./gcp-instances"
amount = 2
name = "linux-vm-1"
}
module "group-web" {
source = "./gcp-instances"
amount = 3
name = "linux-web"
image = "centos-cloud/centos-8"
}
module "group-gitlab" {
source = "./gcp-instances"
amount = 2
name = "linux-gitlab"
image = "centos-cloud/centos-7"
}
Atenção, este código acima é apenas uma demonstração dos tipos de casos que podemos ter, o código não irá funcionar e veremos o motivo no próximo capítulo.