Edit

Share via


Quickstart: Create a lab and VM using Terraform

Terraform is an infrastructure as code tool that helps you build and manage cloud resources. This article shows how to use Terraform to create a lab containing a Windows Server 2019 Datacenter virtual machine (VM) in Azure DevTest Labs.

Prerequisites

  • Owner or Contributor-level permissions in the Azure subscription where you want to create the lab.
  • Terraform installed and configured, locally or in Azure Cloud Shell.

Create the lab and VM

The sample code this article references is located in the Azure Terraform GitHub repository. The Terraform code takes the following actions:

Create the code files

Create the following files in your Terraform directory. Make sure the directory is added to your PATH.

  • A file named main.tf that contains the following code. You can change the gallery_image_reference to create different types of VMs.

    resource "random_pet" "rg_name" {
      prefix = var.resource_group_name_prefix
    }
    
    resource "random_string" "vm_suffix" {
      length  = 5
      upper   = false
      special = false
      numeric = false
    }
    
    resource "azurerm_resource_group" "rg" {
      name     = random_pet.rg_name.id
      location = var.resource_group_location
    }
    
    resource "random_password" "password" {
      count       = var.password == null ? 1 : 0
      length      = 20
      special     = true
      min_numeric = 1
      min_upper   = 1
      min_lower   = 1
      min_special = 1
    }
    
    locals {
      password = try(random_password.password[0].result, var.password)
    }
    
    resource "azurerm_dev_test_lab" "lab" {
      name                = var.lab_name
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    }
    
    resource "azurerm_dev_test_virtual_network" "vnet" {
      name                = "Dtl${var.lab_name}"
      lab_name            = azurerm_dev_test_lab.lab.name
      resource_group_name = azurerm_resource_group.rg.name
    }
    
    resource "azurerm_dev_test_windows_virtual_machine" "vm" {
      name                   = "ExampleVM-${random_string.vm_suffix.result}"
      lab_name               = azurerm_dev_test_lab.lab.name
      lab_subnet_name        = "Dtl${var.lab_name}Subnet"
      resource_group_name    = azurerm_resource_group.rg.name
      location               = azurerm_resource_group.rg.location
      storage_type           = "Standard"
      size                   = var.vm_size
      username               = var.user_name
      password               = local.password
      allow_claim            = false
      lab_virtual_network_id = azurerm_dev_test_virtual_network.vnet.id
    
      gallery_image_reference {
        offer     = "WindowsServer"
        publisher = "MicrosoftWindowsServer"
        sku       = "2019-Datacenter"
        version   = "latest"
      }
    }
    
  • A file named outputs.tf that contains the following code:

    output "resource_group_name" {
      value = azurerm_resource_group.rg.name
    }
    
    output "lab_name" {
      value = azurerm_dev_test_lab.lab.name
    }
    
    output "vm_name" {
      value = azurerm_dev_test_windows_virtual_machine.vm.name
    }
    
    output "password" {
      sensitive = true
      value     = local.password
    }
    
  • A file named providers.tf that contains the following code:

    terraform {
      required_version = ">=0.12"
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~>3.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
      }
    }
    provider "azurerm" {
      features {}
    }
    
  • A file named variables.tf that contains the following code. You can change the default values for some variables like resource_group_location or vm_size if you need to use different values.

    variable "resource_group_location" {
      type        = string
      default     = "eastus"
      description = "Location for all resources."
    }
    
    variable "resource_group_name_prefix" {
      type        = string
      default     = "rg"
      description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
    }
    
    variable "lab_name" {
      type        = string
      description = "The name of the new lab instance to be created"
      default     = "ExampleLab"
    }
    
    variable "vm_size" {
      type        = string
      description = "The size of the vm to be created."
      default     = "Standard_D4_v3"
    }
    
    variable "user_name" {
      type        = string
      description = "The username for the local account that will be created on the new vm."
      default     = "exampleuser"
    }
    
    variable "password" {
      type        = string
      description = "The password for the local account that will be created on the new vm."
      sensitive   = true
      default     = null
    }
    

Initialize Terraform

Run terraform init to initialize the Terraform deployment. This command downloads the Azure provider required to manage your Azure resources. The -upgrade parameter upgrades the provider plugins to the newest supported version.

terraform init -upgrade

Create the Terraform execution plan

Run terraform plan to create an execution plan. The terraform plan command creates an execution plan, but doesn't execute it. Instead, it determines what actions are necessary to create the configuration specified in your configuration files.

This pattern allows you to verify whether the execution plan matches your expectations before making any changes to actual resources. Use the optional -out parameter to specify an output file named main.tfplan for the plan. You can review the output file to ensure that the plan is exactly what you want to apply.

terraform plan -out main.tfplan

Apply the Terraform execution plan

Run terraform apply to apply the execution plan to your cloud infrastructure. The following terraform apply command assumes you previously ran terraform plan -out main.tfplan.

terraform apply main.tfplan

If you specify a different filename for the -out parameter in terraform_plan, use that filename in the call to terraform apply. If you don't use the -out parameter in terraform_plan, call terraform apply without any parameters.

Verify the results

There are several ways to verify the results of the Terraform deployment. If you have Azure CLI available, you can use az lab vm list to get the names of the resource group and lab that Terraform created.

resource_group_name=$(terraform output -raw resource_group_name)
lab_name=$(terraform output -raw lab_name)
az lab vm list --resource-group $resource_group_name --lab-name $lab_name

Clean up resources

When you no longer need the resources Terraform created, take the following steps to remove them:

  1. Run terraform plan with the destroy flag. The terraform plan command creates the execution plan but doesn't execute it. The -out parameter specifies an output file for the plan named main.destroy.tfplan.

    terraform plan -destroy -out main.destroy.tfplan
    
  2. Run terraform apply to apply the execution plan specified in the main.destroy.tfplan file.

    terraform apply main.destroy.tfplan
    

Next step