Alisson Machado
22 January 2020

Terraform, Azure: Criando uma infraestrutura básica

Oi Pessoal, Como já faz um tempo que a minha vida só tem sido Azure e eu não tenho nenhum post aqui sobre isso, vou começar com esse.


Nesse tutorial vou mostrar como podemos fazer uma introdução ao Terraform, azclick e Azure e como podemos criar toda uma infraestrutura sem basicamente acessar o painel. Primeiro passo é instalar o Terraform e o AZCli.


https://www.terraform.io/downloads.htmlhttps://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?view=azure-cli-latest


Bom, já estou considerando que você já se cadastrou na Azure e já tenho acesso ao painel. Abaixo um exemplo da tela inicial da parte de criação de máquinas virtuais da Azure.


Então para fazer o login via AZCli, digite o seguinte comando:

az login


O windows abrirá uma nova janela no navegador e pedir para você selecionar a sua conta, uma vez que autenticação está correta você receberá uma mensagem assim.

PS C:\Users\1511 MXTI> az login
Note, we have launched a browser for you to login. For old experience with device code, use "az login --use-device-code"
You have logged in. Now let us find all the subscriptions to which you have access...
[
  {
    "cloudName": "AzureCloud",
    "id": "55465d5a-355d-43d1-85ce-9e518c812c0c",
    "isDefault": true,
    "name": "Pay-As-You-Go",
    "state": "Enabled",
    "tenantId": "b048b26d-8424-43eb-8b37-12820133cc95",
    "user": {
      "name": "alisson.copyleft@gmail.com",
      "type": "user"
    }
  }
]


No meu caso está tudo certo já.


Quando trabalhamos com Azure é importante criarmos um ResourceGroup, que é basicamente um groupo onde você irá alocar todos os serviços contratados para um determinado contexto.


Por exemplo, no meu caso eu estou fazendo a migração do meu blog para a Azure, então nada mais justo do criar um ResourceGroup chamado Blog e dentro dele criar uma máquina virtual que posso chamar de WebServer, um banco de dados, pode ser um CosmoDB, uma StorageAccount para guardar o estado do Terraform e toda essa infraestrutura é criada com o propósito de atender o meu blog.


Listando todos os ResourceGroups.

PS C:\Users\1511 MXTI> az group list
[]


Criando um ResourgeGroup.

PS C:\Users\1511 MXTI> az group create --name Blog --location westeurope
{
  "id": "/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog",
  "location": "westeurope",
  "managedBy": null,
  "name": "Blog",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": null
}


O local aonde será criado esse ResourceGroup é obrigatório, no meu caso selecionei westeurope. Para listar todas as localidades você pode usar o comando:

PS C:\Users\1511 MXTI> az account list-locations


Vamos listar agora as Storage Accounts, elas são equivalentes aos repositórios S3 na Amazon, que servem para fazer o armazenamento de arquivos, nesse tutorial vou usar uma StorageAccount para guardar o estado do terraform, isso vai ser explicado mais a frente. Listando as StorageAccount:

PS C:\Users\1511 MXTI> az storage account list
[]


Criando a StorageAccount:

PS C:\Users\1511 MXTI> az storage account create --name alissonstack --resource-group Blog
{
  "accessTier": null,
  "azureFilesIdentityBasedAuthentication": null,
  "creationTime": "2020-01-22T19:04:03.283860+00:00",
  "customDomain": null,
  "enableHttpsTrafficOnly": true,
  "encryption": {
    "keySource": "Microsoft.Storage",
    "keyVaultProperties": null,
    "services": {
      "blob": {
        "enabled": true,
        "lastEnabledTime": "2020-01-22T19:04:03.362000+00:00"
      },
      "file": {
        "enabled": true,
        "lastEnabledTime": "2020-01-22T19:04:03.362000+00:00"
      },
      "queue": null,
      "table": null
    }
  },


Já temos a storage account, dentro dela precisamos criar um Container que é onde serão armazenados os arquivos. Para criar o container precisamos pegar a chave de acesso a StorageAccount, portanto execute o comando:

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> az storage account keys list --account-name alissonstack
[
  {
    "keyName": "key1",
    "permissions": "Full",
    "value": "--=Chave1=--"
  },
  {
    "keyName": "key2",
    "permissions": "Full",
    "value": "--=Chave2=--"
  }
]


Criando o container:

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> az storage container create --name terraform --account-name alissonstack --account-key "--=Chave1=--"
{
  "created": true
}


Beleza, agora já temos o básico de infraestrutura para começar com o Terraform. Crie um arquivo chamado blog.tf e nele coloque o seguinte conteudo.

provider "azurerm" {
    
}

terraform {
  

    backend "azurerm" {
        resource_group_name  = "Blog"
        storage_account_name = "alissonstack"
        container_name       = "terraform"
        key                  = "blog.tfstate"
    }

}


Está bem simples, pois quero mostrar como a gente pode incrementar a nossa infraestrutura e ver as mudanças de estado a partir do momento que executamos o terraform.


No mesmo diretório onde você criou o arquivo, execute o seguinte comando:

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> terraform init

Initializing the backend...

Initializing provider plugins...

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.azurerm: version = "~> 1.41"

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.


Esse comando acima, vai fazer o Download dos plugins necessários para executar o terraform, como no caso o AzureRM que é o plugin utilizado para criar coisas na Azure. No meu caso não deu nenhum erro, agora vamos executar o nosso primeiro plan.

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> terraform plan
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.


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

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.


O Terraform plan. serve pra você poder ver com antecedencia o que será modificado na sua infraestrutura, no nosso caso como não temos nada ainda, ela está up-to-date.


Agora vamos criar uma máquina virtual e ver como o terraform se comporta.


Para criar a máquina virtual, primeiro precisamos criar 3 itens.


  • - VNet (VirtualNetwork): quer seria a nossa rede completa
  • - Subnet: que pode ser uma rede menor dentro da nossa VNet, no meu caso vou usar a rede inteira
  • - NetworkInterface: que é o equivalente a uma placa de rede que será atrelada a máquina virtual Com esses três itens criados, podemos criar a nossa máquina virtual.


Então agora o nosso arquivo do terraform ficou assim:

provider "azurerm" {
    
}

terraform {
  

    backend "azurerm" {
        resource_group_name  = "Blog"
        storage_account_name = "alissonstack"
        container_name       = "terraform"
        key                  = "blog.tfstate"
    }
    
}

resource "azurerm_virtual_network" "production" {
  name                = "production-network"
  address_space       = ["192.168.0.0/24"]
  location            = "westeurope"
  resource_group_name = "Blog"
}

resource "azurerm_subnet" "main_subnet" {
  name                 = "main_subnet"
  resource_group_name = "Blog"
  virtual_network_name = "${azurerm_virtual_network.production.name}"
  address_prefix       = "192.168.0.0/24"
}

resource "azurerm_network_interface" "nic01" {
  name                = "nic01"
  location            = "westeurope"
  resource_group_name = "Blog"

  ip_configuration {
    name                          = "ip01"
    subnet_id                     = "${azurerm_subnet.main_subnet.id}"
    private_ip_address_allocation = "static"
    private_ip_address = "192.168.0.10"
  }
}

resource "azurerm_virtual_machine" "blog" {
    name                  = "blog-prod"
    location              = "westeurope"
    resource_group_name   = "Blog"
    vm_size               = "Standard_DS1_v2"
    network_interface_ids = ["${azurerm_network_interface.nic01.id}"]


    storage_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "18.04-LTS"
        version   = "latest"
    }
    storage_os_disk {
        name              = "blogdisk"
        caching           = "ReadWrite"
        create_option     = "FromImage"
        managed_disk_type = "Standard_LRS"
    }
    os_profile {
        computer_name  = "blog.alissonmachado.com.br"
        admin_username = "alisson"
        admin_password = "teste123"
    }
    os_profile_linux_config {
        disable_password_authentication = true

        ssh_keys {
            key_data = file("~/.ssh/id_rsa.pub")
            path = "/home/alisson/.ssh/authorized_keys"
        }
    }
}


Resumindo:


Eu criei uma VNet chamada production, dentro dela foi criada uma Subnet chamada main_subnet e uma placa de rede chamada nic01.


A VNet foi configurada com o AddressSpace 192.168.0.0/24, que é o tamanho total da minha rede e a subnet com o mesmo range.


Já a NetworkInterface (nic01), está com um ip estático, ou seja, ele nunca vai mudar e foi atrelado o endereço 192.168.0.10.


Logo na sequencia temos as configurações da máquina virtual. Sistema Operacional: Ubuntu 18.04 Tamanho: Standard_DS1_v2 - 1 vCPU e 3,5 de RAM Agora vamos executar o Terraform plan e ver qual será a saída.

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> terraform plan
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:

  # azurerm_network_interface.nic01 will be created
  + resource "azurerm_network_interface" "nic01" {
      + applied_dns_servers           = (known after apply)
      + dns_servers                   = (known after apply)
      + enable_accelerated_networking = false
      + enable_ip_forwarding          = false
      + id                            = (known after apply)
      + internal_dns_name_label       = (known after apply)
      + internal_fqdn                 = (known after apply)
      + location                      = "westeurope"
      + mac_address                   = (known after apply)
      + name                          = "nic01"
      + private_ip_address            = (known after apply)
      + private_ip_addresses          = (known after apply)
      + resource_group_name           = "Blog"
      + tags                          = (known after apply)
      + virtual_machine_id            = (known after apply)

      + ip_configuration {
          + application_gateway_backend_address_pools_ids = (known after apply)
          + application_security_group_ids                = (known after apply)
          + load_balancer_backend_address_pools_ids       = (known after apply)
          + load_balancer_inbound_nat_rules_ids           = (known after apply)
          + name                                          = "ip01"
          + primary                                       = (known after apply)
          + private_ip_address                            = "192.168.0.2"
          + private_ip_address_allocation                 = "static"
          + private_ip_address_version                    = "IPv4"
          + subnet_id                                     = (known after apply)
        }
    }

  # azurerm_subnet.main_subnet will be created
  + resource "azurerm_subnet" "main_subnet" {
      + address_prefix                                 = "192.168.0.0/24"
      + enforce_private_link_endpoint_network_policies = false
      + enforce_private_link_service_network_policies  = false
      + id                                             = (known after apply)
      + ip_configurations                              = (known after apply)
      + name                                           = "main_subnet"
      + resource_group_name                            = "Blog"
      + virtual_network_name                           = "production-network"
    }

  # azurerm_virtual_machine.blog will be created
  + resource "azurerm_virtual_machine" "blog" {
      + availability_set_id              = (known after apply)
      + delete_data_disks_on_termination = false
      + delete_os_disk_on_termination    = false
      + id                               = (known after apply)
      + license_type                     = (known after apply)
      + location                         = "westeurope"
      + name                             = "blog-prod"
      + network_interface_ids            = (known after apply)
      + resource_group_name              = "Blog"
      + tags                             = (known after apply)
      + vm_size                          = "Standard_DS1_v2"

      + identity {
          + identity_ids = (known after apply)
          + principal_id = (known after apply)
          + type         = (known after apply)
        }

      + os_profile_linux_config {
          + disable_password_authentication = true

          + ssh_keys {
              + key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChi8HX26xv9Rk9gz47Qhb+Tu7MRqGIyPxnheIeEgFad/dlqG4w4pY7y5dtx5LNGE9C01varco5dZagqsHplI7M+5ECSvjAuS6b5rkYZwZiZruDXxckcQHFpr2yIz3DOzKRTUc5Hg5JHF5aymiqyVfTsxL/aI/LDY8Ikh+INn3S9+b5bZtU+74tA6yuqth5SCtNSWwMUlv7QL6ONHtQiviAjBe+ksDBBV6thWz2ZIJA/jApSIBJWK9AWmZwq2hFy9sOZArUDB2Kt6kl3rIZnHpqJ/GMUCxFhtggYamJ5J2H6277qLFqLZ/8tum9uc5l/lSWYKTDm2+E/prQfmFrxPf9 1511 mxti@avell\r\n"
              + path     = "/home/alisson/.ssh/authorized_keys"
            }
        }

      + storage_data_disk {
          + caching                   = (known after apply)
          + create_option             = (known after apply)
          + disk_size_gb              = (known after apply)
          + lun                       = (known after apply)
          + managed_disk_id           = (known after apply)
          + managed_disk_type         = (known after apply)
          + name                      = (known after apply)
          + vhd_uri                   = (known after apply)
          + write_accelerator_enabled = (known after apply)
        }

      + storage_image_reference {
          + offer     = "UbuntuServer"
          + publisher = "Canonical"
          + sku       = "18.04-LTS"
          + version   = "latest"
        }

      + storage_os_disk {
          + caching                   = "ReadWrite"
          + create_option             = "FromImage"
          + disk_size_gb              = (known after apply)
          + managed_disk_id           = (known after apply)
          + managed_disk_type         = "Standard_LRS"
          + name                      = "blogdisk"
          + os_type                   = (known after apply)
          + write_accelerator_enabled = false
        }
    }

  # azurerm_virtual_network.production will be created
  + resource "azurerm_virtual_network" "production" {
      + address_space       = [
          + "192.168.0.0/24",
        ]
      + id                  = (known after apply)
      + location            = "westeurope"
      + name                = "production-network"
      + resource_group_name = "Blog"
      + tags                = (known after apply)

      + subnet {
          + address_prefix = (known after apply)
          + id             = (known after apply)
          + name           = (known after apply)
          + security_group = (known after apply)
        }
    }

Plan: 4 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.


Veja que o Terraform colocou um sinal de + na frente de tudo que será criado.


No caso parece que está tudo certo então vamos executar com o comando Terraform Apply.

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> terraform apply

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

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_virtual_machine.blog: Creating...
azurerm_virtual_machine.blog: Still creating... [10s elapsed]
azurerm_virtual_machine.blog: Still creating... [20s elapsed]
azurerm_virtual_machine.blog: Still creating... [30s elapsed]
azurerm_virtual_machine.blog: Still creating... [40s elapsed]
azurerm_virtual_machine.blog: Still creating... [50s elapsed]
azurerm_virtual_machine.blog: Still creating... [1m0s elapsed]
azurerm_virtual_machine.blog: Still creating... [1m10s elapsed]
azurerm_virtual_machine.blog: Still creating... [1m20s elapsed]
azurerm_virtual_machine.blog: Still creating... [1m30s elapsed]
azurerm_virtual_machine.blog: Still creating... [1m40s elapsed]
azurerm_virtual_machine.blog: Still creating... [1m50s elapsed]
azurerm_virtual_machine.blog: Still creating... [2m0s elapsed]
azurerm_virtual_machine.blog: Still creating... [2m10s elapsed]
azurerm_virtual_machine.blog: Still creating... [2m20s elapsed]
azurerm_virtual_machine.blog: Still creating... [2m30s elapsed]
azurerm_virtual_machine.blog: Creation complete after 2m32s [id=/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Compute/virtualMachines/blog-prod]

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


O terraform apply, vai exibir de novo o conteúdo do plan e pedir para confirmar a execução, no meu caso deu tudo certo.


Apply Complete! Caso você queira validar é possível fazer isso com o az cli tbm.

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> az vm list
[
  {
    "additionalCapabilities": null,
    "availabilitySet": null,
    "diagnosticsProfile": null,
    "hardwareProfile": {
      "vmSize": "Standard_DS1_v2"
    },
...


Até agora tudo certo, mas a nossa máquina ainda não tem IP Publico, então vamos associar e ver como o terraform se comporta. Isso poderia ter sido feito desde o inicio, eu estou fazendo em duas etapas para que a gente possa ver o comportamento do terraform com relação aos estados.


Vamos adicionar o IP Publico e os outputs.

provider "azurerm" {
    
}

terraform {
  

    backend "azurerm" {
        resource_group_name  = "Blog"
        storage_account_name = "alissonstack"
        container_name       = "terraform"
        key                  = "blog.tfstate"
    }
    
}

resource "azurerm_virtual_network" "production" {
  name                = "production-network"
  address_space       = ["192.168.0.0/24"]
  location            = "westeurope"
  resource_group_name = "Blog"
}

resource "azurerm_subnet" "main_subnet" {
  name                 = "main_subnet"
  resource_group_name = "Blog"
  virtual_network_name = "${azurerm_virtual_network.production.name}"
  address_prefix       = "192.168.0.0/24"
}

resource "azurerm_public_ip" "public_address" {
    name                = "public_address"
    location            = "westeurope"
    resource_group_name = "Blog"
    allocation_method   = "Static"

}

resource "azurerm_network_interface" "nic01" {
  name                = "nic01"
  location            = "westeurope"
  resource_group_name = "Blog"

  ip_configuration {
    name                          = "ip01"
    subnet_id                     = "${azurerm_subnet.main_subnet.id}"
    private_ip_address_allocation = "static"
    private_ip_address = "192.168.0.10"
    public_ip_address_id          = "${azurerm_public_ip.public_address.id}"

  }
}



resource "azurerm_virtual_machine" "blog" {
    name                  = "blog-prod"
    location              = "westeurope"
    resource_group_name   = "Blog"
    vm_size               = "Standard_DS1_v2"
    network_interface_ids = ["${azurerm_network_interface.nic01.id}"]


    storage_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "18.04-LTS"
        version   = "latest"
    }
    storage_os_disk {
        name              = "blogdisk"
        caching           = "ReadWrite"
        create_option     = "FromImage"
        managed_disk_type = "Standard_LRS"
    }
    os_profile {
        computer_name  = "blog.alissonmachado.com.br"
        admin_username = "alisson"
        admin_password = "teste123"
    }
    os_profile_linux_config {
        disable_password_authentication = true

        ssh_keys {
            key_data = file("~/.ssh/id_rsa.pub")
            path = "/home/alisson/.ssh/authorized_keys"
        }
    }

    
}


output "vm_name" {
  value = "${azurerm_virtual_machine.blog.name}"
}
output "vm_size" {
  value = "${azurerm_virtual_machine.blog.vm_size}"
}
output "public_ip" {
  value = "${azurerm_public_ip.public_address.ip_address}"
}


Agora executando o Terraform plan para ver o que alterou.

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> terraform plan
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.

azurerm_virtual_network.production: Refreshing state... [id=/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Network/virtualNetworks/production-network]
azurerm_subnet.main_subnet: Refreshing state... [id=/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Network/virtualNetworks/production-network/subnets/main_subnet]
azurerm_network_interface.nic01: Refreshing state... [id=/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Network/networkInterfaces/nic01]
azurerm_virtual_machine.blog: Refreshing state... [id=/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Compute/virtualMachines/blog-prod]

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

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

Terraform will perform the following actions:

  # azurerm_network_interface.nic01 will be updated in-place
  ~ resource "azurerm_network_interface" "nic01" {
        applied_dns_servers           = []
        dns_servers                   = []
        enable_accelerated_networking = false
        enable_ip_forwarding          = false
        id                            = "/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Network/networkInterfaces/nic01"
        location                      = "westeurope"
        mac_address                   = "00-0D-3A-A8-82-DB"
        name                          = "nic01"
        private_ip_address            = "192.168.0.10"
        private_ip_addresses          = [
            "192.168.0.10",
        ]
        resource_group_name           = "Blog"
        tags                          = {}
        virtual_machine_id            = "/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Compute/virtualMachines/blog-prod"

      ~ ip_configuration {
            application_gateway_backend_address_pools_ids = []
            application_security_group_ids                = []
            load_balancer_backend_address_pools_ids       = []
            load_balancer_inbound_nat_rules_ids           = []
            name                                          = "ip01"
            primary                                       = true
            private_ip_address                            = "192.168.0.10"
            private_ip_address_allocation                 = "static"
            private_ip_address_version                    = "IPv4"
          + public_ip_address_id                          = (known after apply)
            subnet_id                                     = "/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Network/virtualNetworks/production-network/subnets/main_subnet"
        }
    }

  # azurerm_public_ip.public_address will be created
  + resource "azurerm_public_ip" "public_address" {
      + allocation_method            = "Static"
      + fqdn                         = (known after apply)
      + id                           = (known after apply)
      + idle_timeout_in_minutes      = 4
      + ip_address                   = (known after apply)
      + ip_version                   = "IPv4"
      + location                     = "westeurope"
      + name                         = "public_address"
      + public_ip_address_allocation = (known after apply)
      + resource_group_name          = "Blog"
      + sku                          = "Basic"
      + tags                         = (known after apply)
    }

Plan: 1 to add, 1 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.


Tudo certo, então vamos aplicar como Terraform apply.

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> terraform apply
Plan: 1 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_public_ip.public_address: Creating...
azurerm_public_ip.public_address: Creation complete after 3s [id=/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Network/publicIPAddresses/public_address]
azurerm_network_interface.nic01: Modifying... [id=/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Network/networkInterfaces/nic01]
azurerm_network_interface.nic01: Still modifying... [id=/subscriptions/55465d5a-355d-43d1-85ce-...rosoft.Network/networkInterfaces/nic01, 10s elapsed]
azurerm_network_interface.nic01: Still modifying... [id=/subscriptions/55465d5a-355d-43d1-85ce-...rosoft.Network/networkInterfaces/nic01, 20s elapsed]
azurerm_network_interface.nic01: Still modifying... [id=/subscriptions/55465d5a-355d-43d1-85ce-...rosoft.Network/networkInterfaces/nic01, 30s elapsed]
azurerm_network_interface.nic01: Still modifying... [id=/subscriptions/55465d5a-355d-43d1-85ce-...rosoft.Network/networkInterfaces/nic01, 40s elapsed]
azurerm_network_interface.nic01: Still modifying... [id=/subscriptions/55465d5a-355d-43d1-85ce-...rosoft.Network/networkInterfaces/nic01, 50s elapsed]
azurerm_network_interface.nic01: Modifications complete after 52s [id=/subscriptions/55465d5a-355d-43d1-85ce-9e518c812c0c/resourceGroups/Blog/providers/Microsoft.Network/networkInterfaces/nic01]

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

Outputs:

public_ip = 13.80.128.118
vm_name = blog-prod
vm_size = Standard_DS1_v2


Note que no final da execução o terraform nos mostrou o endereço de IP, nome da máquina e o tamanho da VM.


Caso você queira consultar essa informação novamente sem precisar digitar o AZCli ou acessar o painel, temos o comando:

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> terraform output
public_ip = 13.80.128.118
vm_name = blog-prod
vm_size = Standard_DS1_v2


Agora vamos testar o acesso a essa VM.

PS C:\Users\1511 MXTI\Documents\MyStack\Azure> ssh alisson@13.80.128.118
The authenticity of host '13.80.128.118 (13.80.128.118)' can't be established.
ECDSA key fingerprint is SHA256:JHio39GCKeEYU3o/O00xN4Xd8i4rpqwvivnTuHf9FUQ.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '13.80.128.118' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 5.0.0-1027-azure x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Wed Jan 22 20:31:39 UTC 2020

  System load:  0.0               Processes:           107
  Usage of /:   4.0% of 28.90GB   Users logged in:     0
  Memory usage: 9%                IP address for eth0: 192.168.0.10
  Swap usage:   0%

0 packages can be updated.
0 updates are security updates.



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To run a command as administrator (user "root"), use "sudo ".
See "man sudo_root" for details.

alisson@blog:~$


Tudo topzera funcionando =).


Agora no final um printscreen para que a gente possa ver tudo que foi criado.


Brigaduuu, xau!