🌤 Introduction
In the post — Authenticating Terraform with Azure CLI and Deploying a Virtual Network and Subnet — we used Terraform to provision a Resource Group, Virtual Network (VNet), and Subnet in Azure.
In this post, we’ll go deeper into that Terraform configuration and understand how each section works.
🔁 Quick Recap – The Terraform Code
Here’s the same code snippet we used earlier for reference:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}
provider "azurerm" {
resource_provider_registrations = "none" # This is only required when the User, Service Principal, or Identity running Terraform lacks the permissions to register Azure Resource Providers.
features {}
#Uncomment the line and hardcode subscription id if you are not using ARM_SUBSCRIPTION_ID environment variable in next step
#subscription_id = "your-subscription-id"
}
# Option 1: Create a new Resource Group
resource "azurerm_resource_group" "rg" {
name = "tfcli-rg"
location = "eastus"
}
# Option 2: Use an existing Resource Group (if provided)
# data "azurerm_resource_group" "rg" {
# name = "student-assigned-rg-name"
# }
# Create a Virtual Network
resource "azurerm_virtual_network" "vnet" {
name = "tfcli-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
# Create a Subnet inside the Virtual Network
resource "azurerm_subnet" "subnet" {
name = "tfcli-subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
}
🧱 Section 1: Terraform Block
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}
This is the Terraform configuration block. It tells Terraform which providers to use.
required_providersdeclares the provider dependencies for your project.azurermmeans we’re using the Azure Resource Manager provider, which lets Terraform talk to Azure.- The
version = "~> 4.0"ensures we use version 4.x (any compatible minor version, e.g., 4.3.1).
In simple terms — this section tells Terraform:
“You’ll be working with Azure, using the AzureRM provider version 4.”
🔑 Section 2: Provider Configuration
provider "azurerm" {
resource_provider_registrations = "none"
features {}
# subscription_id = "your-subscription-id"
}
This block configures how Terraform connects to Azure.
- The
providerblock defines settings for the AzureRM provider. resource_provider_registrations = "none"tells Terraform not to automatically register Azure resource providers (useful when permissions are limited).features {}is required — even if empty — to enable the AzureRM provider.- The
subscription_idline is commented out because we’re using environment variables instead of hardcoding credentials. It is added just to show where it needs to be present if needed.
📦 Section 3: Resource Group
Terraform offers two options for handling Resource Groups — depending on whether you want to create a new one or use an existing one. In our config file, the code to create one (Option 1) was used, and the code to use an existing one (Option 2) was commented.
If you were provided a Resource Group, you would comment Option 1 and uncomment Option 2.
Option 1: Create a New Resource Group
resource "azurerm_resource_group" "rg" {
name = "tfcli-rg"
location = "eastus"
}
This creates a new Resource Group named tfcli-rg in the eastus region.
Terraform manages its entire lifecycle — it can create, update, and destroy it when needed.
Option 2: Use an Existing Resource Group
# Option 2: Use an existing Resource Group (if provided)
# data "azurerm_resource_group" "rg" {
# name = "student-assigned-rg-name"
# }
If your admin, trainer, or organization has already assigned you a Resource Group (for example, rg-student-john), you should not create a new one. Instead, use a data block to reference that existing group.
Explanation:
datatells Terraform to read existing infrastructure instead of creating new resources.azurerm_resource_groupspecifies the type of data source.- The
nameparameter identifies the existing Resource Group in Azure.
You can then reference it in other resources like this:
location = data.azurerm_resource_group.rg.location
resource_group_name = data.azurerm_resource_group.rg.name
💡 This method is perfect for shared environments, classroom labs, or restricted Azure accounts where you cannot create Resource Groups yourself.
🧭 When to Use Each Option
| Scenario | Recommended Option | Description |
|---|---|---|
| You’re learning or testing in your own Azure account | Option 1 | Let Terraform create a new Resource Group. |
| You’re working with a pre-assigned Resource Group | Option 2 | Reference the existing one using a data block. |
🌐 Section 4: Virtual Network (VNet)
resource "azurerm_virtual_network" "vnet" {
name = "tfcli-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
This creates a Virtual Network inside the Resource Group.
Here’s what each line does:
name— defines the name of your virtual network (tfcli-vnet).address_space— defines the IP address range (CIDR block) for your network.location— references the location from the resource group.resource_group_name— references the name of the resource group.
Notice how we’re not hardcoding values like the region or RG name.
Instead, we’re using references:
azurerm_resource_group.rg.location
azurerm_resource_group.rg.name
This ensures that if the resource group name or location changes, the VNet automatically adapts.
🌐 Section 5: Subnet
resource "azurerm_subnet" "subnet" {
name = "tfcli-subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
}
Finally, we define a Subnet within the VNet.
Explanation:
name— defines the subnet name (tfcli-subnet).resource_group_name— points to the same RG as before.virtual_network_name— links this subnet to the VNet we just created.address_prefixes— defines the subnet’s IP range.
This means:
Your VNet has an overall range of 10.0.0.0/16, and within that, this subnet uses 10.0.1.0/24.
🧠 Summary
In this post, we dissected the Terraform configuration that:
- Creates a Resource Group
- Provisions a Virtual Network within that group
- Defines a Subnet inside the VNet
Each section builds upon the previous one, showing how Terraform enables declarative, reusable, and modular infrastructure.