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