Guia definitivo: Como gerenciar sua infraestrutura com Terraform
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!