Part2 - Terraform to create a virtual machine (VM) in Azure

Posted on April 28, 2023
beginnerstutorialazureTerraforminfrastructure as code (IaC)Terraform Azure VM deploymentCreating an Azure VM with TerraformDeploying a VM on Azure with Terraform

What is Terraform?

Terraform is an open-source infrastructure as code (IaC) tool that allows users to define and manage their cloud infrastructure in a declarative way. This means that users can write code that describes their desired infrastructure state, and Terraform will handle the provisioning and management of the actual resources in the cloud provider.

We talk about Terraform theory in detail in our previous article Part1 - Terraform on Microsoft Azure

Terraform to create/provision a virtual machine (VM) in Azure

Terraform Workflow

  1. Azure subscription: If you don't have an Azure subscription, create a free account
  2. Installing Terraform Terraform Download - For Windows

From the downloaded zip file you need to extract the executable to your directory e.g. c:\terraform and then make sure to update your global path.

  1. Install Azure CLI on Windows Install or update

The Azure Command-Line Interface (CLI) is a cross-platform command-line tool that can be installed locally on Windows computers. You can use the Azure CLI for Windows to connect to Azure and execute administrative commands on Azure resources.

Make sure to restart your command prompt after setting global path and azure cli

  1. Create a main.tf This is the main Terraform configuration file where you define the resources and their configurations that you want to create or manage in your cloud infrastructure.

The source code for this article can be found on GitHub.

# Provider block for Azure
provider "azurerm" {
  features {}
}

# Create a resource group
resource "azurerm_resource_group" "myresourcegroup" {
  name     = "my-resource-group"
  location = "eastus"
}

# Create a virtual network
resource "azurerm_virtual_network" "mynetwork" {
  name                = "my-virtual-network"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.myresourcegroup.location
  resource_group_name = azurerm_resource_group.myresourcegroup.name
}

# Create a subnet
resource "azurerm_subnet" "mysubnet" {
  name                 = "my-subnet"
  address_prefixes     = ["10.0.1.0/24"]
  virtual_network_name = azurerm_virtual_network.mynetwork.name
  resource_group_name  = azurerm_resource_group.myresourcegroup.name
}

# Create a public IP address
resource "azurerm_public_ip" "mypublicip" {
  name                = "my-public-ip"
  location            = azurerm_resource_group.myresourcegroup.location
  resource_group_name = azurerm_resource_group.myresourcegroup.name
  allocation_method   = "Static"
}

# Create a network interface
resource "azurerm_network_interface" "mynic" {
  name                = "my-network-interface"
  location            = azurerm_resource_group.myresourcegroup.location
  resource_group_name = azurerm_resource_group.myresourcegroup.name

  ip_configuration {
    name                          = "my-ip-configuration"
    subnet_id                     = azurerm_subnet.mysubnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.mypublicip.id
  }
}

# Create a virtual machine
resource "azurerm_virtual_machine" "myvm" {
  name                  = "my-virtual-machine"
  location              = azurerm_resource_group.myresourcegroup.location
  resource_group_name   = azurerm_resource_group.myresourcegroup.name
  network_interface_ids = ["${azurerm_network_interface.mynic.id}"]
  vm_size               = "Standard_B2s"

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

  storage_os_disk {
    name              = "my-os-disk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }

  os_profile {
    computer_name  = "myvm"
    admin_username = "admin_01"
    admin_password = "myvmToRock@123"
  }

  os_profile_linux_config {
    disable_password_authentication = false
  }
}
  1. Using Azure CLI

Prepare your working directory for other commands

terraform init -upgrade

Output:

terraform init -upgrade

Show changes required by the current configuration, and create an execution plan and output to *.tfplan

terraform plan -out main.tfplan

Output:

terraform plan

Create or update infrastructure

terraform apply main.tfplan

Output:

terraform apply

Validating Deployment/Virtual Machine

Output- Provisioned Virtual Machine

Clean up resources

When you no longer need the resources created via Terraform, do the following steps:

Destroy previously-created infrastructure and output to *.destroy.tfplan

terraform plan -destroy -out main.destroy.tfplan
terraform apply main.destroy.tfplan

Output:

Terraform Destroy

Using Input and Output variable

Input variable Let you customize the terraform module so that can use reused for multiple configurations if required. Let's see how we can declare input variables.

variables.tf

# Define input variables
variable "resource_group_name" {
  type    = string
  default = "my-resource-group"
}

variable "location" {
  type    = string
  default = "eastus"
}

variable "virtual_network_name" {
  type    = string
  default = "my-virtual-network"
}

Example of using a variable in main.tf (note: we are using var here)

# Create a resource group
resource "azurerm_resource_group" "myresourcegroup" {
  name     = var.resource_group_name
  location = var.location
}

# Create a virtual network
resource "azurerm_virtual_network" "mynetwork" {
  name                = var.virtual_network_name
  address_space       = var.address_space
  location            = azurerm_resource_group.myresourcegroup.location
  resource_group_name = azurerm_resource_group.myresourcegroup.name
}

Output value Output values make information about your infrastructure available on the command line, and can expose information for other Terraform configurations to use. Output values are similar to return values in programming languages.

outputs.tf

output "resource_group_name" {
value = azurerm_resource_group.myresourcegroup.name
}

output "virtual_network_name" {
value = azurerm_virtual_network.mynetwork.name
}

output "subnet_name" {
value = azurerm_subnet.mysubnet.name
}

Example of using an output value

terraform output resource_group_name

Summary

Provided step-by-step instructions on how to perform this transformation also discussion was focused on transforming a Terraform file to use input and output variables.

Thanks for reading!


Posted on April 28, 2023
Profile Picture

Arun Yadav

Software Architect | Full Stack Web Developer | Cloud/Containers

Subscribe
to our Newsletter

Signup for our weekly newsletter to get the latest news, articles and update in your inbox.