Terraform | Introdução

Terraform | Introdução

Iniciando Terraform com Google Cloud Platform (GCP)

Introdução ao Terraform

Terraform é uma ferramenta de código aberto comumente utilizada para construir, alterar e versionar uma infraestrutura de forma segura e eficiente, através de uma linguagem declarativa. A ferramenta é escrita em GoLang e teve seu primeiro release em 2014 e atualmente suporta uma grande variedade de nuvens públicas, como Google Cloud, AWS, Azure, Digital Ocean e também nuvens privadas, como por exemplo o OpenStack.

Com Terraform é possível gerenciar os componentes chamados de low-level, como por exemplo instâncias (máquinas virtuais), storage e redes, mas também serviços, como DNS e bancos de dados.

Para descrever o que você quer que seja criado utilizando Terraform, é necessário apenas criar arquivos de configuração no formato HCL (Hashicorp Configuration Language) que podem servir para pequenos projetos ou até uma infraestrutura por completo, como um datacenter. Uma vez descrito o que deve ser criado, é gerado um plano de execução (plan) que irá mostrar o que será criado e dai sim estas modificações poderão ser aplicadas (apply) para criar os componentes necessários.

Acompanharemos abaixo um exemplo de como criar uma nova instância no Google Cloud Platform – GCP.

Primeiro de tudo é necessário baixar o Terraform em https://www.terraform.io/downloads.html. Nesta página você irá encontrar os binários para o seu sistema, simplesmente faça o download deste arquivo e descompacte em algum diretório.

Não esqueça que Terraform é escrito em GoLang, ou seja, todas dependências para o software funcionar já estão dentro do pacote, então apenas adicione permissão de execução neste binário.

Para fazer um teste rápido se está tudo correto, execute o comando ./terraform e pressione enter ou então adicione no seu $PATH. Ao executar o comando, deverá ser mostrado a lista com todos os subcomandos conforme abaixo.

Usage: terraform [-version] [-help]  [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you are just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
apply Builds or changes infrastructure
console Interactive console for Terraform interpolations
destroy Destroy Terraform-managed infrastructure
env Workspace management
fmt Rewrites config files to canonical format
get Download and install modules for the configuration
graph Create a visual graph of Terraform resources
import Import existing infrastructure into Terraform
init Initialize a Terraform working directory
output Read an output from a state file
plan Generate and show an execution plan
providers Prints a tree of the providers used in the configuration
refresh Update local state file against real resources
show Inspect Terraform state or plan
taint Manually mark a resource for recreation
untaint Manually unmark a resource as tainted
validate Validates the Terraform files
version Prints the Terraform version
workspace Workspace management

All other commands:
0.12upgrade Rewrites pre-0.12 module source code for v0.12
debug Debug output management (experimental)
force-unlock Manually unlock the terraform state
push Obsolete command for Terraform Enterprise legacy (v1)
state Advanced state management
Com Terraform sendo executado, a primeira coisa que precisamos fazer é configurar um Provider em um arquivo. Neste arquivo é descrito qual Provider estamos querendo utilizar e quais nossas credenciais para criar recursos e claro, precisamos já ter uma conta no Google Cloud Platform.

Assumindo que você tem uma conta no Google, crie suas credenciais: vá até console.cloud.google.com/apis/credentials/s.., selecione Compute Engine default service account escolha o formato JSON e baixe-o para o seu computador.

Crie o arquivo de provider.tf em qualquer diretório com o seguinte conteúdo abaixo, alterando o caminho das credenciais para o caminho onde salvou o arquivo JSON contendo as suas credenciais:

provider "google" {
  credentials = "/home/rafael/.google/credentials.json"
  project = "projeto-1"
  region = "us-east-1"
}

Próximo passo é inicializarmos este Provider que acabamos de escrever acima. O que o Terraform irá fazer é olhar o seu código, procurar por um Provider (Google) e então baixar os plugins necessários para fazer a comunicação entre sua máquina e o Google.

Para inicializar o Provider, utilize o comando terraform init.

$ terraform init

Ao executar o comando, você irá receber no seu terminal uma mensagem como esta abaixo:

Initializing the backend...

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "google" (hashicorp/google) 3.1.0...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.google: version = "~> 3.1"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Agora é necessário criar seu primeiro código que será responsável por criar uma instância na GCP.

Abaixo, é possível observar o código que irá criar uma máquina virtual chamada de linux-vm-1 com o tamanho f1-micro (cada Cloud Provider utiliza suas nomeclaturas para definir tamanhos de máquinas e outros recursos) e iremos criar esta máquina na zone us-central1-a.

Crie um arquivo chamado de instance.tf com o seguinte código abaixo:

resource "google_compute_instance" "default" {
  name = "linux-vm-1"
  machine_type = "f1-micro"
  zone = "us-central1-a"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-9"
  }
}

  network_interface {
    network = "default"
  }
}

Execute o comando para planejar o que será criado:

$ terraform plan

Ao executar o comando, você irá receber no seu terminal uma mensagem como esta abaixo.

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # google_compute_instance.default will be created
  + resource "google_compute_instance" "default" {
      + 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)
      + name                 = "linux-vm-1"
      + project              = (known after apply)
      + self_link            = (known after apply)
      + tags_fingerprint     = (known after apply)
      + zone                 = "us-east-a"

      + boot_disk {
          + auto_delete                = true
          + device_name                = (known after apply)
          + disk_encryption_key_sha256 = (known after apply)
          + kms_key_self_link          = (known after apply)
          + mode                       = "READ_WRITE"
          + source                     = (known after apply)

          + initialize_params {
              + image  = "debian-cloud/debian-9"
              + labels = (known after apply)
              + size   = (known after apply)
              + type   = (known after apply)
            }
        }

      + network_interface {
          + name               = (known after apply)
          + network            = "default"
          + network_ip         = (known after apply)
          + subnetwork         = (known after apply)
          + subnetwork_project = (known after apply)
        }

      + scheduling {
          + automatic_restart   = (known after apply)
          + on_host_maintenance = (known after apply)
          + preemptible         = (known after apply)

          + node_affinities {
              + key      = (known after apply)
              + operator = (known after apply)
              + values   = (known after apply)
            }
        }
    }

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

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Conforme foi visto, este é o plano de execução do Terraform, aqui é mostrado tudo que será criado, alterado ou ainda que poderá ser destruído.

Veja na última linha do terminal a seguinte mensagem:

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

Esta linha é super importante pois nos retorna um status do que será realizado pelo plano de ação, neste caso apenas 1 recurso será criado.

Para aplicarmos nosso código e criarmos a máquina virtual, precisamos do comando para aplicar que é feito através do comando terraform apply. Caso não seja passado o argumento -auto-approve, o Terraform irá pedir a confirmação para realiza esta ação.

$ terraform apply -auto-approve

Com o seguinte resultado:

google_compute_instance.default: Creating...
google_compute_instance.default: Still creating... [10s elapsed]
google_compute_instance.default: Creation complete after 13s [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Para destruirmos esta máquina, apenas alteramos o comando apply para destroy.

$ terraform destroy -auto-approve

Com o seguinte resultado:

google_compute_instance.default: Refreshing state... [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1]
google_compute_instance.default: Destroying... [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1]
google_compute_instance.default: Still destroying... [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1, 10s elapsed]
google_compute_instance.default: Still destroying... [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1, 20s elapsed]
google_compute_instance.default: Still destroying... [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1, 30s elapsed]
google_compute_instance.default: Still destroying... [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1, 40s elapsed]
google_compute_instance.default: Still destroying... [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1, 50s elapsed]
google_compute_instance.default: Still destroying... [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1, 1m0s elapsed]
google_compute_instance.default: Still destroying... [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1, 1m10s elapsed]
google_compute_instance.default: Still destroying... [id=projects/projeto-1/zones/us-central1-a/instances/linux-vm-1, 1m20s elapsed]
google_compute_instance.default: Destruction complete after 1m20s

Destroy complete! Resources: 1 destroyed.