Implementing an Azure Virtual Network and Subnets Configuration using Terraform Infrastructure as Code

Danushka Lakmina
5 min readFeb 13, 2023

--

In the current digital landscape, infrastructure as code (IAC) has become a critical component of managing cloud environments. To meet this demand, Terraform, a popular IAC tool, has gained widespread adoption among IT organisations. With Terraform, you can define and provision infrastructure in a simple, yet powerful, repeatable and versioned manner.

In this article, I will explore the use of Terraform to create virtual networks (VNETs) and subnets in Azure. By the end of this article, you will have a solid understanding of how Terraform can be used to provision infrastructure in Azure, allowing you to quickly and easily create your own VNETs and subnets.

Steps to create VNET

In this article, I will take you through the process of setting up a virtual network (VNET) and subnets in Azure using Terraform. Our first step will be to establish a Terraform module, referred to as the “vnet” module, which will hold the necessary Terraform configuration files to create a VNET with the proper address space.

By creating a module, I can simplify the management and maintenance of our infrastructure by being able to reuse the code for creating a VNET across multiple projects. The module will enable us to define the parameters for our VNET, such as its name, resource group, and address space, in a single location, making it easier to update and modify our infrastructure as our needs evolve.

At the conclusion of this first step, you will have established a Terraform module for creating a VNET in Azure that can be customised to suit the requirements of your own projects.

vnet.tf


resource "azurerm_virtual_network" "vnet" {
name = var.vnet_name
resource_group_name = var.resource_group
location = var.vnet_location
address_space = var.address_space
# tags = var.tags
}

resourcegroup.tf

resource "azurerm_resource_group" "rg" {
name = var.resource_group
location = var.vnet_location
}

variables.tf

variable "vnet_name" {
description = "Name of the vnet to create"
type = string
default = "acctvnet"
}


variable "address_space" {
type = list(string)
description = "The address space that is used by the virtual network."
}

variable "vnet_location" {
description = "The location of the vnet to create. Defaults to the location of the resource group."
type = string
default = null
}

variable "resource_group" {
type = string
}

With the “vnet” module created, the next step is to call it from the main Terraform configuration file, typically named “main.tf”. This file is responsible for defining the resources that Terraform will manage and the modules that it will use to create those resources.

To call the “vnet” module from the main Terraform configuration file, I will use the “module” block in Terraform. This block specifies the source of the module, the name of the module, and the input variables required by the module.

For example:

main.tf

module "vnet" {
source = "../../modules/vnet"
vnet_name = "${var.env}-${var.project}-vnet"
vnet_location = var.location
address_space = ["192.168.92.0/22", "192.168.96.0/22"]
resource_group = "${var.env}-${var.project}-vnet-rg"

}

Steps to create Subnet

With the first step of calling the “vnet” module in the main Terraform configuration file complete, the next step is to create a subnet module within the “vnet” module folder. This subnet module will contain the Terraform configuration files necessary to create subnets within the virtual network.

Just like the “vnet” module, the “subnet” module will make it easier to manage and maintain our infrastructure as code. By defining the subnets in a separate module, we can reuse the code for creating subnets across multiple projects, making it easier to manage the configuration of our subnets. The “subnet” module will allow us to define the parameters for our subnets, such as the name, address prefix, and VNET association, in a single place, making it easier to update our infrastructure as our needs change.

To call the “subnet” module from the “vnet” module, I will use the same “module” block in Terraform. This block specifies the source of the module, the name of the module, and the input variables required by the module.

For example:

subnet.tf



resource "azurerm_subnet" "subnet" {
resource_group_name = var.resource_group
virtual_network_name = var.virtual_network_name
name = var.subnet_name
address_prefixes = var.address_prefixes
service_endpoints = var.service_endpoints
delegation {
name = "delegation"
service_delegation {
name = var.service_delegation_name
actions = var.delegation_actions
}
}
}

variables.tf

variable "subnet_name" {
description = "Name of the subnet to create"
type = string
}

variable "resource_group" {
description = "Name of the resource group to be imported."
type = string
}

variable "address_prefixes" {
description = "Virtual network location"
type = list(string)
}

variable "service_endpoints" {
description = "service endpoint"
type = list(string)
}

variable "service_delegation_name" {
description = "service deligation name"
type = string
default = ""
}
variable "delegation_actions" {
description = "deligation action"
type = list(string)
default = [ "" ]
}

variable "virtual_network_name" {
description = "Virtual network name for subnet"
type = string
}

Now that I have created the “subnet” module within the “vnet” module folder, the final step is to call it from the main Terraform configuration file, “main.tf”.

To do this, I simply add another “module” block in the main Terraform configuration file and specify the source of the “subnet” module and the required input variables.

For example:

main.tf

module "subnet_storage_acc" {
source = "../../modules/vnet/subnet"
subnet_name = "${var.env}-${var.project}-subnet"
resource_group = module.vnet.resource_group_name
address_prefixes = ["192.168.92.0/24"]
service_endpoints = ["Microsoft.ServiceBus", "Microsoft.Storage", "Microsoft.Sql", "Microsoft.KeyVault"]
virtual_network_name = module.vnet.vnet_name
}

In this example, calling the “subnet” module from within the “vnet” module folder and passing in the required variables, such as the name of the subnet, the address prefix, and the Name of the virtual network.

By calling the “subnet” module from the main Terraform configuration file, Terraform will now manage the creation and configuration of both the virtual network and the subnets within the virtual network, making it easier to manage and maintain your infrastructure as code.

This article demonstrated the use of Terraform modules for creating an Azure virtual network and subnets. By organizing the Terraform code into separate modules, it becomes easier to manage and maintain the infrastructure as code. The “vnet” module contains the Terraform configuration files necessary to create the virtual network, while the “subnet” module contains the Terraform configuration files necessary to create subnets within the virtual network.

The main Terraform configuration file, “main.tf”, calls the “vnet” module, passing in the required parameters such as the virtual network name, address space, and location. The “vnet” module then calls the “subnet” module, passing in the required parameters such as the subnet name, address prefix, and VNET association. This modular approach to Terraform code makes it easier to reuse code, manage your infrastructure, and update it as needed.

In summary, using Terraform modules is a best practice for managing infrastructure as code and makes it easier to maintain and update your infrastructure. I hope this article has provided you with a good understanding of how to create an Azure virtual network and subnets using Terraform.

Thank you for taking the time to read this article. I hope it was helpful in showing you how to create an Azure virtual network and subnets using Terraform. If you have any questions or need further clarification, please feel free to reach out.

--

--

Danushka Lakmina

Skilled DevOps Engineer with 4+ years of hands-on experience supporting, automating, and optimizing mission critical deployments in AWS, leveraging config.