Back to Blog

Designing Virtual Networks in Azure with Terraform

Complete tutorial about azurerm_virtual_network in Terraform. Learn VNets, subnets, address spaces, NSGs, peering.

Designing Virtual Networks in Azure with Terraform

Designing Virtual Networks in Azure with Terraform

Introduction

Azure Virtual Networks (VNets) serve as the foundation for network connectivity in Microsoft Azure. They allow Azure resources to communicate with each other, the internet, and on-premises networks securely. VNets are comparable to traditional networks in on-premises data centers, but they leverage Azure's scalability, availability, and security features. Using Infrastructure as Code (IaC) with tools like Terraform brings several benefits, including consistency, version control, and ease of deployment, which are essential for managing complex infrastructures.

Main use cases for Azure VNets include:

  • Isolating network traffic for different applications or environments (development, testing, production).
  • Connecting virtual machines (VMs) and other resources within the same network securely.
  • Creating hybrid networks that integrate on-premises infrastructure with cloud resources.
  • Implementing advanced networking features, such as Network Security Groups (NSGs) for fine-grained access control.

In this tutorial, we will explore how to design and implement VNets in Azure using Terraform, focusing on key components such as subnets, address spaces, NSGs, and peering.

Prerequisites

Before you begin, ensure you have the following:

  • Terraform CLI installed (version 1.0 or later)
  • An Azure subscription (you can create a free account here)
  • Azure CLI installed and configured
  • A service principal for Terraform to access Azure resources (you can create a service principal)

Fundamental Concepts

Key Terminology

  • Virtual Network (VNet): A logically isolated network within Azure, allowing resources to communicate securely.
  • Subnet: A range of IP addresses within a VNet, used to segment the network for better organization and security.
  • Address Space: The range of IP addresses available to a VNet, defined in CIDR notation.
  • Network Security Group (NSG): A set of rules that allow or deny inbound and outbound network traffic to resources within a subnet or VNet.
  • Peering: A mechanism that allows VNets to connect with each other, enabling resources in different VNets to communicate seamlessly.

Resource Dependencies

When designing a VNet, you typically define the VNet first, followed by its subnets and security groups. Terraform manages the dependencies automatically.

State Management

Terraform maintains a state file that tracks your infrastructure's current state. This file should be stored securely and can be configured to use remote backends like Azure Storage for better collaboration.

Resource Syntax

The basic syntax for defining a VNet in Terraform using the azurerm_virtual_network resource is as follows:

resource "azurerm_virtual_network" "example" {
  name                = "example-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = "East US"
  resource_group_name = azurerm_resource_group.example.name
}

Arguments Table

Argument Description
name The name of the virtual network.
address_space The address space for the virtual network in CIDR notation.
location The Azure region where the virtual network will be created.
resource_group_name The name of the resource group where the VNet resides.

Practical Examples

Example 1: Create a Basic VNet

resource "azurerm_resource_group" "example" {
  name     = "example-rg"
  location = "East US"
}

resource "azurerm_virtual_network" "example" {
  name                = "example-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

Example 2: Create Subnets within a VNet

resource "azurerm_subnet" "subnet1" {
  name                 = "subnet1"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefix       = "10.0.1.0/24"
}

resource "azurerm_subnet" "subnet2" {
  name                 = "subnet2"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefix       = "10.0.2.0/24"
}

Example 3: Add a Network Security Group (NSG)

resource "azurerm_network_security_group" "example" {
  name                = "example-nsg"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  
  security_rule {
    name                       = "allow-ssh"
    priority                   = 1000
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix  = "*"
  }
}

Example 4: Associate NSG with a Subnet

resource "azurerm_subnet_network_security_group_association" "example" {
  subnet_id                 = azurerm_subnet.subnet1.id
  network_security_group_id  = azurerm_network_security_group.example.id
}

Example 5: Create VNet Peering

resource "azurerm_virtual_network_peering" "example" {
  name                          = "example-peering"
  resource_group_name           = azurerm_resource_group.example.name
  virtual_network_name          = azurerm_virtual_network.example.name
  remote_virtual_network_id     = azurerm_virtual_network.other_vnet.id
  allow_virtual_network_access   = true
}

Example 6: Create a VNet with Multiple Address Spaces

resource "azurerm_virtual_network" "example" {
  name                = "example-vnet"
  address_space       = ["10.0.0.0/16", "10.1.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

Example 7: Configure DNS Servers for the VNet

resource "azurerm_virtual_network" "example" {
  name                = "example-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  
  dns_servers = ["10.0.0.4", "10.0.0.5"]
}

Example 8: Create a VNet with Subnets and NSGs

resource "azurerm_virtual_network" "example" {
  name                = "example-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet" "subnet1" {
  name                 = "subnet1"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefix       = "10.0.1.0/24"
}

resource "azurerm_network_security_group" "example" {
  name                = "example-nsg"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet_network_security_group_association" "example" {
  subnet_id                 = azurerm_subnet.subnet1.id
  network_security_group_id  = azurerm_network_security_group.example.id
}

Real-World Use Cases

Scenario 1: Multi-Tier Application Architecture

In a multi-tier application, the application can be segmented into three VNets: a front-end VNet, a back-end VNet, and a database VNet. Each VNet can have its own set of subnets and NSGs, providing an additional layer of security.

Scenario 2: Hybrid Network Setup

An organization can set up a hub and spoke architecture, where the hub VNet connects to on-premises networks, and multiple spoke VNets connect through peering. This design isolates workloads while sharing common services such as firewalls and VPN gateways.

Scenario 3: Multi-Region Deployment

Using VNets in multiple regions allows organizations to deploy applications closer to their users while maintaining secure communication between regions. This setup can use VNet peering to enable seamless connectivity across regions.

Best Practices

  1. Address Space Planning: Always define address spaces without overlaps and leave room for future growth.
  2. Segmentation with Subnets: Use subnets to isolate different application tiers and enhance security.
  3. Implement NSGs: Always use Network Security Groups to control traffic flow to and from subnets.
  4. Use VNet Peering Wisely: Utilize peering for communication between VNets while minimizing direct connections between spokes.
  5. Document Infrastructure: Maintain clear documentation of the network architecture for easier management and troubleshooting.

Common Errors

  1. Error: "Address space overlaps with existing VNet"

    • Cause: You are trying to create a VNet with an address space that overlaps with an existing VNet.
    • Solution: Update the address space to ensure it does not overlap.
  2. Error: "Subnets cannot have overlapping address prefixes"

    • Cause: You defined subnets with overlapping address prefixes.
    • Solution: Adjust the address prefixes to ensure they are unique.
  3. Error: "Invalid network security group association"

    • Cause: The NSG does not exist or is not associated correctly.
    • Solution: Check the NSG resource and ensure it is being referenced correctly.
  4. Error: "Insufficient permissions to create resources"

    • Cause: The service principal does not have the required permissions.
    • Solution: Assign the necessary roles to the service principal in Azure.

Related Resources

Resource Description
azurerm_virtual_network Terraform resource for creating Azure Virtual Networks.
azurerm_subnet Terraform resource for creating subnets within a VNet.
azurerm_network_security_group Terraform resource for creating NSGs that manage inbound and outbound traffic.
azurerm_virtual_network_peering Terraform resource for creating peering between VNets.

Complete Infrastructure Script

Here's a complete Terraform script that sets up a VNet, subnets, and an NSG:

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "example" {
  name     = "example-rg"
  location = "East US"
}

resource "azurerm_virtual_network" "example" {
  name                = "example-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet" "subnet1" {
  name                 = "subnet1"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefix       = "10.0.1.0/24"
}

resource "azurerm_network_security_group" "example" {
  name                = "example-nsg"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet_network_security_group_association" "example" {
  subnet_id                 = azurerm_subnet.subnet1.id
  network_security_group_id  = azurerm_network_security_group.example.id
}

Conclusion

In this tutorial, we have explored how to design and implement Azure VNets using Terraform. By leveraging VNets, subnets, NSGs, and peering, you can create robust, secure, and scalable network architectures in Azure.

Next steps may involve exploring further networking features in Azure or integrating VNets with other Azure services.

References