Create an Azure Virtual Machine with Terraform

owendavies

Owen Davies

Posted on February 25, 2020

Create an Azure Virtual Machine with Terraform

To round off things nicely, I thought I would follow on from two previous posts about creating Azure Virtual Machines. First we went through how to create an Azure Virtual Machine using PowerShell, then we went through with ARM templates. Now we’re going to use Terraform for the third try.

Create an Azure Virtual Machine with PowerShell

Create an Azure Virtual Machine with an ARM template

Setting the scene

Let’s assume that we have nothing setup. No virtual network, no storage, nothing. So we will be using Terraform to define everything.

The plan

  1. Create our terraform file
  2. Create the AzureRM provider in terraform
  3. Define the Azure resource group
  4. Define a virtual network and subnet
  5. Define a new public IP address
  6. Define a Network Interface for our VM
  7. Define the Virtual Machine
  8. Build the Virtual Machine
  9. The whole file in one
  10. Conclusion

1. Create the terraform file

Let’s create our terraform file and name it main.tf

touch main.tf

Enter fullscreen mode Exit fullscreen mode

2. Create the AzureRM provider in terraform

Open up main.tf in your editor of choice and add the azure provider to the top of the file

provider "azurerm" {
  version = "= 2.0.0"
  features {}
}

Enter fullscreen mode Exit fullscreen mode

3. Define the Azure resource group

Now let’s create our new resource group that everything will live inside

resource "azurerm_resource_group" "rg" {
  name = "my-first-terraform-rg"
  location = "northeurope"
}

Enter fullscreen mode Exit fullscreen mode

4. Define a virtual network and subnet

resource "azurerm_virtual_network" "myvnet" {
  name = "my-vnet"
  address_space = ["10.0.0.0/16"]
  location = "northeurope"
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "frontendsubnet" {
  name = "frontendSubnet"
  resource_group_name = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.myvnet.name
  address_prefix = "10.0.1.0/24"
}

Enter fullscreen mode Exit fullscreen mode

5. Define a new public IP address

resource "azurerm_public_ip" "myvm1publicip" {
  name = "pip1"
  location = "northeurope"
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method = "Dynamic"
  sku = "Basic"
}

Enter fullscreen mode Exit fullscreen mode

6. Define a Network Interface for our VM

resource "azurerm_network_interface" "myvm1nic" {
  name = "myvm1-nic"
  location = "northeurope"
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name = "ipconfig1"
    subnet_id = azurerm_subnet.frontendsubnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id = azurerm_public_ip.myvm1publicip.id
  }
}

Enter fullscreen mode Exit fullscreen mode

7. Define the Virtual Machine

resource "azurerm_windows_virtual_machine" "example" {
  name = "myvm1"  
  location = "northeurope"
  resource_group_name = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.myvm1nic.id]
  size = "Standard_B1s"
  admin_username = "adminuser"
  admin_password = "Password123!"

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer = "WindowsServer"
    sku = "2019-Datacenter"
    version = "latest"
  }

  os_disk {
    caching = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }
}

Enter fullscreen mode Exit fullscreen mode

8. Build the Virtual Machine

Login to Azure with the CLI

There are several ways to authenticate with Azure to run our terraform file, for this example I’m going to suggest the Azure CLI

Make sure you have the Azure CLI installed, then run:

az login

Enter fullscreen mode Exit fullscreen mode

Which should bring up a browser window for you to login to your Azure subscription.

Run terraform init

Now we need to run terrafrom init to prepare the directory and pull down the resources that we have defined in our file.

terraform init

Enter fullscreen mode Exit fullscreen mode

Build our terraform file

terraform apply

Enter fullscreen mode Exit fullscreen mode

Time taken: 3m10s

  1. The whole file in one
provider "azurerm" {
  version = "= 2.0.0"
  features {}
}

resource "azurerm_resource_group" "rg" {
  name = "my-first-terraform-rg"
  location = "northeurope"
}

resource "azurerm_virtual_network" "myvnet" {
  name = "my-vnet"
  address_space = ["10.0.0.0/16"]
  location = "northeurope"
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "frontendsubnet" {
  name = "frontendSubnet"
  resource_group_name = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.myvnet.name
  address_prefix = "10.0.1.0/24"
}

resource "azurerm_public_ip" "myvm1publicip" {
  name = "pip1"
  location = "northeurope"
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method = "Dynamic"
  sku = "Basic"
}

resource "azurerm_network_interface" "myvm1nic" {
  name = "myvm1-nic"
  location = "northeurope"
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name = "ipconfig1"
    subnet_id = azurerm_subnet.frontendsubnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id = azurerm_public_ip.myvm1publicip.id
  }
}

resource "azurerm_windows_virtual_machine" "example" {
  name = "myvm1"  
  location = "northeurope"
  resource_group_name = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.myvm1nic.id]
  size = "Standard_B1s"
  admin_username = "adminuser"
  admin_password = "Password123!"

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer = "WindowsServer"
    sku = "2019-Datacenter"
    version = "latest"
  }

  os_disk {
    caching = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }
}

Enter fullscreen mode Exit fullscreen mode

10. Conclusion

So there we have it, a new Virtual Machine built in Azure using terraform. I personally really like the formatting and syntax compared to ARM templates. Of course I think terraform plan is where the magic is, which ARM template CURRENTLY has no answer for. I’m sure it will come soon enough to ARM, but in the mean time. Terraform really is a great solution for IaC (Infrastructure as Code).

💖 💪 🙅 🚩
owendavies
Owen Davies

Posted on February 25, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related