Featured image of post Creating a Windows VM with Terraform: Managing Resource Dependencies - Terraform on Azure - Part 6

Creating a Windows VM with Terraform: Managing Resource Dependencies - Terraform on Azure - Part 6

Get ready to embark on an exciting adventure as we create a Windows Virtual Machine on Azure using Terraform! In this hands-on guide, we'll not only learn how to manage resource dependencies like pros but also have a blast doing it. Buckle up, folks โ€“ it's gonna be a wild ride! ๐Ÿš€

Introduction ๐ŸŽ‰

Hey there, Everyone! ๐Ÿ‘‹ Welcome back to our exciting journey into the world of Terraform on Azure! Last time, we dove deep into the heart of Terraform’s magic: the dependency graph. We explored how Terraform automatically detects dependencies between resources, plans the deployment order, and manages changes like a boss.

In this post, we’ll take our skills to the next level by creating a Windows Virtual Machine on Azure using Terraform. Along the way, we’ll learn how to manage resource dependencies effectively, making our infrastructure provisioning process smoother than ever. Get ready for a thrilling ride filled with hands-on learning and plenty of fun! ๐ŸŽข

Resource Dependencies and Terraform ๐Ÿงฉ

Creating a Windows VM on Azure involves more than just spinning up the virtual machine itself. We need to lay the groundwork by creating prerequisite resources such as a resource group, a Virtual Network, a Subnet, and a Network Interface card. Each of these resources depends on the previous one, forming a chain of dependencies.

Terraform Creating a VM figuring out dependencies

Managing resource dependencies is crucial in infrastructure provisioning because it ensures that resources are created in the correct order and that all necessary components are in place before dependent resources are provisioned. Terraform excels at handling these dependencies, making our lives as infrastructure engineers much easier. ๐Ÿ˜Œ

Defining the Virtual Machine Resource and Dependencies ๐Ÿ“

To create our Windows VM and its dependencies, we need to define several components in our Terraform configuration file:

a. Resource group b. Virtual network and subnet c. Network interface card d. Windows image and size

For this example, we’ll use the Windows Server 2019 Datacenter image and the Standard_D2s_v3 VM size.

Creating the Terraform Configuration File ๐Ÿ› ๏ธ

Let’s dive in and create the main.tf Terraform configuration file โ€“ our blueprint for Azure infrastructure excellence:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# Configure the Azure provider
provider "azurerm" {
  features {}
}

# Create a resource group
resource "azurerm_resource_group" "iaMachs_rg" {
  name     = "prod-iaMachs-rg" #Name of the Resource Group in Azure
  location = "Australia East" # Location for the resource group
}

# Create a virtual network within the resource group
resource "azurerm_virtual_network" "iaMachs_VNet" {
  name                = "iaMachs-VNet"
  location            = azurerm_resource_group.iaMachs_rg.location
  resource_group_name = azurerm_resource_group.iaMachs_rg.name
  address_space       = ["10.0.0.0/16"] # Address space of the virtual network
}

# Create a subnet within the virtual network
resource "azurerm_subnet" "iaMachs_sn" {
  name                 = "iaMachs-sn"
  resource_group_name  = azurerm_resource_group.iaMachs_rg.name
  virtual_network_name = azurerm_virtual_network.iaMachs_VNet.name
  address_prefixes     = ["10.0.2.0/24"] # Address space of the subnet
}

# Create a network interface and associate it with the subnet
resource "azurerm_network_interface" "iaMachs_VM_NIC" {
  name                = "iaMachs-VM-NIC"
  location            = azurerm_resource_group.iaMachs_rg.location
  resource_group_name = azurerm_resource_group.iaMachs_rg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.iaMachs_sn.id
    private_ip_address_allocation = "Dynamic" # IP address allocation method
  }
}

# Create a Windows virtual machine and associate it with the network interface
resource "azurerm_windows_virtual_machine" "iaMachs_VM" {
  name                = "iaMachs-VM"
  location            = azurerm_resource_group.iaMachs_rg.location
  resource_group_name = azurerm_resource_group.iaMachs_rg.name
  size                = "Standard_D2s_v3" # Size of the virtual machine
  admin_username      = "adminuser" # Administrator username
  admin_password      = "P@ssw0rd123!" # Administrator password
  network_interface_ids = [azurerm_network_interface.iaMachs_VM_NIC.id]

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

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2019-Datacenter" # SKU of the source image
    version   = "latest"
  }
}

๐Ÿ’ก Quick Tip: The Terraform configuration file uses the HashiCorp Configuration Language (HCL), a declarative language for defining infrastructure as code. HCL has a straightforward syntax that’s easy to read and write, making your infrastructure code more maintainable and collaborative.

Understanding the Terraform Configuration File ๐Ÿ”

Let’s take a behind-the-scenes look at how we’re orchestrating this Azure infrastructure symphony:

  1. Resource Group: We’re creating a resource group iaMachs_rg (the Terraform name), but Azure knows it as prod-iaMachs-rg. It’s located in the Australia East region and logically contains all our Azure resources.

  2. Virtual Network: Next, we’re creating a virtual network called iaMachs-VNet within the prod-iaMachs-rg resource group. We reference the resource group using resource_group_name = azurerm_resource_group.iaMachs_rg.name and set the virtual network’s location based on the resource group’s location with location = azurerm_resource_group.iaMachs_rg.location.

  3. Subnet: We’re creating a subnet called iaMachs-sn within the iaMachs-VNet virtual network. We reference the resource group and virtual network using resource_group_name = azurerm_resource_group.iaMachs_rg.name and virtual_network_name = azurerm_virtual_network.iaMachs_VNet.name, respectively.

  4. Network Interface Card: Here’s where things get interesting! We’re creating a network interface called iaMachs-VM-NIC and associating it with our iaMachs-sn subnet. We reference the resource group and subnet using resource_group_name = azurerm_resource_group.iaMachs_rg.name and subnet_id = azurerm_subnet.iaMachs_sn.id, respectively.

  5. Windows Virtual Machine: Finally, the star of the show โ€“ our Windows VM called iaMachs-VM! We associate it with our iaMachs-VM-NIC network interface, referencing the resource group and network interface using resource_group_name = azurerm_resource_group.iaMachs_rg.name and network_interface_ids = [azurerm_network_interface.iaMachs_VM_NIC.id], respectively.

By using these references, Terraform understands our resource dependencies and correctly sequences the creation, update, or deletion for a successful Azure Windows VM deployment. ๐ŸŽ‰

Initializing and Applying the Terraform Configuration ๐Ÿš€

Alright, folks, it’s showtime! We’ve got our configuration file ready, so let’s bring our Virtual Machine to life on Azure:

1
2
terraform init
terraform plan

Terraform will give us a sneak peek of what it’s about to do before applying the configuration. You’ll see an output similar to this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
PS C:\Users\AMuhi> terraform plan
Terraform will perform the following actions:

# azurerm_network_interface.iaMachs_VM_NIC will be created
+ resource "azurerm_network_interface" "iaMachs_VM_NIC" {
    + applied_dns_servers           = (known after apply)
    + dns_servers                   = (known after apply)
    + enable_accelerated_networking = false
    + enable_ip_forwarding          = false
    + id                            = (known after apply)
    + location                      = "australiaeast"
    + name                          = "iaMachs-VM-NIC"
    + resource_group_name           = "iaMachs_rg"

# azurerm_resource_group.iaMachs_rg will be created
+ resource "azurerm_resource_group" "iaMachs_rg" {
    + id       = (known after apply)
    + location = "australiaeast"
    + name     = "iaMachs-rg"

# azurerm_subnet.iaMachs_sn will be created
+ resource "azurerm_subnet" "iaMachs_sn" {
    + address_prefixes                               = [
        + "10.0.2.0/24",
    ]
    + id                                             = (known after apply)
    + name                                           = "iaMachs-sn"
    + resource_group_name                            = "iaMachs_rg"
    + virtual_network_name                           = "iaMachs_VNet"

# azurerm_virtual_network.iaMachs_VNet will be created
+ resource "azurerm_virtual_network" "iaMachs_VNet" {
    + address_space       = [
        + "10.0.0.0/16",
    ]
    + dns_servers         = (known after apply)
    + id                  = (known after apply)
    + location            = "australiaeast"
    + name                = "iaMachs-VNet"
    + resource_group_name = "iaMachs_rg"

# azurerm_windows_virtual_machine.iaMachs_VM will be created
+ resource "azurerm_windows_virtual_machine" "iaMachs_VM" {
    + admin_password                                         = (sensitive value)
    + admin_username                                         = "adminuser"
    + allow_extension_operations                             = true
    + bypass_platform_safety_checks_on_user_schedule_enabled = false
    + id                                                     = (known after apply)
    + location                                               = "australiaeast"
    + name                                                   = "iaMachs-VM"
    + resource_group_name                                    = "iaMachs_rg"

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

๐Ÿ’ก Pro Tip: Always review the terraform plan output carefully before proceeding with the apply command. This helps you catch any unintended changes and ensures that your infrastructure will be provisioned as expected.

The resource order displayed doesn’t always reflect the actual creation sequence. Terraform smartly identifies dependencies from our configuration file to determine the creation order:

  1. azurerm_resource_group.iaMachs_rg
  2. azurerm_virtual_network.iaMachs_VNet
  3. azurerm_subnet.iaMachs_sn
  4. azurerm_network_interface.iaMachs_VM_NIC
  5. azurerm_windows_virtual_machine.iaMachs_VM

Creating the Virtual Machine on Azure ๐Ÿ–ฅ๏ธ

Now that we’ve reviewed the Terraform plan output, let’s bring our resources to life with the terraform apply command:

1
terraform apply

Terraform will ask you to confirm that you want to create the specified resources. Type yes and hit enter to proceed:

1
2
3
4
5
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

After confirming, Terraform will create the resources in the correct order based on their dependencies. Once the process is complete, you will see an output similar to the following:

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

Your Windows VM and its associated resources have now been successfully created on Azure using Terraform. ๐ŸŽ‰

Verifying the Virtual Machine in the Azure Portal โœ…

Let’s make sure our Virtual Machine is up and running by checking it out in the Azure Portal:

  1. Log in to the Azure Portal.
  2. Navigate to the “Virtual machines” section in the left-hand menu or search for it in the search bar at the top.
  3. You should see the newly created Virtual Machine iaMachs-VM proudly displayed in the list of VMs. ๐Ÿฅณ

Create a VM on Azure Using Terraform

As you can see in the screenshot, our Virtual Machine iaMachs-VM is happily residing in the resource group prod-iaMachs-rg and connected to the Virtual Network and Subnet iaMachs-VNet/iaMachs-sn. This confirms that our Terraform configuration has been applied successfully, and all our resources have been created exactly as intended. ๐Ÿ’ช

Cleaning Up Resources ๐Ÿงน

Alright, folks, the show’s over, and it’s time to clean up the resources created by Terraform. It’s a good practice to clean up unused resources to avoid unnecessary Azure costs. You can do this by using the terraform destroy command.

  1. Make sure you are in the same directory where you ran the terraform apply command.
  2. Run the following command to destroy all the resources created by Terraform:
1
terraform destroy

Terraform will ask you to confirm that you want to destroy the resources. Type yes and hit enter to proceed.

Once the process is complete, you will see an output similar to the following:

1
Destroy complete! Resources: 5 destroyed.

All the resources we created โ€“ the Virtual Machine, Virtual Network, Subnet, Network Interface, and Resource Group โ€“ have been successfully deleted from your Azure account, leaving you with a clean slate for your next Azure adventure. ๐Ÿ˜„

Conclusion ๐ŸŽ‰

Wow, what a journey! In this article, we walked through the process of creating a Windows Virtual Machine on Azure using Terraform while managing resource dependencies like pros. We learned how to:

  • Define resources and their dependencies in a Terraform configuration file ๐Ÿ“
  • Initialize and apply Terraform configurations to create resources on Azure ๐Ÿš€
  • Verify the created resources in the Azure Portal โœ…
  • Clean up resources using the terraform destroy command ๐Ÿงน

I hope you found this article helpful and informative. If you have any questions or want to share your own Terraform and Azure adventures, feel free to leave a comment below. ๐Ÿ’ฌ

Stay tuned for more exciting Terraform and Azure content! Until then, happy coding, and keep exploring the amazing world of infrastructure as code! ๐Ÿ˜Š๐ŸŒŸ