Microsoft offers the ability to create a direct, private connection between Azure data centers and infrastructure located on-premises or in a colocation with Azure ExpressRoute. ExpressRoute offers a network route for your connection to Azure data centers that connects directly and does not traverse the public Internet. The ExpressRoute connection also offers a faster speed, lower latency, and higher reliability connection than a typical Internet connection would.

These connections are purchased through a Service Provider that provide the direct connection. When an Azure ExpressRoute connection is being setup, the connection is purchased from a Service Provider, then the Azure ExpressRoute Circuit resource needs to be deployed into your Azure subscription and connected by the Service Provider to activate it.

In this article, we’ll take a look at the Terraform code using the azurerm Provider to deploy an Azure ExpressRoute Circuit with Azure Private Peering that is connected to a Virtual Network. This setup will enable on-premises resources to have a network route through the Azure ExpressRoute connection to resources within Microsoft Azure.



Azure ExpressRoute Resources

The Azure ExpressRoute circuit resource is the specific resource in Microsoft Azure for setting up an Azure ExpressRoute connection with a Service Provider. However, this alone wont get everything configured to use the ExpressRoute connection. Setting up an ExpressRoute Peeing is needed to configure the connection from on-premises to Azure resources. Also, to connect at a networking level to resources connected to an Azure Virtual Network (VNet) then an Azure Virtual Network Gateway must be deployed and connected to the ExpressRoute as well.

To deploy and configure this Azure ExpressRoute, there are a few Azure resources necessary:

  • Azure ExpressRoute circuit – This is the Azure ExpressRoute connection.
  • Azure Virtual Network – This is the VNet in Azure that will be connected to on-premises through the ExpressRoute connection.
  • Azure Virtual Network Gateway – This is the VNet Gateway that connects the ExpressRoute circuit and VNet together.
  • Azure Public IP – This is the Azure Public IP that is required for the VNet Gateway.
Terraform: Deploy Azure ExpressRoute Circuit with VNet Gateway 3
Image: List of Azure resources needed for ExpressRoute

ExpressRoute Deployment Terraform Code

Before we look at all the Azure resources and their Terraform code to get this Azure ExpressRoute circuit and VNet Gateway deployed, the proceeding Terraform examples will require the following local variables and azure_resource_group to be deployed:

locals {
    # Azure region to deploy to
    azure_region = "eastus"

    # define the Azure resource names
    resource_name_prefix= "E1-B59-PRD-NET" # {region}-{org}-{env}-{app}
}

# The Azure Resource group for all the resources to reside
resource azurerm_resource_group "rg" {
    name     = "${local.resource_name_prefix}-rg"
    location = local.azure_region
}

NOTE: This article uses an Azure resource naming convention of {region}-{org}-{env}-{app}-{type} This enables all the Azure resources to have a unique name and be organized with a naming convention that keeps all the resources named similar. You can learn more about coming up with a naming convention for your Azure resources in the “Azure Resource Naming Conventions and Best Practices” article here on Build5Nines.

Azure ExpressRoute Circuit

To deploy the Azure ExpressRoute itself, the azurerm_express_route_circuit resource needs to be defined within the Terraform code. This resource will need to have the service_provider_name attribute set to the specific name Azure ExpressRoute expects for the Service Provider you are purchasing the ExpressRoute connection from. You will also need to set the peering_location correctly to the location of the ExpressRoute Service Provider for your connection. The peering_location is not an Azure Region, but the location for the ExpressRoute Service Providers network exchange.

# Azure ExpressRoute Circuit
resource azurerm_express_route_circuit "express_route" {
    name                  = "${local.resource_name_prefix}-erc"
    resource_group_name   = azurerm_resource_group.rg.name
    location              = azurerm_resource_group.rg.location

    # https://docs.microsoft.com/en-us/azure/expressroute/expressroute-locations-providers
    service_provider_name = "Equinix"
    peering_location      = "Washington DC"
    bandwidth_in_mbps     = 1000

    sku {
        tier   = "Standard"  
        family = "MeteredData" 
    }
}

Once, the Azure ExpressRoute circuit is deployed to your Azure Subscription, you will need to grab the Service key from Azure and give it to the Service Provider so they can use it to finish the provisioning of the ExpressRoute circuit. This Service key is easily accessible within the Azure Portal.

Terraform: Deploy Azure ExpressRoute Circuit with VNet Gateway 4
Screenshot: Azure Portal showing ExpressRoute Circuit with Service Key highlighted

Azure Private Peering needs be configured to enable connections to Azure resources through the Azure ExpressRoute circuit. The azurerm_express_route_circuit_peering resource is deployed to setup the peerings on the ExpressRoute circuit. The following is a simple example that configured Azure Private Peering on the ExpressRoute circuit:

# Azure ExpressRoute Private Peering
resource azurerm_express_route_circuit_peering "express_route_peering" {
    resource_group_name           = azurerm_resource_group.rg.name

    express_route_circuit_name    = azurerm_express_route_circuit.express_route.name

    peering_type                  = "AzurePrivatePeering"
    primary_peer_address_prefix   = "10.0.0.0/30"
    secondary_peer_address_prefix = "10.0.0.0/30"
    vlan_id                       = 100
}

Be sure to configure the correct IP Address prefixes necessary for your organizations networking environment.

Azure Virtual Network and Subnet

Before the Azure Virtual Network Gateway can be deployed and connected to the Azure ExpressRoute circuit, there will need to be an Azure Virtual Network (VNet) resource (azurerm_virtual_network) to be deployed with a GatewaySubnet subnet.

# Azure Virtual Network
resource azurerm_virtual_network "virtual_network" {
    name                = "${local.resource_name_prefix}-vnet"
    location            = azurerm_resource_group.rg.location
    resource_group_name = azurerm_resource_group.rg.name

    address_space = ["172.16.0.0/12"]
}

# GatewaySubnet within the Virtual Network
resource azurerm_subnet "gateway_subnet" {
    name                 = "GatewaySubnet"
    resource_group_name = azurerm_resource_group.rg.name

    virtual_network_name = azurerm_virtual_network.virtual_network.name
    address_prefixes     = ["172.16.0.0/24"]

    enforce_private_link_endpoint_network_policies = true
}

Be sure to configure the correct IP Address address space on the VNet and address prefix on the Subnet for your organization.

The GatewaySubnet is the Subnet within the Azure Virtual Network that is configured with the IP Address range for which the IP Address of the Azure Virtual Network Gateway will be granted. This subnet must be named exactly GatewaySubnet and cannot be named differently.

Public IP Address for VNet Gateway

Another item before the Virtual Network Gateway can be deployed is an Azure Public IP address resource (azurerm_public_ip) that will be assigned to the Azure Virtual Network Gateway.

The following is the basic Terraform code to deploy the Azure Public IP address resource needed:

# Azure Public IP Address for the VNet Gateway
resource azurerm_public_ip "vnet_gateway_public_ip" {
    name                  = "${local.resource_name_prefix}-vgw-pip"
    resource_group_name   = azurerm_resource_group.rg.name
    location              = azurerm_resource_group.rg.location

    sku               = "Basic"
    allocation_method = "Dynamic"
}

Azure Virtual Network Gateway

An Azure Virtual Network Gateway resource (azurerm_virtual_network_gateway) will be deployed to make the networking connection between the Azure ExpressRoute circuit and the Azure Virtual Network. This Virtual Network Gateway will be configured with the type set to ExpressRoute since this Gateway will be connected to an Azure ExpressRoute circuit.

The following is the basic code to deploy the Azure Virtual Network Gateway:

# Azure Virtual Network Gateway
resource azurerm_virtual_network_gateway "virtual_network_gateway" {
    name                = "${local.resource_name_prefix}-vgw"
    location            = azurerm_resource_group.rg.location
    resource_group_name = azurerm_resource_group.rg.name

    type     = "ExpressRoute"
    vpn_type = "PolicyBased"

    sku           = "HighPerformance"
    active_active = false
    enable_bgp    = false

    ip_configuration {
        name                          = "default"
        private_ip_address_allocation = "Dynamic"
        subnet_id                     = azurerm_subnet.gateway_subnet.id
        public_ip_address_id          = azurerm_public_ip.vnet_gateway_public_ip.id
    }
}

The ip_configuration of the Virtual Network Gateway in the previous code configures the Virtual Network Gateway to use the Public IP address that was previously deployed, as well as the GatewaySubnet subnet within the VNet that was deployed.

The Virtual Network Gateway isn’t configured itself with the Azure ExpressRoute circuit to connect to. For this, an Azure Virtual Network Gateway Connection resource (azurerm_virutal_network_gateway_connection) needs to be deployed to setup the connection between the Azure ExpressRoute circuit and the Virtual Network Gateway.

The following is the basic code to deploy the Azure Virtual Network Gateway Connection:

# Azure Virtual Network Gateway Connection to Express Route
resource azurerm_virtual_network_gateway_connection "virtual_network_gateway_connection" {
    name                = "${local.resource_name_prefix}-vgw-con"
    location            = azurerm_resource_group.rg.location
    resource_group_name = azurerm_resource_group.rg.name

    type                            = "ExpressRoute"
    virtual_network_gateway_id      = azurerm_virtual_network_gateway.virtual_network_gateway.id
    express_route_circuit_id        = azurerm_express_route_circuit.express_route.id
}

The Build5Nines: Terraform Quickstart Templates open source project contains a full source code example for deploying Azure ExpressRoute with a Virtual Network Gateway that can be referenced here: https://github.com/Build5Nines/terraform-quickstart-templates/tree/main/microsoft-azure/workloads/azure-express-route-with-vnet-gateway

Microsoft MVP

Chris Pietschmann is a Microsoft MVP (Azure & IoT) and HashiCorp Ambassador (2021) with 20+ years of experience designing and building Cloud & Enterprise systems. He has worked with companies of all sizes from startups to Fortune 100. He is also a Microsoft Certified Azure Solutions Architect and developer, a Microsoft Certified Trainer (MCT), and Cloud Advocate. He has a passion for technology and sharing what he learns with others to help enable them to learn faster and be more productive.