Azure Virtual Network Topology Orchestration via Terraform

Azure Virtual Networks (VNets) serve as the fundamental cornerstone of private networking within the Microsoft Azure cloud ecosystem. They provide the essential logical isolation required to separate cloud resources from the public internet, enabling architects to exert granular control over traffic flow through the strategic implementation of subnets and network security groups. By leveraging Terraform, an infrastructure-as-code tool, organizations can move away from manual portal configurations toward a model of defined, versioned, and replicable network topologies. This shift is critical because the architectural decisions made during the initial network design—specifically the allocation of address spaces—have long-term implications. Poor planning can lead to overlapping IP ranges, which creates catastrophic blockers for future VNet peering or connections to on-premises environments, necessitating costly and time-consuming readdressing or workload migration projects.

Core Prerequisites and Environment Initialization

Before initiating the deployment of virtual networks and subnets, a specific set of technical prerequisites must be met to ensure the Terraform provider can communicate effectively with the Azure Resource Manager (ARM) API.

The software requirements include:

  • Terraform version 1.3 or later to ensure compatibility with the latest Azure Resource Manager features.
  • An active Azure subscription and the associated subscription ID.
  • The Azure CLI installed on the local machine, with the user having performed the az login command to authenticate the session.
  • A designated resource group, which can either be pre-existing or created as part of the Terraform execution.

The first step in any Terraform project is the provider configuration. This block tells Terraform which plugins are required to interact with the target cloud environment. For Azure, the azurerm provider is utilized.

```terraform
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}

variable "subscription_id" {
description = "Azure subscription ID to deploy into"
type = string
}

provider "azurerm" {
features {}
subscriptionid = var.subscriptionid
}
```

The features {} block is a mandatory requirement for the Azure provider; it allows the provider to handle specific Azure resource behaviors. By defining the subscription_id as a variable, the configuration remains portable across different environments such as development, staging, and production.

Establishing the Virtual Network Foundation

The azurerm_virtual_network resource is the primary container for all networking components. It defines the overall IP address space that will be partitioned into smaller subnets.

A production-ready virtual network requires a resource group for logical organization and a clearly defined address space. In a typical enterprise scenario, a /16 CIDR block (such as 10.0.0.0/16) is used to provide a vast amount of IP addresses that can be subdivided.

```terraform

Resource group for networking

resource "azurermresourcegroup" "networking" {
name = "rg-networking-prod-eus"
location = "East Use"
tags = {
Environment = "production"
Purpose = "networking"
}
}

Virtual Network

resource "azurermvirtualnetwork" "main" {
name = "vnet-main-prod-eus"
location = azurermresourcegroup.networking.location
resourcegroupname = azurermresourcegroup.networking.name
addressspace = ["10.0.0.0/16"]
dns
servers = []
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
```

The impact of the address_space definition cannot be overstated. If an organization intends to use a hub-and-spoke architecture or connect to a local data center via VPN, these address spaces must not overlap. The dns_servers attribute is left as an empty list in the example above, which defaults the network to use Azure-provided DNS services. However, this can be customized for organizations utilizing custom DNS forwarders.

Tiered Subnet Implementation and Segmentation

Subnets are the mechanism used to slice the larger Virtual Network into smaller, manageable segments. This segmentation is vital for security, as it allows the application of different security policies to different tiers of an application.

Web Tier Subnet Configuration

The web tier is typically the entry point for traffic. By creating a dedicated subnet, administrators can isolate public-facing resources from the internal business logic.

```terraform

Subnet for web tier

resource "azurermsubnet" "web" {
name = "snet-web"
resource
groupname = azurermresourcegroup.networking.name
virtual
networkname = azurermvirtualnetwork.main.name
address
prefixes = ["10.0.1.0/24"]
service_endpoints = ["Microsoft.Sql", "Microsoft.Storage"]
}
```

The service_endpoints attribute is used here to optimize security and performance. By enabling endpoints for Microsoft.Sql and Microsoft.Storage, traffic to these Azure services remains within the Azure backbone network rather than traversing the public internet.

Application Tier Subnet Configuration

The application tier houses the core processing logic and should be more restricted than the web tier.

```terraform

Subnet for application tier

resource "azurermsubnet" "app" {
name = "snet-app"
resource
groupname = azurermresourcegroup.networking.name
virtual
networkname = azurermvirtualnetwork.main.name
address
prefixes = ["10.0.2.0/24"]
service_endpoints = ["Microsoft.Sql", "Microsoft.KeyVault"]
}
```

The use of Microsoft.KeyVault as a service endpoint ensures that the application can retrieve secrets and certificates securely without exposing the request to the open web.

Database Tier and Service Delegation

The database tier requires the highest level of isolation. In some scenarios, Azure services require a "delegated subnet," which means the subnet is reserved exclusively for a specific Azure service, giving that service total control over the subnet's networking.

```terraform

Subnet for database tier

resource "azurermsubnet" "db" {
name = "snet-db"
resource
groupname = azurermresourcegroup.networking.name
virtual
networkname = azurermvirtualnetwork.main.name
address
prefixes = ["10.0.3.0/24"]

delegation {
name = "mysql-delegation"
service_delegation {
name = "Microsoft.DBforMySQL/flexibleServers"
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
}
}
}
```

The delegation block is critical for deploying resources like Azure Database for MySQL flexible servers. Without this delegation, the service cannot "join" the subnet, and the deployment will fail.

Advanced Dynamic Subnet Management

Defining subnets as individual resources can lead to repetitive code and maintenance burdens as the network grows. To mitigate this, Terraform's for_each meta-argument can be employed to create subnets dynamically based on a variable map.

Defining the Subnet Map

A map allows the architect to define all subnet properties—including address prefixes, service endpoints, and delegations—in a single data structure.

terraform variable "subnets" { description = "Map of subnet configurations" type = map(object({ address_prefix = string service_endpoints = list(string) delegation = optional(object({ name = string service = string actions = list(string) })) })) default = { web = { address_prefix = "10.0.1.0/24" service_endpoints = ["Microsoft.Sql", "Microsoft.Storage"] }, app = { address_prefix = "10.0.2.0/24" service_endpoints = ["Microsoft.Sql", "Microsoft.KeyVault"] } } }

Dynamic Implementation

By iterating over this map, Terraform creates only the subnets defined in the variable, making the infrastructure highly scalable. This approach is recommended for hub-spoke architectures where dozens of spoke VNets and subnets may be required.

Deployment Lifecycle and Verification

The process of deploying these resources follows a strict operational sequence to ensure consistency and prevent configuration drift.

The operational workflow is as follows:

  • Initialization: Running terraform init downloads the necessary Azure provider plugins and initializes the backend state.
  • Planning: Running terraform plan is mandatory. This step allows the engineer to review the execution plan and verify that only the intended resources are being created, modified, or destroyed.
  • Application: Running terraform apply executes the plan. Terraform automatically handles the dependency graph, ensuring the Resource Group is created before the VNet, and the VNet before the Subnets.
  • Verification: Post-deployment, the resources must be verified for operational health.

Observability and Network Health Monitoring

Networking is not a "set and forget" task. Once the VNets and subnets are deployed, comprehensive observability must be implemented to detect failures early.

Azure Monitor and Log Analytics

Integration with Azure Monitor and Log Analytics is essential for cloud observability. This allows for the tracking of network flow logs and the configuration of alerts based on specific network events.

The observability stack includes:

  • Azure Monitor: Used for collecting and analyzing telemetry data.
  • Log Analytics: Used for querying network logs to identify bottlenecks or security threats.
  • Alerts: Configured to notify administrators when network health thresholds are breached.

VNet Connectivity Tracking

Tools like OneUptime can be integrated to track specific networking health indicators. Monitoring the following metrics is crucial for maintaining high availability:

  • VNet Connectivity: Ensuring that resources in different subnets can communicate as expected.
  • DNS Resolution: Detecting timeouts or failures in DNS resolution which can lead to application downtime.
  • Peering Health: Monitoring the state of VNet peering to ensure that connected networks remain accessible.

Catching a peering state change or a DNS timeout early through these monitoring tools can save hours of debugging that would otherwise be required to resolve downstream service failures.

Security Integration and Architectural Patterns

A VNet and its subnets are only as secure as the rules governing them. While the subnet provides a logical boundary, the actual traffic control is managed via Network Security Groups (NSGs).

Network Security Groups (NSGs)

NSGs act as a virtual firewall for each subnet, allowing administrators to define inbound and outbound security rules based on source/destination IP, port, and protocol. For a fully secured environment, every subnet defined in the Terraform configuration should be associated with a corresponding NSG.

Hub-and-Spoke Architecture

For organizations with more than a few workloads, a hub-and-spoke architecture is recommended. In this pattern:

  • Hub VNet: Acts as the central point of connectivity. It typically contains shared services like Azure Firewall, VPN Gateways, and DNS servers.
  • Spoke VNets: Contain the actual application workloads (Web, App, DB tiers).
  • VNet Peering: Connects the spokes to the hub, ensuring that traffic is routed centrally and can be inspected for security purposes.

This architecture prevents the "flat network" problem where a breach in one application tier could lead to unrestricted lateral movement across the entire cloud environment.

Comparative Summary of Subnet Configurations

The following table summarizes the typical configurations for different subnet tiers within an Azure environment managed by Terraform.

Tier Purpose Recommended CIDR Key Feature Critical Service Endpoint
Web Public Entry /24 Public Access Microsoft.Storage
App Business Logic /24 Internal Isolation Microsoft.KeyVault
DB Data Storage /24 Service Delegation Microsoft.Sql
Hub Shared Services /20 Central Routing N/A

Expanded Infrastructure Ecosystem

The network foundation created via Terraform is the prerequisite for deploying higher-level Azure services. Once the VNet and subnets are established, the following components are typically integrated into the infrastructure:

  • Azure Application Gateway: Used for WAF (Web Application Firewall), SSL termination, and URL routing to direct traffic into the web subnet.
  • Azure Container Registry and Container Instances: Used for lightweight container workloads deployed within the app subnet.
  • Azure Key Vault: Used for managing secrets and certificates, accessed via service endpoints from the app subnet.
  • Private Endpoints: Used to ensure that traffic to PaaS services never leaves the virtual network, providing a higher security posture than service endpoints alone.

Conclusion

The orchestration of Azure Virtual Networks and subnets using Terraform transforms networking from a manual, error-prone process into a disciplined engineering practice. By defining the network topology as code, organizations ensure that their infrastructure is consistent across different environments and can be recovered rapidly in the event of a disaster. The strategic use of address space planning prevents the critical failure of overlapping IP ranges, while the implementation of tiered subnets and service delegations ensures that security is baked into the architecture rather than added as an afterthought.

The integration of dynamic subnet creation using for_each allows for massive scalability, supporting complex hub-and-spoke topologies that can grow alongside the business. Furthermore, the coupling of this infrastructure with Azure Monitor, Log Analytics, and third-party observability tools like OneUptime creates a resilient system where connectivity issues are detected and remediated before they impact the end-user experience. Ultimately, the investment in getting the networking foundation correct at the start—by utilizing the strict provider configurations and resource definitions outlined in this analysis—pays dividends in the form of reduced technical debt and increased operational stability.

Sources

  1. TerraformPilot
  2. OneUptime
  3. Microsoft Learn

Related Posts