Click here to Skip to main content
15,886,105 members
Articles / Containers / Virtual Machine

Create an Azure Virtual Machine with Terraform

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
28 Feb 2020CPOL2 min read 36.9K   1
Using Terraform to create an Azure Virtual Machine
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..

Two Previous Posts

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.

Bash
touch  main.tf

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.

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

3. Define the Azure Resource Group

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

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

4. Define a Virtual Network and Subnet

JSON
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" 
 } 

5. Define a New Public IP Address

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

6. Define a Network Interface for our VM

JSON
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.myvm 1 publicip.id 
   } 
 } 

7. Define the Virtual Machine

JSON
resource   "azurerm_windows_virtual_machine"   "example"   { 
   name                    =   "myvm1"   
   location                =   "northeurope" 
   resource_group_name     =   azurerm_resource_group.rg.name 
   network_interface_ids   =   [ azurerm_network_interface.myvm 1 nic.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" 
   } 
 } 

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:

Bash
az login

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.

Bash
terraform init

Build Our Terraform File

Bash
terraform apply

Time taken: 3m10s

9. The Whole File in One

JSON
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.myvm 1 publicip.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.myvm 1 nic.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" 
   } 
 } 

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).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
United Kingdom United Kingdom
I have been working in software development for over 16 years, during that time I have worn many hats.

I have worked as a Software Engineer, Architect, Agile Coach and Trainer. I’ve created teams, I’ve lead teams, but my main goal is to help teams build great software and enjoy the process.

I help a whole range of businesses – from startups with just an idea who want to build a team to take that idea into reality and FTSE 100 businesses who need to optimise existing teams – I train, mentor and coach them to success.

If you happen to know of anybody who could benefit from results like this, then please go to my contact page and get in touch.

Owen Davies

Comments and Discussions

 
AnswerUpdate to Terraform Code for Azure VM Deployment Pin
Paul Andres Pedroza Martinez8-Nov-21 5:42
Paul Andres Pedroza Martinez8-Nov-21 5:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.