Post

Trabalhando com provisioners no Terraform [Azure]

Fala galera! Seis tão baum?

Sejam bem-vindos a mais um artigo da nossa série sobre Terraform. Hoje vamos falar sobre os Terraform Provisioners, um recurso poderoso que pode ajudar muito na gestão das suas infraestruturas.

1. Uma visão geral de provisioners no Terraform

Para começar, vamos dar uma visão geral sobre os provisioners no Terraform. Provisioners são recursos que permitem a execução de scripts e comandos depois que os recursos são criados ou atualizados. Eles são usados para realizar tarefas que não podem ser feitas com recursos nativos do Terraform, como a instalação de software, a configuração de serviços e outras atividades específicas.

Existem três tipos de provisioners no Terraform: file, local-exec e remote-exec.

Vamos entender um pouco mais sobre cada um deles.

2. file

O provisioner file é utilizado para criar arquivos ou diretórios em máquinas provisionadas. Ele pode ser usado para carregar arquivos de configuração, scripts e outros recursos necessários para o funcionamento dos serviços.

Para utilizar o provisioner file, é necessário especificar o caminho do arquivo que será criado e o seu conteúdo.

Abaixo, segue um exemplo de código que cria um arquivo chamado "example.txt" em uma instância do Azure:

1
2
3
4
5
6
7
8
resource "azurerm_linux_virtual_machine" "example" {
  // Configurações da máquina virtual

  provisioner "file" {
    source      = "files/example.txt"
    destination = "/home/user/example.txt"
  }
}

3. local-exec

O provisioner local-exec é utilizado para executar comandos em máquinas provisionadas. Ele pode ser usado para realizar tarefas como a instalação de pacotes, a configuração de serviços e outras atividades específicas.

Para utilizar o provisioner local-exec, é necessário especificar o comando que será executado.

Abaixo, segue um exemplo de código que executa o comando "sudo apt-get update" em uma instância do Azure:

1
2
3
4
5
6
7
resource "azurerm_linux_virtual_machine" "example" {
  // Configurações da máquina virtual

  provisioner "local-exec" {
    command = "sudo apt-get update"
  }
}

4. remote-exec

O provisioner remote-exec é utilizado para executar comandos em máquinas provisionadas através de uma conexão SSH. Ele pode ser usado para realizar tarefas como a instalação de pacotes, a configuração de serviços e outras atividades específicas.

Para utilizar o provisioner remote-exec, é necessário especificar o comando que será executado e as credenciais de SSH.

Abaixo, segue um exemplo de código que executa o comando "sudo apt-get update" em uma instância do Azure através de uma conexão SSH:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
resource "azurerm_linux_virtual_machine" "example" {
  // Configurações da máquina virtual

  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install nginx -y"
    ]

    connection {
      type        = "ssh"
      user        = "username"
      private_key = file("~/.ssh/id_rsa")
    }
  }
}

5. Comparação entre, file, local-exec e remote-exec

Cada provisioner tem suas próprias vantagens e desvantagens, e o seu uso depende do cenário em que ele será aplicado.

Abaixo, segue uma tabela comparativa entre os três tipos de provisioners:

 filelocal-execremote-exec
O que fazCria arquivos
diretórios
Executa comandos
localmente
Executa comandos
através de uma
conexão SSH
VantagensNão requer
conexão SSH
Pode ser usado
para executar
comandos complexos
Pode ser usado
em máquinas
sem acesso direto
à internet
DesvantagensNão é adequado para
comandos complexos
ou interativos
 Pode ser mais lento
que o local-exec
em ambientes locais
Quando usarQuando você precisa
criar arquivos
Quando você precisa
executar comandos
simples
Quando você precisa
executar comandos
complexos ou
remotos

6. Exemplo de uso

Agora, vamos para um exemplo de uso real que envolve os três tipos de provisioners disponíveis no Terraform. Neste exemplo, vamos criar uma máquina virtual no Azure, instalar o Apache HTTP Server e criar um arquivo HTML simples.

Para isso, vamos precisar de um recurso de máquina virtual, um recurso de rede virtual e um recurso de grupo de segurança de rede.

Aqui está o código Terraform para a criação desses recursos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
resource "azurerm_resource_group" "example" {
  name     = "example-resource-group"
  location = "East US"
}

resource "azurerm_virtual_network" "example" {
  name                = "example-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet" "example" {
  name                 = "example-subnet"
  address_prefixes     = ["10.0.1.0/24"]
  virtual_network_name = azurerm_virtual_network.example.name
  resource_group_name  = azurerm_resource_group.example.name
}

resource "azurerm_network_security_group" "example" {
  name                = "example-nsg"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_network_interface" "example" {
  name                = "example-nic"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.example.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = null
  }
}

resource "azurerm_linux_virtual_machine" "example" {
  name                = "example-vm"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  size                = "Standard_B1s"
  admin_username      = "adminuser"
  network_interface_ids = [
    azurerm_network_interface.example.id,
  ]
  os_disk {
    name              = "example-osdisk"
    caching           = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }
  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "18.04-LTS"
    version   = "latest"
  }
}

Agora, vamos adicionar um provisioner file para criar um arquivo HTML simples na máquina virtual:

1
2
3
4
5
6
7
8
resource "azurerm_linux_virtual_machine" "example" {
  // ...

  provisioner "file" {
    source = "index.html"
    destination = "/var/www/html/index.html"
  }
}

Em seguida, adicionamos um provisioner local-exec para instalar o Apache HTTP Server na máquina virtual:

1
2
3
4
5
6
7
8
9
10
11
12
resource "azurerm_linux_virtual_machine" "example" {
  // ...

  provisioner "file" {
    source = "index.html"
    destination = "/var/www/html/index.html"
  }

  provisioner "local-exec" {
    command = "sudo apt-get update && sudo apt-get install -y apache2"
  }
}

Agora, vamos adicionar o provisioner remote-exec para iniciar o serviço Apache HTTP Server na máquina virtual:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
resource "azurerm_linux_virtual_machine" "example" {
  // ...

  provisioner "file" {
    source = "index.html"
    destination = "/var/www/html/index.html"
  }

  provisioner "local-exec" {
    command = "sudo apt-get update && sudo apt-get install -y apache2"
  }

  provisioner "remote-exec" {
    inline = [
      "sudo systemctl start apache2",
      "sudo systemctl enable apache2"
    ]
  }
}

E, finalmente, crie um arquivo chamado index.html com o seguinte conteúdo:

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
  <head>
    <title>Terraform + Azure</title>
  </head>
  <body>
    <h1>Terraform + Azure = ❤️</h1>
    <p>

Com esses três provisioners, podemos criar uma máquina virtual, instalar o Apache HTTP Server e criar um arquivo HTML simples. Vale lembrar que o provisioner remote-exec também pode ser usado para executar comandos em outras máquinas virtuais na mesma rede.

Para executar este código, basta colocar os arquivos index.html e main.tf no mesmo diretório e, em seguida, executar os seguintes comandos:

1
2
terraform init
terraform apply

Com isso, o Terraform criará os recursos no Azure e executará os provisioners para configurar a máquina virtual. Após a execução, você poderá acessar a página web em **http://**.

7. Conclusão

Os provisioners no Terraform são uma ótima opção para realizar tarefas específicas que não podem ser feitas com os recursos nativos do Terraform. Cada tipo de provisioner tem suas próprias vantagens e desvantagens, e é importante entender as diferenças entre eles para escolher o mais adequado para o seu cenário.

No entanto, confesso que não utilizo frequentemente os provisioners em minha rotina de trabalho. Na maioria das vezes, prefiro utilizar o Ansible para configurar a infraestrutura e deixar o Terraform responsável apenas pelo provisionamento.

Isso não significa que os provisioners não sejam uma excelente opção para determinados casos de uso. Na verdade, essa funcionalidade é mais uma opção poderosa que o Terraform oferece, capaz de atender às necessidades de diferentes projetos.

Espero que este artigo tenha sido útil e esclarecedor para você entender o que são os provisioners no Terraform e como utilizá-los em seus projetos.

Se você tiver alguma dúvida ou comentário, sinta-se à vontade para compartilhá-los conosco na seção de comentários abaixo!

É isso galera, espero que gostem!

Forte Abraço!

Este post está licenciado sob CC BY 4.0 e pelo autor.